#![allow(dead_code)]
#![allow(non_camel_case_types)]
use std::fmt;
use std::io::{Read, Write};
use filetime;
use num_derive::{FromPrimitive, ToPrimitive};
use crate::xdr::{DeserializeEnum, SerializeEnum};
use crate::{DeserializeStruct, SerializeStruct};
use super::{deserialize, Deserialize, Serialize};
pub mod dir;
pub mod file;
pub mod fs;
pub const PROGRAM: u32 = 100_003;
pub const VERSION: u32 = 3;
pub const NFS3_FHSIZE: u32 = 64;
pub const NFS3_COOKIEVERFSIZE: u32 = 8;
pub const NFS3_CREATEVERFSIZE: u32 = 8;
pub const NFS3_WRITEVERFSIZE: u32 = 8;
#[allow(non_camel_case_types)]
#[derive(Default, Clone)]
pub struct nfsstring(pub Vec<u8>);
impl nfsstring {
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
impl From<Vec<u8>> for nfsstring {
fn from(value: Vec<u8>) -> Self {
Self(value)
}
}
impl From<&[u8]> for nfsstring {
fn from(value: &[u8]) -> Self {
Self(value.into())
}
}
impl AsRef<[u8]> for nfsstring {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl std::ops::Deref for nfsstring {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl fmt::Debug for nfsstring {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", String::from_utf8_lossy(&self.0))
}
}
impl fmt::Display for nfsstring {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", String::from_utf8_lossy(&self.0))
}
}
impl Serialize for nfsstring {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
self.0.serialize(dest)
}
}
impl Deserialize for nfsstring {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
self.0.deserialize(src)
}
}
#[allow(non_camel_case_types)]
#[allow(clippy::upper_case_acronyms)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, ToPrimitive)]
pub enum NFSProgram {
NFSPROC3_NULL = 0,
NFSPROC3_GETATTR = 1,
NFSPROC3_SETATTR = 2,
NFSPROC3_LOOKUP = 3,
NFSPROC3_ACCESS = 4,
NFSPROC3_READLINK = 5,
NFSPROC3_READ = 6,
NFSPROC3_WRITE = 7,
NFSPROC3_CREATE = 8,
NFSPROC3_MKDIR = 9,
NFSPROC3_SYMLINK = 10,
NFSPROC3_MKNOD = 11,
NFSPROC3_REMOVE = 12,
NFSPROC3_RMDIR = 13,
NFSPROC3_RENAME = 14,
NFSPROC3_LINK = 15,
NFSPROC3_READDIR = 16,
NFSPROC3_READDIRPLUS = 17,
NFSPROC3_FSSTAT = 18,
NFSPROC3_FSINFO = 19,
NFSPROC3_PATHCONF = 20,
NFSPROC3_COMMIT = 21,
INVALID = 22,
}
pub type opaque = u8;
pub type filename3 = nfsstring;
pub type nfspath3 = nfsstring;
pub type fileid3 = u64;
pub type cookie3 = u64;
pub type cookieverf3 = [opaque; NFS3_COOKIEVERFSIZE as usize];
pub type createverf3 = [opaque; NFS3_CREATEVERFSIZE as usize];
pub type writeverf3 = [opaque; NFS3_WRITEVERFSIZE as usize];
pub type uid3 = u32;
pub type gid3 = u32;
pub type size3 = u64;
pub type offset3 = u64;
pub type mode3 = u32;
pub type count3 = u32;
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, ToPrimitive)]
#[repr(u32)]
pub enum nfsstat3 {
NFS3_OK = 0,
NFS3ERR_PERM = 1,
NFS3ERR_NOENT = 2,
NFS3ERR_IO = 5,
NFS3ERR_NXIO = 6,
NFS3ERR_ACCES = 13,
NFS3ERR_EXIST = 17,
NFS3ERR_XDEV = 18,
NFS3ERR_NODEV = 19,
NFS3ERR_NOTDIR = 20,
NFS3ERR_ISDIR = 21,
NFS3ERR_INVAL = 22,
NFS3ERR_FBIG = 27,
NFS3ERR_NOSPC = 28,
NFS3ERR_ROFS = 30,
NFS3ERR_MLINK = 31,
NFS3ERR_NAMETOOLONG = 63,
NFS3ERR_NOTEMPTY = 66,
NFS3ERR_DQUOT = 69,
NFS3ERR_STALE = 70,
NFS3ERR_REMOTE = 71,
NFS3ERR_BADHANDLE = 10001,
NFS3ERR_NOT_SYNC = 10002,
NFS3ERR_BAD_COOKIE = 10003,
NFS3ERR_NOTSUPP = 10004,
NFS3ERR_TOOSMALL = 10005,
NFS3ERR_SERVERFAULT = 10006,
NFS3ERR_BADTYPE = 10007,
NFS3ERR_JUKEBOX = 10008,
}
impl SerializeEnum for nfsstat3 {}
impl DeserializeEnum for nfsstat3 {}
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Default, FromPrimitive, ToPrimitive)]
#[repr(u32)]
pub enum ftype3 {
#[default]
NF3REG = 1,
NF3DIR = 2,
NF3BLK = 3,
NF3CHR = 4,
NF3LNK = 5,
NF3SOCK = 6,
NF3FIFO = 7,
}
impl SerializeEnum for ftype3 {}
impl DeserializeEnum for ftype3 {}
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Default)]
pub struct specdata3 {
pub specdata1: u32,
pub specdata2: u32,
}
DeserializeStruct!(specdata3, specdata1, specdata2);
SerializeStruct!(specdata3, specdata1, specdata2);
#[allow(non_camel_case_types)]
#[derive(Clone, Debug, Default)]
pub struct nfs_fh3 {
pub data: Vec<u8>,
}
DeserializeStruct!(nfs_fh3, data);
SerializeStruct!(nfs_fh3, data);
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Default)]
pub struct nfstime3 {
pub seconds: u32,
pub nseconds: u32,
}
DeserializeStruct!(nfstime3, seconds, nseconds);
SerializeStruct!(nfstime3, seconds, nseconds);
impl From<nfstime3> for filetime::FileTime {
fn from(time: nfstime3) -> Self {
Self::from_unix_time(time.seconds as i64, time.nseconds)
}
}
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Default)]
pub struct fattr3 {
pub ftype: ftype3,
pub mode: mode3,
pub nlink: u32,
pub uid: uid3,
pub gid: gid3,
pub size: size3,
pub used: size3,
pub rdev: specdata3,
pub fsid: u64,
pub fileid: fileid3,
pub atime: nfstime3,
pub mtime: nfstime3,
pub ctime: nfstime3,
}
DeserializeStruct!(
fattr3, ftype, mode, nlink, uid, gid, size, used, rdev, fsid, fileid, atime, mtime, ctime
);
SerializeStruct!(
fattr3, ftype, mode, nlink, uid, gid, size, used, rdev, fsid, fileid, atime, mtime, ctime
);
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Default)]
pub struct wcc_attr {
pub size: size3,
pub mtime: nfstime3,
pub ctime: nfstime3,
}
DeserializeStruct!(wcc_attr, size, mtime, ctime);
SerializeStruct!(wcc_attr, size, mtime, ctime);
pub type pre_op_attr = Option<wcc_attr>;
pub type post_op_attr = Option<fattr3>;
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Default)]
pub struct wcc_data {
pub before: pre_op_attr,
pub after: post_op_attr,
}
DeserializeStruct!(wcc_data, before, after);
SerializeStruct!(wcc_data, before, after);
pub type post_op_fh3 = Option<nfs_fh3>;
pub type set_mode3 = Option<mode3>;
pub type set_uid3 = Option<uid3>;
pub type set_gid3 = Option<gid3>;
pub type set_size3 = Option<size3>;
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug)]
#[repr(u32)]
pub enum set_atime {
DONT_CHANGE,
SET_TO_SERVER_TIME,
SET_TO_CLIENT_TIME(nfstime3),
}
impl Serialize for set_atime {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
match self {
set_atime::DONT_CHANGE => {
0_u32.serialize(dest)?;
}
set_atime::SET_TO_SERVER_TIME => {
1_u32.serialize(dest)?;
}
set_atime::SET_TO_CLIENT_TIME(v) => {
2_u32.serialize(dest)?;
v.serialize(dest)?;
}
}
Ok(())
}
}
impl Deserialize for set_atime {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
match deserialize::<u32>(src)? {
0 => {
*self = set_atime::DONT_CHANGE;
}
1 => {
*self = set_atime::SET_TO_SERVER_TIME;
}
2 => {
*self = set_atime::SET_TO_CLIENT_TIME(deserialize(src)?);
}
c => {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("Invalid set_atime value: {c}"),
));
}
}
Ok(())
}
}
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug)]
#[repr(u32)]
pub enum set_mtime {
DONT_CHANGE,
SET_TO_SERVER_TIME,
SET_TO_CLIENT_TIME(nfstime3),
}
impl Serialize for set_mtime {
fn serialize<R: Write>(&self, dest: &mut R) -> std::io::Result<()> {
match self {
set_mtime::DONT_CHANGE => {
0_u32.serialize(dest)?;
}
set_mtime::SET_TO_SERVER_TIME => {
1_u32.serialize(dest)?;
}
set_mtime::SET_TO_CLIENT_TIME(v) => {
2_u32.serialize(dest)?;
v.serialize(dest)?;
}
}
Ok(())
}
}
impl Deserialize for set_mtime {
fn deserialize<R: Read>(&mut self, src: &mut R) -> std::io::Result<()> {
match deserialize::<u32>(src)? {
0 => {
*self = set_mtime::DONT_CHANGE;
}
1 => {
*self = set_mtime::SET_TO_SERVER_TIME;
}
2 => {
*self = set_mtime::SET_TO_CLIENT_TIME(deserialize(src)?);
}
c => {
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidData,
format!("Invalid set_mtime value: {c}"),
));
}
}
Ok(())
}
}
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug)]
pub struct sattr3 {
pub mode: set_mode3,
pub uid: set_uid3,
pub gid: set_gid3,
pub size: set_size3,
pub atime: set_atime,
pub mtime: set_mtime,
}
DeserializeStruct!(sattr3, mode, uid, gid, size, atime, mtime);
SerializeStruct!(sattr3, mode, uid, gid, size, atime, mtime);
impl Default for sattr3 {
fn default() -> sattr3 {
sattr3 {
mode: set_mode3::None,
uid: set_uid3::None,
gid: set_gid3::None,
size: set_size3::None,
atime: set_atime::DONT_CHANGE,
mtime: set_mtime::DONT_CHANGE,
}
}
}
#[allow(non_camel_case_types)]
#[derive(Clone, Debug, Default)]
pub struct diropargs3 {
pub dir: nfs_fh3,
pub name: filename3,
}
DeserializeStruct!(diropargs3, dir, name);
SerializeStruct!(diropargs3, dir, name);
#[allow(non_camel_case_types)]
#[derive(Debug, Default)]
pub struct symlinkdata3 {
pub symlink_attributes: sattr3,
pub symlink_data: nfspath3,
}
DeserializeStruct!(symlinkdata3, symlink_attributes, symlink_data);
SerializeStruct!(symlinkdata3, symlink_attributes, symlink_data);
pub fn get_root_mount_handle() -> Vec<u8> {
vec![0]
}
pub const ACCESS3_READ: u32 = 0x0001;
pub const ACCESS3_LOOKUP: u32 = 0x0002;
pub const ACCESS3_MODIFY: u32 = 0x0004;
pub const ACCESS3_EXTEND: u32 = 0x0008;
pub const ACCESS3_DELETE: u32 = 0x0010;
pub const ACCESS3_EXECUTE: u32 = 0x0020;
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Default, FromPrimitive, ToPrimitive)]
#[repr(u32)]
pub enum createmode3 {
#[default]
UNCHECKED = 0,
GUARDED = 1,
EXCLUSIVE = 2,
}
impl SerializeEnum for createmode3 {}
impl DeserializeEnum for createmode3 {}
pub type sattrguard3 = Option<nfstime3>;
#[allow(non_camel_case_types)]
#[derive(Clone, Debug, Default)]
pub struct SETATTR3args {
pub object: nfs_fh3,
pub new_attribute: sattr3,
pub guard: Option<nfstime3>,
}
DeserializeStruct!(SETATTR3args, object, new_attribute, guard);
SerializeStruct!(SETATTR3args, object, new_attribute, guard);