diff options
author | Michael Kelly <mike@weatherwax.co.uk> | 2025-07-20 14:19:11 +0200 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2025-07-20 14:19:11 +0200 |
commit | 529b93b8f6cc94830325cfde1b237f0ca04af38e (patch) | |
tree | 2d1319b3725a1481737bf4f553173d3d8236d302 /nfs/nfs.c | |
parent | 2c39bb58dfbcc018d2f2104d60733e6cf6be4adc (diff) |
nfs: fix the handling of replies to MKNOD and SYMLINK
The Linux NFS server does not accept a setting of file size to 0 for
sockets and FIFOs so there is code to strip that for those cases. I also
spotted that the file modification times were not being applied to a
created file so there is now just one rpc to set all file attributes using
xdr_encode_create_state(). This sets the times to be server time which is
appropriate for a new file (even though it was created in the previous RPC
call). The previous code was supplying the 'gid' based on that returned by
the 'stat' but I don't think that can be relied on since the V3 protocol
states that CREATE3 using EXCLUSIVE cannot guarantee any file attributes
until after the SETATTR3.
Diffstat (limited to 'nfs/nfs.c')
-rw-r--r-- | nfs/nfs.c | 32 |
1 files changed, 30 insertions, 2 deletions
@@ -25,6 +25,7 @@ #include <string.h> #include <netinet/in.h> +#include <stdbool.h> #include <stdio.h> #include <sys/sysmacros.h> @@ -179,6 +180,30 @@ xdr_encode_string (int *p, const char *string) return xdr_encode_data (p, string, strlen (string)); } +/* Some NFSv3 rpcs can fail if the file size field + is set within the set attributes unnecessarily. */ +static inline bool +nfs_sattr3_size_needed(mode_t mode, size_t sz) +{ + if (sz == 0) + { + switch (hurd_mode_to_nfs_type (mode)) + { + case NFSOCK: + case NF3FIFO: + /* NFCHR and NFBLK probaly also fall into this + category but as unable to check then leave + those alone. */ + return false; + + default: + break; + } + } + + return true; +} + /* Encode a MODE into an otherwise empty sattr. */ int * xdr_encode_sattr_mode (int *p, mode_t mode) @@ -372,14 +397,17 @@ xdr_encode_sattr_stat (int *p, } else { + bool needs_size = nfs_sattr3_size_needed (st->st_mode, st->st_size); + *(p++) = htonl (1); /* set mode */ *(p++) = htonl (hurd_mode_to_nfs_mode (st->st_mode)); *(p++) = htonl (1); /* set uid */ *(p++) = htonl (st->st_uid); *(p++) = htonl (1); /* set gid */ *(p++) = htonl (st->st_gid); - *(p++) = htonl (1); /* set size */ - p = xdr_encode_64bit (p, st->st_size); + *(p++) = htonl (needs_size); /* set size */ + if (needs_size) + p = xdr_encode_64bit (p, st->st_size); *(p++) = htonl (SET_TO_CLIENT_TIME); /* set atime */ *(p++) = htonl (st->st_atim.tv_sec); *(p++) = htonl (st->st_atim.tv_nsec); |