diff --git a/nuttx/fs/nfs/nfs.h b/nuttx/fs/nfs/nfs.h index da0d5735c9..d18442b97a 100644 --- a/nuttx/fs/nfs/nfs.h +++ b/nuttx/fs/nfs/nfs.h @@ -374,7 +374,7 @@ EXTERN int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath, FAR struct nfs_fattr *dir_attributes); EXTERN int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath, FAR struct file_handle *fhandle, - FAR struct nfs_fattr *attributes); + FAR struct nfs_fattr *attributes, FAR char *filename); #undef EXTERN #if defined(__cplusplus) diff --git a/nuttx/fs/nfs/nfs_mount.h b/nuttx/fs/nfs/nfs_mount.h index 60ffdd3a45..7e548fe349 100644 --- a/nuttx/fs/nfs/nfs_mount.h +++ b/nuttx/fs/nfs/nfs_mount.h @@ -54,10 +54,6 @@ * Pre-processor Definitions ****************************************************************************/ -/* Convert mount ptr to nfsmount ptr. */ - -#define VFSTONFS(mp) ((struct nfsmount *)((mp)->i_private)) - /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/nuttx/fs/nfs/nfs_proto.h b/nuttx/fs/nfs/nfs_proto.h index c5800b216d..18cfbf5c1c 100644 --- a/nuttx/fs/nfs/nfs_proto.h +++ b/nuttx/fs/nfs/nfs_proto.h @@ -187,27 +187,6 @@ #define NFSPROC_NOOP 22 #define NFS_NPROCS 23 -/* Actual Version 2 procedure numbers */ - -#define NFSV2PROC_NULL 0 -#define NFSV2PROC_GETATTR 1 -#define NFSV2PROC_SETATTR 2 -#define NFSV2PROC_NOOP 3 -#define NFSV2PROC_ROOT NFSV2PROC_NOOP/* Obsolete */ -#define NFSV2PROC_LOOKUP 4 -#define NFSV2PROC_READLINK 5 -#define NFSV2PROC_READ 6 -#define NFSV2PROC_WRITECACHE NFSV2PROC_NOOP/* Obsolete */ -#define NFSV2PROC_WRITE 8 -#define NFSV2PROC_CREATE 9 -#define NFSV2PROC_REMOVE 10 -#define NFSV2PROC_RENAME 11 -#define NFSV2PROC_LINK 12 -#define NFSV2PROC_SYMLINK 13 -#define NFSV2PROC_MKDIR 14 -#define NFSV2PROC_RMDIR 15 -#define NFSV2PROC_READDIR 16 -#define NFSV2PROC_STATFS 17 /* Constants used by the Version 3 protocol for various RPCs */ @@ -274,17 +253,11 @@ /* Conversion macros */ -#define vtonfsv2_mode(t,m) \ - txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \ - MAKEIMODE((t), (m))) #define vtonfsv3_mode(m) txdr_unsigned((m) & 07777) #define nfstov_mode(a) (fxdr_unsigned(u_int16_t, (a))&07777) -#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((int32_t)(a))]) #define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((int32_t)(a))]) -#define nfsv2tov_type(a) nv2tov_type[fxdr_unsigned(uint32_t,(a))&0x7] #define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(uint32_t,(a))&0x7] -#define NFS_MAXFHSIZE 64 /* Mode bit values */ @@ -356,17 +329,11 @@ typedef struct fhandle fhandle_t; struct nfsfh { - uint8_t fh_bytes[NFSX_V2FH]; + uint8_t fh_bytes[NFSX_V3FHMAX]; }; typedef struct nfsfh nfsfh_t; #define SIZEOF_nfsfh_t(n) (n) -struct nfsv2_time -{ - uint32_t nfsv2_sec; - uint32_t nfsv2_usec; -}; -typedef struct nfsv2_time nfstime2; struct nfsv3_time { @@ -405,125 +372,54 @@ typedef struct nfsv3_spec nfsv3spec; struct nfs_fattr { - uint32_t fa_type; - uint32_t fa_mode; - uint32_t fa_nlink; - uint32_t fa_uid; - uint32_t fa_gid; - union - { - /*struct - { - uint32_t nfsv2fa_size; - uint32_t nfsv2fa_blocksize; - uint32_t nfsv2fa_rdev; - uint32_t nfsv2fa_blocks; - uint32_t nfsv2fa_fsid; - uint32_t nfsv2fa_fileid; - nfstime2 nfsv2fa_atime; - nfstime2 nfsv2fa_mtime; - nfstime2 nfsv2fa_ctime; - } fa_nfsv2;*/ - struct - { - nfsuint64 nfsv3fa_size; - nfsuint64 nfsv3fa_used; - nfsv3spec nfsv3fa_rdev; - nfsuint64 nfsv3fa_fsid; - nfsuint64 nfsv3fa_fileid; - nfstime3 nfsv3fa_atime; - nfstime3 nfsv3fa_mtime; - nfstime3 nfsv3fa_ctime; - } fa_nfsv3; - } fa_un; + uint32_t fa_type; + uint32_t fa_mode; + uint32_t fa_nlink; + uint32_t fa_uid; + uint32_t fa_gid; + nfsuint64 fa_size; + nfsuint64 fa_used; + nfsv3spec fa_rdev; + nfsuint64 fa_fsid; + nfsuint64 fa_fileid; + nfstime3 fa_atime; + nfstime3 fa_mtime; + nfstime3 fa_ctime; }; -/* And some ugly defines for accessing union components */ - -/*#define fa2_size fa_un.fa_nfsv2.nfsv2fa_size -#define fa2_blocksize fa_un.fa_nfsv2.nfsv2fa_blocksize -#define fa2_rdev fa_un.fa_nfsv2.nfsv2fa_rdev -#define fa2_blocks fa_un.fa_nfsv2.nfsv2fa_blocks -#define fa2_fsid fa_un.fa_nfsv2.nfsv2fa_fsid -#define fa2_fileid fa_un.fa_nfsv2.nfsv2fa_fileid -#define fa2_atime fa_un.fa_nfsv2.nfsv2fa_atime -#define fa2_mtime fa_un.fa_nfsv2.nfsv2fa_mtime -#define fa2_ctime fa_un.fa_nfsv2.nfsv2fa_ctime*/ -#define fa3_size fa_un.fa_nfsv3.nfsv3fa_size -#define fa3_used fa_un.fa_nfsv3.nfsv3fa_used -#define fa3_rdev fa_un.fa_nfsv3.nfsv3fa_rdev -#define fa3_fsid fa_un.fa_nfsv3.nfsv3fa_fsid -#define fa3_fileid fa_un.fa_nfsv3.nfsv3fa_fileid -#define fa3_atime fa_un.fa_nfsv3.nfsv3fa_atime -#define fa3_mtime fa_un.fa_nfsv3.nfsv3fa_mtime -#define fa3_ctime fa_un.fa_nfsv3.nfsv3fa_ctime - -struct nfsv2_sattr -{ - uint32_t sa_mode; - uint32_t sa_uid; - uint32_t sa_gid; - uint32_t sa_size; - nfstime2 sa_atime; - nfstime2 sa_mtime; -}; - -/* NFS Version 3 sattr structure for the new node creation case. */ +/* NFS Version 3 sattr structure for the new node creation case. This is the + * maximum size of the attributes; the actual size may vary if values are not + * include. + */ struct nfsv3_sattr { - uint32_t sa_modetrue; - uint32_t sa_mode; - uint32_t sa_uidfalse; -//uint32_t sa_uid; - uint32_t sa_gidfalse; -//uint32_t sa_gid; - uint32_t sa_sizefalse; - uint32_t sa_atimetype; -//nfstime3 sa_atime; - uint32_t sa_mtimetype; -//nfstime3 sa_mtime; + uint32_t sa_modefollows; /* TRUE: Mode value follows */ + uint32_t sa_mode; /* Mode value */ + uint32_t sa_uidfollows; /* TRUE: Uid value follows */ + uint32_t sa_uid; /* Uid value */ + uint32_t sa_gidfollows; /* TRUE: Mode value follows */ + uint32_t sa_gid; /* Mode value */ + uint32_t sa_sizefollows; /* TRUE: Size value follows */ + uint32_t sa_size; /* Size value */ + uint32_t sa_atimetype; /* Don't change, use server timer, or use client time */ + nfstime3 sa_atime; /* Client time */ + uint32_t sa_mtimetype; /* Don't change, use server timer, or use client time */ + nfstime3 sa_mtime; /* Client time */ }; struct nfs_statfs { struct nfs_fattr obj_attributes; - union - { - /*struct - { - uint32_t nfsv2sf_tsize; - uint32_t nfsv2sf_bsize; - uint32_t nfsv2sf_blocks; - uint32_t nfsv2sf_bfree; - uint32_t nfsv2sf_bavail; - } sf_nfsv2;*/ - struct - { - nfsuint64 nfsv3sf_tbytes; - nfsuint64 nfsv3sf_fbytes; - nfsuint64 nfsv3sf_abytes; - nfsuint64 nfsv3sf_tfiles; - nfsuint64 nfsv3sf_ffiles; - nfsuint64 nfsv3sf_afiles; - uint32_t nfsv3sf_invarsec; - } sf_nfsv3; - } sf_un; + nfsuint64 sf_tbytes; + nfsuint64 sf_fbytes; + nfsuint64 sf_abytes; + nfsuint64 sf_tfiles; + nfsuint64 sf_ffiles; + nfsuint64 sf_afiles; + uint32_t sf_invarsec; }; - -/*#define sf_tsize sf_un.sf_nfsv2.nfsv2sf_tsize -#define sf_bsize sf_un.sf_nfsv2.nfsv2sf_bsize -#define sf_blocks sf_un.sf_nfsv2.nfsv2sf_blocks -#define sf_bfree sf_un.sf_nfsv2.nfsv2sf_bfree -#define sf_bavail sf_un.sf_nfsv2.nfsv2sf_bavail*/ -#define sf_tbytes sf_un.sf_nfsv3.nfsv3sf_tbytes -#define sf_fbytes sf_un.sf_nfsv3.nfsv3sf_fbytes -#define sf_abytes sf_un.sf_nfsv3.nfsv3sf_abytes -#define sf_tfiles sf_un.sf_nfsv3.nfsv3sf_tfiles -#define sf_ffiles sf_un.sf_nfsv3.nfsv3sf_ffiles -#define sf_afiles sf_un.sf_nfsv3.nfsv3sf_afiles -#define sf_invarsec sf_un.sf_nfsv3.nfsv3sf_invarsec - + struct post_attr { uint32_t obj_attributesfalse; @@ -570,9 +466,9 @@ struct file_handle struct diropargs3 { - struct file_handle dir; - uint32_t length; - char name[64]; + struct file_handle fhandle; /* Variable length */ + uint32_t length; /* Size of name[] */ + uint32_t name[(NAME_MAX+3) >> 2]; /* Variable length */ }; struct CREATE3args @@ -584,8 +480,10 @@ struct CREATE3args struct CREATE3resok { - struct file_handle fshandle; - struct nfs_fattr attributes; + uint32_t handle_follows; /* True, handle follows */ + struct file_handle fhandle; /* Variable length */ + uint32_t attributes_follows; /* True, attributes follows */ + struct nfs_fattr attributes; /* File attributes */ struct wcc_data dir_wcc; }; @@ -595,7 +493,7 @@ struct CREATE3resok struct LOOKUP3filename { - uint32_t namelen; /* Size name */ + uint32_t namelen; /* Size of name[] */ uint32_t name[(NAME_MAX+3) >> 2]; /* Variable length */ }; @@ -612,7 +510,7 @@ struct LOOKUP3args struct LOOKUP3resok { - struct file_handle fshandle; + struct file_handle fhandle; uint32_t obj_attributes_follow; struct nfs_fattr obj_attributes; uint32_t dir_attributes_follow; @@ -621,7 +519,7 @@ struct LOOKUP3resok struct READ3args { - struct file_handle fshandle; /* Variable length */ + struct file_handle fhandle; /* Variable length */ uint64_t offset; uint32_t count; }; @@ -644,7 +542,7 @@ struct READ3resok struct nfs_wrhdr_s { - struct file_handle fshandle; /* Variable length */ + struct file_handle fhandle; /* Variable length */ uint64_t offset; uint32_t count; uint32_t stable; @@ -695,7 +593,7 @@ struct MKDIR3args struct MKDIR3resok { - struct file_handle fshandle; + struct file_handle fhandle; uint32_t obj_attributesfalse; struct nfs_fattr obj_attributes; struct wcc_data dir_wcc; diff --git a/nuttx/fs/nfs/nfs_util.c b/nuttx/fs/nfs/nfs_util.c index 5964248e78..ccf40b4fa9 100644 --- a/nuttx/fs/nfs/nfs_util.c +++ b/nuttx/fs/nfs/nfs_util.c @@ -540,10 +540,9 @@ int nfs_findnode(struct nfsmount *nmp, FAR const char *relpath, int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath, FAR struct file_handle *fhandle, - FAR struct nfs_fattr *attributes) + FAR struct nfs_fattr *attributes, FAR char *filename) { FAR const char *path = relpath; - char buffer[NAME_MAX+1]; uint32_t tmp; char terminator; int error; @@ -569,13 +568,13 @@ int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath, { /* Extract the next path segment name. */ - error = nfs_pathsegment(&path, buffer, &terminator); + error = nfs_pathsegment(&path, filename, &terminator); if (error != 0) { /* The filename segment contains is too long. */ fdbg("nfs_pathsegment of \"%s\" failed after \"%s\": %d\n", - relpath, buffer, error); + relpath, filename, error); return error; } @@ -595,11 +594,11 @@ int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath, /* Look-up the next path segment */ - error = nfs_lookup(nmp, buffer, fhandle, attributes, NULL); + error = nfs_lookup(nmp, filename, fhandle, attributes, NULL); if (error != 0) { fdbg("nfs_lookup of \"%s\" failed at \"%s\": %d\n", - relpath, buffer, error); + relpath, filename, error); return error; } @@ -611,7 +610,7 @@ int nfs_finddir(struct nfsmount *nmp, FAR const char *relpath, /* Ooops.. we found something else */ fdbg("ERROR: Intermediate segment \"%s\" of \'%s\" is not a directory\n", - buffer, path); + filename, path); return ENOTDIR; } } diff --git a/nuttx/fs/nfs/nfs_vfsops.c b/nuttx/fs/nfs/nfs_vfsops.c index 1529140250..4e826792a3 100644 --- a/nuttx/fs/nfs/nfs_vfsops.c +++ b/nuttx/fs/nfs/nfs_vfsops.c @@ -90,6 +90,10 @@ #define NFS_DIRHDSIZ (sizeof (struct nfs_dirent) - (MAXNAMLEN + 1)) #define NFS_DIRENT_OVERHEAD offsetof(struct nfs_dirent, dirent) +/* The V3 EXCLUSIVE file creation logic is not fully support. */ + +#define USE_GUARDED_CREATE 1 + /* include/nuttx/fs/dirent.h has its own version of these lengths. They must * match the NFS versions. */ @@ -116,8 +120,10 @@ struct nfs_dirent * Private Function Prototypes ****************************************************************************/ -static int nfs_create(FAR struct nfsmount *nmp, struct nfsnode *np, +static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np, FAR const char *relpath, mode_t mode); +static int nfs_fileopen(FAR struct nfsmount *nmp, struct nfsnode *np, + FAR const char *relpath, int oflags, mode_t mode); static int nfs_open(FAR struct file *filep, const char *relpath, int oflags, mode_t mode); static ssize_t nfs_read(FAR struct file *filep, char *buffer, size_t buflen); @@ -179,7 +185,7 @@ const struct mountpt_operations nfs_operations = ****************************************************************************/ /**************************************************************************** - * Name: nfs_create + * Name: nfs_filecreate * * Description: * Create a file. This is part of the file open logic that is executed if @@ -190,62 +196,257 @@ const struct mountpt_operations nfs_operations = * ****************************************************************************/ -static int nfs_create(FAR struct nfsmount *nmp, struct nfsnode *np, - FAR const char *relpath, mode_t mode) +static int nfs_filecreate(FAR struct nfsmount *nmp, struct nfsnode *np, + FAR const char *relpath, mode_t mode) { -//struct nfs_fattr vap; - struct nfsv3_sattr sp; - struct CREATE3args create; + struct file_handle fhandle; + char filename[NAME_MAX + 1]; + struct CREATE3args create; struct rpc_reply_create resok; - int error = 0; + FAR uint32_t *ptr; + uint32_t tmp; + int namelen; + int reqlen; + int error; + + /* Find the NFS node of the directory containing the file filename */ + + error = nfs_finddir(nmp, relpath, &fhandle, &np->n_fattr, filename); + if (error != OK) + { + fdbg("ERROR: nfs_finddir returned: %d\n", error); + return error; + } + + /* Create the CREATE RPC call arguments */ + + ptr = (FAR uint32_t *)&create; + reqlen = 0; + + /* Copy the variable length, directory file handle */ + + *ptr++ = txdr_unsigned(fhandle.length); + reqlen += sizeof(uint32_t); + + memcpy(ptr, &fhandle.handle, fhandle.length); + reqlen += (int)fhandle.length; + ptr += uint32_increment(fhandle.length); + + /* Copy the variable-length file name */ + + namelen = strlen(filename); + + *ptr++ = txdr_unsigned(namelen); + reqlen += sizeof(uint32_t); + + memcpy(ptr, filename, namelen); + reqlen += uint32_alignup(namelen); + + /* Set the creation mode */ + + if ((mode & O_CREAT) != 0) + { +#ifdef USE_GUARDED_CREATE + *ptr++ = HTONL(NFSV3CREATE_GUARDED); +#else + *ptr++ = HTONL(NFSV3CREATE_GUARDED); +#endif + } + else + { + *ptr++ = HTONL(NFSV3CREATE_UNCHECKED); + } + reqlen += sizeof(uint32_t); + + /* Mode information is not provided if EXCLUSIVE creation is used. + * in this case, we must call SETATTR after successfully creating + * the file. + */ + +#ifndef USE_GUARDED_CREATE + if ((mode & O_CREAT) == 0) +#endif + { + /* Set the mode. NOTE: Here we depend on the fact that the NuttX and NFS + * bit settings are the same (at least for the bits of interest). + */ + + *ptr++ = nfs_true; /* True: mode value follows */ + reqlen += sizeof(uint32_t); + + tmp = mode & (NFSMODE_IWOTH | NFSMODE_IROTH | NFSMODE_IWGRP | + NFSMODE_IRGRP | NFSMODE_IWUSR | NFSMODE_IRUSR); + *ptr++ = txdr_unsigned(tmp); + reqlen += sizeof(uint32_t); + + /* Set the user ID to zero */ + + *ptr++ = nfs_true; /* True: Uid value follows */ + reqlen += sizeof(uint32_t); + + *ptr++ = 0; + reqlen += sizeof(uint32_t); + + /* Set the group ID to one */ + + *ptr++ = nfs_true; /* True: Gid value follows */ + reqlen += sizeof(uint32_t); + + *ptr++ = HTONL(1); + reqlen += sizeof(uint32_t); + + /* Set the size to zero */ + + *ptr++ = nfs_true; /* True: Size value follows */ + reqlen += sizeof(uint32_t); + + *ptr++ = 0; + reqlen += sizeof(uint32_t); + + /* Don't change times */ + + *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change atime */ + reqlen += sizeof(uint32_t); + + *ptr++ = HTONL(NFSV3SATTRTIME_DONTCHANGE); /* Don't change mtime */ + reqlen += sizeof(uint32_t); + } + + /* Send the NFS request. Note there is special logic here to handle version 3 + * exclusive open semantics. + */ do { nfsstats.rpccnt[NFSPROC_CREATE]++; - memset(&sp, 0, sizeof(struct nfsv3_sattr)); - //memset(&vap, 0, sizeof(struct nfs_fattr)); - //vap = nmp->nm_head->n_fattr; - sp.sa_modetrue = true; - sp.sa_mode = txdr_unsigned(mode); - sp.sa_uidfalse = nfs_xdrneg1; - sp.sa_gidfalse = nfs_xdrneg1; - sp.sa_sizefalse = 0; - sp.sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); - sp.sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); - //txdr_nfsv3time2(&vap.fa3_atime, &sp.sa_atime); - //txdr_nfsv3time2(&vap.fa3_mtime, &sp.sa_mtime); - - memset(&create, 0, sizeof(struct CREATE3args)); - memset(&resok, 0, sizeof(struct rpc_reply_create)); - memcpy(&create.how, &sp, sizeof(struct nfsv3_sattr)); -#warning "BUG HERE: np has not yet been initialized" - create.where.dir.length = txdr_unsigned(np->n_fhsize); - memcpy(&create.where.dir.handle, &np->n_fhandle, sizeof(nfsfh_t)); - create.where.length = txdr_unsigned(64); - strncpy(create.where.name, relpath, 64); - error = nfs_request(nmp, NFSPROC_CREATE, - (FAR const void *)&create, sizeof(struct CREATE3args), + (FAR const void *)&create, reqlen, (FAR void *)&resok, sizeof(struct rpc_reply_create)); } - while (error == EOPNOTSUPP); +#ifdef USE_GUARDED_CREATE + while (0); +#else + while (((mode & O_CREAT) != 0) && error == EOPNOTSUPP); +#endif - if (error == 0) + /* Check for success */ + + if (error == OK) { - //np->n_type = fxdr_unsigned(uint32_t, resok.attributes.fa_type); - - memcpy(&np->n_fhandle, &resok.create.fshandle.handle, sizeof(nfsfh_t)); - np->n_size = fxdr_hyper(&resok.create.attributes.fa3_size); + np->n_type = fxdr_unsigned(uint32_t, resok.create.attributes.fa_type); + memcpy(&np->n_fhandle, &resok.create.fhandle.handle, sizeof(nfsfh_t)); + np->n_size = fxdr_hyper(&resok.create.attributes.fa_size); memcpy(&resok.create.attributes, &np->n_fattr, sizeof(struct nfs_fattr)); - fxdr_nfsv3time(&resok.create.attributes.fa3_mtime, &np->n_mtime) - np->n_ctime = fxdr_hyper(&resok.create.attributes.fa3_ctime); + fxdr_nfsv3time(&resok.create.attributes.fa_mtime, &np->n_mtime) + np->n_ctime = fxdr_hyper(&resok.create.attributes.fa_ctime); np->n_flags = NFSNODE_OPEN; } return error; } - /**************************************************************************** +/**************************************************************************** + * Name: nfs_fileopen + * + * Description: + * Open a file. This is part of the file open logic that attempts to open + * an existing file. + * + * Returned Value: + * 0 on success; a positive errno value on failure. + * + ****************************************************************************/ + +static int nfs_fileopen(FAR struct nfsmount *nmp, struct nfsnode *np, + FAR const char *relpath, int oflags, mode_t mode) +{ + struct file_handle fhandle; + uint32_t tmp; + int error = 0; + + /* Find the NFS node associate with the path */ + + error = nfs_findnode(nmp, relpath, &fhandle, &np->n_fattr, NULL); + if (error != OK) + { + fdbg("ERROR: nfs_findnode returned: %d\n", error); + return error; + } + + /* Check if the object is a directory */ + + tmp = fxdr_unsigned(uint32_t, np->n_fattr.fa_type); + if (tmp == NFDIR) + { + /* Exit with EISDIR if we attempt to open a directory */ + + fdbg("ERROR: Path is a directory\n"); + return EISDIR; + } + + /* Check if the caller has sufficient privileges to open the file */ + + if ((oflags & O_WRONLY) != 0) + { + /* Check if anyone has priveleges to write to the file -- owner, + * group, or other (we are probably "other" and may still not be + * able to write). + */ + + tmp = fxdr_unsigned(uint32_t, np->n_fattr.fa_mode); + if ((tmp & (NFSMODE_IWOTH|NFSMODE_IWGRP|NFSMODE_IWUSR)) == 0) + { + fdbg("ERROR: File is read-only: %08x\n", tmp); + return EACCES; + } + } + + /* It would be an error if we are asked to create the file exclusively */ + + if ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) + { + /* Already exists -- can't create it exclusively */ + + fdbg("ERROR: File exists\n"); + return EEXIST; + } + + /* If O_TRUNC is specified and the file is opened for writing, + * then truncate the file. This operation requires that the file is + * writable, but we have already checked that. O_TRUNC without write + * access is ignored. + */ + + if ((oflags & (O_TRUNC|O_WRONLY)) == (O_TRUNC|O_WRONLY)) + { + /* Truncate the file to zero length. I think we can do this with + * the SETATTR call by setting the length to zero. + */ + + fvdbg("Truncating file\n"); +#warning "Missing logic" + return ENOSYS; + } + + /* Initialize the file private data */ + /* Copy the file handle */ + + np->n_fhsize = (uint8_t)fhandle.length; + memcpy(&np->n_fhandle, &fhandle.handle, fhandle.length); + + /* Get a convenience versions of file type, size, and modification time + * in host byte order. + */ + + np->n_type = fxdr_unsigned(uint32_t, np->n_fattr.fa_type); + np->n_size = fxdr_hyper(&np->n_fattr.fa_size); + fxdr_nfsv3time(&np->n_fattr.fa_mtime, &np->n_mtime) + np->n_ctime = fxdr_hyper(&np->n_fattr.fa_ctime); + + return OK; +} + +/**************************************************************************** * Name: nfs_open * * Description: @@ -260,13 +461,12 @@ static int nfs_create(FAR struct nfsmount *nmp, struct nfsnode *np, static int nfs_open(FAR struct file *filep, FAR const char *relpath, int oflags, mode_t mode) { - struct file_handle fhandle; struct inode *in; struct nfsmount *nmp; struct nfsnode *np; uint32_t buflen; uint32_t tmp; - int error = 0; + int error; /* Sanity checks */ @@ -334,122 +534,47 @@ static int nfs_open(FAR struct file *filep, FAR const char *relpath, goto errout_with_semaphore; } - /* Find the NFS node associate with the path */ + /* Try to open an existing file at that path */ - error = nfs_findnode(nmp, relpath, &fhandle, &np->n_fattr, NULL); - if (error == 0) + error = nfs_fileopen(nmp, np, relpath, oflags, mode); + if (error != 0) { - /* Check if the path is a directory */ + /* An error occurred while trying to open the existing file. Check if + * the open failed because the file does not exist. That is not + * necessarily an error; that may only mean that we have to create the + * file. + */ - tmp = fxdr_unsigned(uint32_t, np->n_fattr.fa_type); - if (tmp == NFDIR) + if (error != ENOENT) { - /* Exit with EISDIR if we attempt to open a directory */ - - fdbg("ERROR: Path is a directory\n"); - error = EISDIR; + fdbg("ERROR: nfs_findnode failed: %d\n", error); goto errout_with_semaphore; } - /* Check if the caller has sufficient privileges to open the file */ + /* The file does not exist. Check if we were asked to create the file. If + * the O_CREAT bit is set in the oflags then we should create the file if it + * does not exist. + */ - if ((oflags & O_WRONLY) != 0) + if ((oflags & O_CREAT) == 0) { - /* Check if anyone has priveleges to write to the file -- owner, - * group, or other (we are probably "other" and may still not be - * able to write). + /* Return ENOENT if the file does not exist and we were not asked + * to create it. */ - tmp = fxdr_unsigned(uint32_t, np->n_fattr.fa_mode); - if ((tmp & (NFSMODE_IWOTH|NFSMODE_IWGRP|NFSMODE_IWUSR)) == 0) - { - fdbg("ERROR: File is read-only: %08x\n", tmp); - error = EACCES; - goto errout_with_semaphore; - } - } - - /* It would be an error if we are asked to create the file exclusively */ - - if ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) - { - /* Already exists -- can't create it exclusively */ - - fdbg("ERROR: File exists\n"); - error = EEXIST; + fdbg("ERROR: File does not exist\n"); + error = ENOENT; goto errout_with_semaphore; } - - /* If O_TRUNC is specified and the file is opened for writing, - * then truncate the file. This operation requires that the file is - * writable, but we have already checked that. O_TRUNC without write - * access is ignored. - */ - - if ((oflags & (O_TRUNC|O_WRONLY)) == (O_TRUNC|O_WRONLY)) - { - /* Truncate the file to zero length */ - - fvdbg("Truncating file\n"); -#warning "Missing logic" - } - - /* Initialize the file private data */ - /* Copy the file handle */ - - np->n_fhsize = (uint8_t)fhandle.length; - memcpy(&np->n_fhandle, &fhandle.handle, fhandle.length); - - /* Get a convenience version of file size and modification time in host - * byte order. - */ - - np->n_size = fxdr_hyper(&np->n_fattr.fa3_size); - fxdr_nfsv3time(&np->n_fattr.fa3_mtime, &np->n_mtime) - np->n_ctime = fxdr_hyper(&np->n_fattr.fa3_ctime); - - /* Fall through to finish the file open operation */ - } - - /* An error occurred while getting the file node. Check if the stat failed - * because the file does not exist. That is not necessarily an error; that - * may only mean that we have to create the file. - */ - - else if (error != ENOENT) - { - fdbg("ERROR: nfs_findnode failed: %d\n", error); - goto errout_with_semaphore; - } - - /* The file does not exist. Check if we were asked to create the file. If - * the O_CREAT bit is set in the oflags then we should create the file if it - * does not exist. - */ - - else if ((oflags & O_CREAT) == 0) - { - /* Return ENOENT if the file does not exist and we were not asked - * to create it. - */ - - fdbg("ERROR: File does not exist\n"); - error = ENOENT; - goto errout_with_semaphore; - } - /* Create the file */ + /* Create the file */ - else - { - error = nfs_create(nmp, np, relpath, mode); + error = nfs_filecreate(nmp, np, relpath, mode); if (error != 0) { - fdbg("ERROR: nfs_create failed: %d\n", error); + fdbg("ERROR: nfs_filecreate failed: %d\n", error); goto errout_with_semaphore; } - - /* Fall through to finish the file open operation */ } /* Initialize the file private data (only need to initialize @@ -828,7 +953,7 @@ static ssize_t nfs_write(FAR struct file *filep, const char *buffer, memcpy((void*) nmp->nm_verf, (void*) resok.write.verf, NFSX_V3WRITEVERF); } - fxdr_nfsv3time(&np->n_fattr.fa3_mtime, &np->n_mtime) + fxdr_nfsv3time(&np->n_fattr.fa_mtime, &np->n_mtime) nfs_semgive(nmp); return writesize; @@ -1805,10 +1930,10 @@ static int nfs_remove(struct inode *mountpt, const char *relpath) nfsstats.rpccnt[NFSPROC_REMOVE]++; memset(&remove, 0, sizeof(struct REMOVE3args)); memset(&resok, 0, sizeof(struct rpc_reply_remove)); - remove.object.dir.length = txdr_unsigned(np->n_fhsize); - memcpy(&remove.object.dir.handle, &np->n_fhandle, sizeof(nfsfh_t)); + remove.object.fhandle.length = txdr_unsigned(np->n_fhsize); + memcpy(&remove.object.fhandle.handle, &np->n_fhandle, sizeof(nfsfh_t)); remove.object.length = txdr_unsigned(64); - strncpy(remove.object.name, relpath, 64); + strncpy((FAR char *)remove.object.name, relpath, 64); error = nfs_request(nmp, NFSPROC_REMOVE, (FAR const void *)&remove, sizeof(struct REMOVE3args), @@ -1880,18 +2005,18 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) nfsstats.rpccnt[NFSPROC_MKDIR]++; memset(&mkir, 0, sizeof(struct MKDIR3args)); memset(&resok, 0, sizeof(struct rpc_reply_mkdir)); - mkir.where.dir.length = txdr_unsigned(np->n_fhsize); - memcpy(&mkir.where.dir.handle, &np->n_fhandle, sizeof(nfsfh_t)); + mkir.where.fhandle.length = txdr_unsigned(np->n_fhsize); + memcpy(&mkir.where.fhandle.handle, &np->n_fhandle, sizeof(nfsfh_t)); mkir.where.length = txdr_unsigned(64); - strncpy(mkir.where.name, relpath, 64); + strncpy((FAR char *)mkir.where.name, relpath, 64); - sp.sa_modetrue = nfs_true; - sp.sa_mode = txdr_unsigned(mode); - sp.sa_uidfalse = 0; - sp.sa_gidfalse = 0; - sp.sa_sizefalse = 0; - sp.sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); - sp.sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); + sp.sa_modefollows = nfs_true; + sp.sa_mode = txdr_unsigned(mode); + sp.sa_uidfollows = 0; + sp.sa_gidfollows = 0; + sp.sa_sizefollows = 0; + sp.sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); + sp.sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); //memset(&sp.sa_atime, 0, sizeof(nfstime3)); //memset(&sp.sa_mtime, 0, sizeof(nfstime3)); @@ -1907,11 +2032,11 @@ static int nfs_mkdir(struct inode *mountpt, const char *relpath, mode_t mode) } np->n_type = fxdr_unsigned(uint32_t, resok.mkdir.obj_attributes.fa_type); - memcpy(&np->n_fhandle, &resok.mkdir.fshandle.handle, sizeof(nfsfh_t)); - np->n_size = fxdr_hyper(&resok.mkdir.obj_attributes.fa3_size); + memcpy(&np->n_fhandle, &resok.mkdir.fhandle.handle, sizeof(nfsfh_t)); + np->n_size = fxdr_hyper(&resok.mkdir.obj_attributes.fa_size); memcpy(&np->n_fattr, &resok.mkdir.obj_attributes, sizeof(struct nfs_fattr)); - fxdr_nfsv3time(&resok.mkdir.obj_attributes.fa3_mtime, &np->n_mtime) - np->n_ctime = fxdr_hyper(&resok.mkdir.obj_attributes.fa3_ctime); + fxdr_nfsv3time(&resok.mkdir.obj_attributes.fa_mtime, &np->n_mtime) + np->n_ctime = fxdr_hyper(&resok.mkdir.obj_attributes.fa_ctime); np->n_flags |= (NFSNODE_OPEN | NFSNODE_MODIFIED); errout_with_semaphore: @@ -1966,10 +2091,10 @@ static int nfs_rmdir(struct inode *mountpt, const char *relpath) nfsstats.rpccnt[NFSPROC_RMDIR]++; memset(&rmdir, 0, sizeof(struct RMDIR3args)); memset(&resok, 0, sizeof(struct rpc_reply_rmdir)); - rmdir.object.dir.length = txdr_unsigned(np->n_fhsize); - memcpy(&rmdir.object.dir.handle, &np->n_fhandle, sizeof(nfsfh_t)); + rmdir.object.fhandle.length = txdr_unsigned(np->n_fhsize); + memcpy(&rmdir.object.fhandle.handle, &np->n_fhandle, sizeof(nfsfh_t)); rmdir.object.length = txdr_unsigned(64); - strncpy(rmdir.object.name, relpath, 64); + strncpy((FAR char *)rmdir.object.name, relpath, 64); error = nfs_request(nmp, NFSPROC_RMDIR, (FAR const void *)&rmdir, sizeof(struct RMDIR3args), @@ -2041,14 +2166,14 @@ static int nfs_rename(struct inode *mountpt, const char *oldrelpath, nfsstats.rpccnt[NFSPROC_RENAME]++; memset(&rename, 0, sizeof(struct RENAME3args)); memset(&resok, 0, sizeof(struct rpc_reply_rename)); - rename.from.dir.length = txdr_unsigned(np->n_fhsize); - memcpy(&rename.from.dir.handle, &np->n_fhandle, sizeof(nfsfh_t)); + rename.from.fhandle.length = txdr_unsigned(np->n_fhsize); + memcpy(&rename.from.fhandle.handle, &np->n_fhandle, sizeof(nfsfh_t)); rename.from.length = txdr_unsigned(64); - strncpy(rename.from.name, oldrelpath, 64); - rename.to.dir.length = txdr_unsigned(np->n_fhsize); - memcpy(&rename.to.dir.handle, &np->n_fhandle, sizeof(nfsfh_t)); + strncpy((FAR char *)rename.from.name, oldrelpath, 64); + rename.to.fhandle.length = txdr_unsigned(np->n_fhsize); + memcpy(&rename.to.fhandle.handle, &np->n_fhandle, sizeof(nfsfh_t)); rename.to.length = txdr_unsigned(64); - strncpy(rename.to.name, newrelpath, 64); + strncpy((FAR char *)rename.to.name, newrelpath, 64); error = nfs_request(nmp, NFSPROC_RENAME, (FAR const void *)&rename, sizeof(struct RENAME3args), @@ -2188,12 +2313,12 @@ static int nfs_stat(struct inode *mountpt, const char *relpath, } buf->st_mode = mode; - buf->st_size = fxdr_hyper(&obj_attributes.fa3_size); + buf->st_size = fxdr_hyper(&obj_attributes.fa_size); buf->st_blksize = 0; buf->st_blocks = 0; - buf->st_mtime = fxdr_hyper(&obj_attributes.fa3_mtime); - buf->st_atime = fxdr_hyper(&obj_attributes.fa3_atime); - buf->st_ctime = fxdr_hyper(&obj_attributes.fa3_ctime); + buf->st_mtime = fxdr_hyper(&obj_attributes.fa_mtime); + buf->st_atime = fxdr_hyper(&obj_attributes.fa_atime); + buf->st_ctime = fxdr_hyper(&obj_attributes.fa_ctime); errout_with_semaphore: nfs_semgive(nmp); diff --git a/nuttx/fs/nfs/rpc_clnt.c b/nuttx/fs/nfs/rpc_clnt.c index afa383d9cb..bb213288dd 100644 --- a/nuttx/fs/nfs/rpc_clnt.c +++ b/nuttx/fs/nfs/rpc_clnt.c @@ -189,8 +189,6 @@ static uint32_t rpc_auth_null; int rpcclnt_ticks; struct rpcstats rpcstats; -//struct rpc_call *callmgs; -//struct rpc_reply *replymsg; /* Queue head for rpctask's */ @@ -658,7 +656,7 @@ static int rpcclnt_reply(struct rpctask *myrep, int procid, int prog, return 0; } - fdbg("ignoring routing error on connectionless protocol\n"); + fdbg("Ignoring routing error on connectionless protocol\n"); continue; } return error; @@ -980,10 +978,10 @@ static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, ch->rp_vers = txdr_unsigned(vers); ch->rp_proc = txdr_unsigned(procid); - /* rpc_auth part (auth_unix as root) */ + /* rpc_auth part (auth_null) */ ch->rpc_auth.authtype = rpc_auth_null; -//call->rpc_auth.authlen = 0; + #ifdef CONFIG_NFS_UNIX_AUTH ch->rpc_unix.stamp = txdr_unsigned(1); ch->rpc_unix.hostname = 0; @@ -991,10 +989,10 @@ static void rpcclnt_fmtheader(FAR struct rpc_call_header *ch, ch->rpc_unix.gid = setgid; ch->rpc_unix.gidlist = 0; #endif + /* rpc_verf part (auth_null) */ ch->rpc_verf.authtype = rpc_auth_null; -//call->rpc_verf.authlen = 0; } /* Build the RPC header and fill in the authorization info. */ @@ -1029,24 +1027,6 @@ static int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int ve /* Format the message header */ - rpcclnt_fmtheader(&callmsg->ch, xid, prog, vers, procid); - value->xid = callmsg->ch.rp_xid; - return 0; - } - else if (procid == PMAPPROC_UNSET) - { - /* Copy the variable, caller-provided data into the call message structure */ - - struct rpc_call_pmap *callmsg = (struct rpc_call_pmap *)msgbuf;; - memcpy(&callmsg->pmap, request, *reqlen); - - /* Return the full size of the message (including messages headers) */ - - DEBUGASSERT(*reqlen == sizeof(struct call_args_pmap)); - *reqlen = sizeof(struct rpc_call_pmap); - - /* Format the message header */ - rpcclnt_fmtheader(&callmsg->ch, xid, prog, vers, procid); value->xid = callmsg->ch.rp_xid; return 0; @@ -1097,15 +1077,18 @@ static int rpcclnt_buildheader(struct rpcclnt *rpc, int procid, int prog, int ve { case NFSPROC_CREATE: { - /* Copy the variable, caller-provided data into the call message structure */ + /* Copy the variable length, caller-provided data into the call + * message structure. + */ struct rpc_call_create *callmsg = (struct rpc_call_create *)msgbuf; memcpy(&callmsg->create, request, *reqlen); - /* Return the full size of the message (including messages headers) */ + /* Return the full size of the message (the size of variable data + * plus the size of the messages header). + */ - DEBUGASSERT(*reqlen == sizeof(struct CREATE3args)); - *reqlen = sizeof(struct rpc_call_create); + *reqlen += sizeof(struct rpc_call_header); /* Format the message header */