summaryrefslogtreecommitdiff
path: root/rtemsNfs/src/nfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'rtemsNfs/src/nfs.c')
-rw-r--r--rtemsNfs/src/nfs.c251
1 files changed, 155 insertions, 96 deletions
diff --git a/rtemsNfs/src/nfs.c b/rtemsNfs/src/nfs.c
index 73f4354..c95e39a 100644
--- a/rtemsNfs/src/nfs.c
+++ b/rtemsNfs/src/nfs.c
@@ -1,4 +1,4 @@
-/* nfs.c,v 1.33 2004/09/22 22:10:41 till Exp */
+/* $Id$ */
/* NFS client implementation for RTEMS; hooks into the RTEMS filesystem */
@@ -173,7 +173,8 @@ static struct timeval _nfscalltimeout = { 10, 0 }; /* {secs, us } */
RTEMS_INHERIT_PRIORITY | \
RTEMS_BINARY_SEMAPHORE)
-#define LOCK(s) do { rtems_semaphore_obtain((s), \
+#define LOCK(s) do { \
+ rtems_semaphore_obtain((s), \
RTEMS_WAIT, \
RTEMS_NO_TIMEOUT); \
} while (0)
@@ -323,7 +324,7 @@ DirInfo dip;
/* we pass a 0 size - size is unused since
* we always pass a non-NULL pointer
*/
- if ( !xdr_pointer(xdrs, (caddr_t*)&dip, 0 /* size */, xdr_dir_info_entry) )
+ if ( !xdr_pointer(xdrs, (void*)&dip, 0 /* size */, (xdrproc_t)xdr_dir_info_entry) )
return FALSE;
}
@@ -457,12 +458,12 @@ xdr_serporid(XDR *xdrs, serporid *objp)
/* assume reading a long word is atomic */
#define READ_LONG_IS_ATOMIC
-typedef rtems_unsigned32 TimeStamp;
+typedef uint32_t TimeStamp;
static inline TimeStamp
nowSeconds(void)
{
-register rtems_unsigned32 rval;
+register uint32_t rval;
#ifndef READ_LONG_IS_ATOMIC
rtems_interrupt_level l;
@@ -486,12 +487,12 @@ typedef struct NfsRec_ {
/* statistics; how many NfsNodes are
* currently alive.
*/
- int nodesInUse;
+ volatile int nodesInUse;
#if DEBUG & DEBUG_COUNT_NODES
/* statistics; how many 'NfsNode.str'
* strings are currently allocated.
*/
- int stringsInUse;
+ volatile int stringsInUse;
#endif
/* A small number who uniquely
* identifies a mounted NFS within
@@ -582,10 +583,10 @@ static int
nfs_sattr(NfsNode node, sattr *arg, u_long mask);
extern struct _rtems_filesystem_operations_table nfs_fs_ops;
-extern struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers;
-extern struct _rtems_filesystem_file_handlers_r nfs_dir_file_handlers;
-extern struct _rtems_filesystem_file_handlers_r nfs_link_file_handlers;
-extern rtems_driver_address_table drvNfs;
+static struct _rtems_filesystem_file_handlers_r nfs_file_file_handlers;
+static struct _rtems_filesystem_file_handlers_r nfs_dir_file_handlers;
+static struct _rtems_filesystem_file_handlers_r nfs_link_file_handlers;
+static rtems_driver_address_table drvNfs;
int
nfsMountsShow(FILE*);
@@ -818,6 +819,7 @@ static NfsNode
nfsNodeCreate(Nfs nfs, nfs_fh *fh)
{
NfsNode rval = malloc(sizeof(*rval));
+unsigned long flags;
#if DEBUG & DEBUG_TRACK_NODES
fprintf(stderr,"NFS: creating a node\n");
@@ -826,11 +828,11 @@ NfsNode rval = malloc(sizeof(*rval));
if (rval) {
if (fh)
memcpy( &SERP_FILE(rval), fh, sizeof(*fh) );
+ rtems_interrupt_disable(flags);
+ nfs->nodesInUse++;
+ rtems_interrupt_enable(flags);
rval->nfs = nfs;
rval->str = 0;
- LOCK(nfsGlob.lock);
- nfs->nodesInUse++;
- UNLOCK(nfsGlob.lock);
} else {
errno = ENOMEM;
}
@@ -842,6 +844,8 @@ NfsNode rval = malloc(sizeof(*rval));
static void
nfsNodeDestroy(NfsNode node)
{
+unsigned long flags;
+
#if DEBUG & DEBUG_TRACK_NODES
fprintf(stderr,"NFS: destroying a node\n");
#endif
@@ -852,13 +856,13 @@ nfsNodeDestroy(NfsNode node)
xdr_free(xdr_serporid, &node->serporid);
#endif
- LOCK(nfsGlob.lock);
- node->nfs->nodesInUse--;
+ rtems_interrupt_disable(flags);
+ node->nfs->nodesInUse--;
#if DEBUG & DEBUG_COUNT_NODES
- if (node->str)
- node->nfs->stringsInUse--;
+ if (node->str)
+ node->nfs->stringsInUse--;
#endif
- UNLOCK(nfsGlob.lock);
+ rtems_interrupt_enable(flags);
if (node->str)
free(node->str);
@@ -897,9 +901,11 @@ NfsNode rval = nfsNodeCreate(node->nfs, 0);
return 0;
}
#if DEBUG & DEBUG_COUNT_NODES
- LOCK(nfsGlob.lock);
+ { unsigned long flags;
+ rtems_interrupt_disable(flags);
node->nfs->stringsInUse++;
- UNLOCK(nfsGlob.lock);
+ rtems_interrupt_enable(flags);
+ }
#endif
}
@@ -928,8 +934,8 @@ nfsInit(int smallPoolDepth, int bigPoolDepth)
{
entry dummy;
- fprintf(stderr,"This is RTEMS-NFS Release SSRL_RTEMS_20041202\n");
- fprintf(stderr,"(nfs.c,v 1.33 2004/09/22 22:10:41 till Exp)\n\n");
+ fprintf(stderr,"This is RTEMS-NFS Release $Name$\n");
+ fprintf(stderr,"($Id$)\n\n");
fprintf(stderr,"Till Straumann, Stanford/SLAC/SSRL 2002\n");
fprintf(stderr,"See LICENSE file for licensing info\n");
@@ -956,7 +962,7 @@ entry dummy;
dummy.nextentry = 0;
dummy.name = "somename"; /* guess average length of a filename */
- dirres_entry_size = xdr_sizeof(xdr_entry, &dummy);
+ dirres_entry_size = xdr_sizeof((xdrproc_t)xdr_entry, &dummy);
assert( smallPool = rpcUdpXactPoolCreate(
NFS_PROGRAM,
@@ -1144,8 +1150,8 @@ updateAttr(NfsNode node, int force)
) {
if ( nfscall(node->nfs->server,
NFSPROC_GETATTR,
- xdr_nfs_fh, &SERP_FILE(node),
- xdr_attrstat, &node->serporid) )
+ (xdrproc_t)xdr_nfs_fh, &SERP_FILE(node),
+ (xdrproc_t)xdr_attrstat, &node->serporid) )
return -1;
if ( NFS_OK != node->serporid.status ) {
@@ -1221,7 +1227,7 @@ int len;
strncpy(host, chpt, len);
host[len]=0;
- if ( ! inet_aton(host, &psa->sin_addr) ) {
+ if ( ! inet_pton(AF_INET, host, &psa->sin_addr) ) {
errno = ENXIO;
return -1;
}
@@ -1333,6 +1339,10 @@ NfsNode node = pathloc->node_access;
char *p = malloc(MAXPATHLEN+1);
Nfs nfs = (Nfs)pathloc->mt_entry->fs_info;
RpcUdpServer server = nfs->server;
+unsigned long flags;
+#if DEBUG & DEBUG_COUNT_NODES
+unsigned long niu,siu;
+#endif
if ( !p ) {
e = ENOMEM;
@@ -1340,8 +1350,16 @@ RpcUdpServer server = nfs->server;
}
strcpy(p, pathname);
+ LOCK(nfsGlob.lock);
+ node = nfsNodeClone(node);
+ UNLOCK(nfsGlob.lock);
+
+ /* from here on, the NFS is protected from being unmounted
+ * since the node refcount is > 1
+ */
+
/* clone the node */
- if ( !(node = nfsNodeClone(node)) ) {
+ if ( !node ) {
/* nodeClone sets errno */
goto cleanup;
}
@@ -1482,8 +1500,8 @@ RpcUdpServer server = nfs->server;
if ( nfscall(server,
NFSPROC_LOOKUP,
- xdr_diropargs, &SERP_FILE(node),
- xdr_serporid, &node->serporid) ||
+ (xdrproc_t)xdr_diropargs, &SERP_FILE(node),
+ (xdrproc_t)xdr_serporid, &node->serporid) ||
NFS_OK != (errno=node->serporid.status) ) {
e = errno;
goto cleanup;
@@ -1518,8 +1536,8 @@ RpcUdpServer server = nfs->server;
if ( (nfscall(nfs->server,
NFSPROC_GETATTR,
- xdr_nfs_fh, &SERP_FILE(node),
- xdr_attrstat, &node->serporid) && !errno && (errno = EIO)) ||
+ (xdrproc_t)xdr_nfs_fh, &SERP_FILE(node),
+ (xdrproc_t)xdr_attrstat, &node->serporid) && !errno && (errno = EIO)) ||
(NFS_OK != (errno=node->serporid.status) ) ) {
goto cleanup;
}
@@ -1538,9 +1556,9 @@ RpcUdpServer server = nfs->server;
/* increment the 'in use' counter since we return one more
* reference to the root node
*/
- LOCK(nfsGlob.lock);
+ rtems_interrupt_disable(flags);
nfs->nodesInUse++;
- UNLOCK(nfsGlob.lock);
+ rtems_interrupt_enable(flags);
nfsNodeDestroy(node);
@@ -1558,9 +1576,9 @@ RpcUdpServer server = nfs->server;
if (node->args.name) {
if (node->str) {
#if DEBUG & DEBUG_COUNT_NODES
- LOCK(nfsGlob.lock);
+ rtems_interrupt_disable(flags);
nfs->stringsInUse--;
- UNLOCK(nfsGlob.lock);
+ rtems_interrupt_enable(flags);
#endif
free(node->str);
}
@@ -1571,9 +1589,9 @@ RpcUdpServer server = nfs->server;
}
#if DEBUG & DEBUG_COUNT_NODES
- LOCK(nfsGlob.lock);
+ rtems_interrupt_disable(flags);
nfs->stringsInUse++;
- UNLOCK(nfsGlob.lock);
+ rtems_interrupt_enable(flags);
#endif
}
@@ -1584,6 +1602,13 @@ RpcUdpServer server = nfs->server;
cleanup:
free(p);
+#if DEBUG & DEBUG_COUNT_NODES
+ /* cache counters; nfs may be unmounted by other thread after the last
+ * node is destroyed
+ */
+ niu = nfs->nodesInUse;
+ siu = nfs->stringsInUse;
+#endif
if (node) {
nfsNodeDestroy(node);
pathloc->node_access = 0;
@@ -1591,7 +1616,7 @@ cleanup:
#if DEBUG & DEBUG_COUNT_NODES
fprintf(stderr,
"leaving evalpath, in use count is %i nodes, %i strings\n",
- nfs->nodesInUse, nfs->stringsInUse);
+ niu,siu);
#endif
if (e) {
#if DEBUG & DEBUG_EVALPATH
@@ -1657,8 +1682,8 @@ NfsNode tNode = to_loc->node_access;
if ( nfscall(tNode->nfs->server,
NFSPROC_LINK,
- xdr_linkargs, &SERP_FILE(tNode),
- xdr_nfsstat, &status)
+ (xdrproc_t)xdr_linkargs, &SERP_FILE(tNode),
+ (xdrproc_t)xdr_nfsstat, &status)
|| (NFS_OK != (errno = status))
) {
#if DEBUG & DEBUG_SYSCALLS
@@ -1697,8 +1722,8 @@ char *name = NFSPROC_REMOVE == proc ?
if ( nfscall(nfs->server,
proc,
- xdr_diropargs, &node->args,
- xdr_nfsstat, &status)
+ (xdrproc_t)xdr_diropargs, &node->args,
+ (xdrproc_t)xdr_nfsstat, &status)
|| (NFS_OK != (errno = status))
) {
#if DEBUG & DEBUG_SYSCALLS
@@ -1739,26 +1764,31 @@ static int nfs_freenode(
{
Nfs nfs = ((NfsNode)pathloc->node_access)->nfs;
+#if DEBUG & DEBUG_COUNT_NODES
+ /* print counts at entry where they are > 0 so 'nfs' is safe from being destroyed
+ * and there's no race condition
+ */
+ fprintf(stderr,
+ "entering freenode, in use count is %i nodes, %i strings\n",
+ nfs->nodesInUse,
+ nfs->stringsInUse);
+#endif
+
/* never destroy the root node; it is released by the unmount
* code
*/
if (locIsRoot(pathloc)) {
+ unsigned long flags;
/* just adjust the references to the root node but
* don't really release it
*/
- LOCK(nfsGlob.lock);
+ rtems_interrupt_disable(flags);
nfs->nodesInUse--;
- UNLOCK(nfsGlob.lock);
+ rtems_interrupt_enable(flags);
} else {
nfsNodeDestroy(pathloc->node_access);
pathloc->node_access = 0;
}
-#if DEBUG & DEBUG_COUNT_NODES
- fprintf(stderr,
- "leaving freenode, in use count is %i nodes, %i strings\n",
- nfs->nodesInUse,
- nfs->stringsInUse);
-#endif
return 0;
}
@@ -1874,8 +1904,8 @@ char *path = mt_entry->dev;
*/
if ( nfscall(nfsServer,
NFSPROC_NULL,
- xdr_void, 0,
- xdr_void, 0) ) {
+ (xdrproc_t)xdr_void, 0,
+ (xdrproc_t)xdr_void, 0) ) {
fputs("NFS Ping ",stderr);
fwrite(host, 1, path-host-1, stderr);
@@ -1896,9 +1926,9 @@ char *path = mt_entry->dev;
stat = mntcall( &saddr,
MOUNTPROC_MNT,
- xdr_dirpath,
+ (xdrproc_t)xdr_dirpath,
&path,
- xdr_fhstatus,
+ (xdrproc_t)xdr_fhstatus,
&fhstat,
uid,
gid );
@@ -1975,11 +2005,11 @@ char *path = mt_entry->dev;
int nodesInUse;
u_long uid,gid;
- LOCK(nfsGlob.lock);
- nodesInUse = ((Nfs)mt_entry->fs_info)->nodesInUse;
- UNLOCK(nfsGlob.lock);
+LOCK(nfsGlob.llock);
+ nodesInUse = ((Nfs)mt_entry->fs_info)->nodesInUse;
if (nodesInUse > 1 /* one ref to the root node used by us */) {
+ UNLOCK(nfsGlob.llock);
fprintf(stderr,
"Refuse to unmount; there are still %i nodes in use (1 used by us)\n",
nodesInUse);
@@ -1990,13 +2020,14 @@ u_long uid,gid;
stat = mntcall( &saddr,
MOUNTPROC_UMNT,
- xdr_dirpath, &path,
- xdr_void, 0,
+ (xdrproc_t)xdr_dirpath, &path,
+ (xdrproc_t)xdr_void, 0,
uid,
gid
);
if (stat) {
+ UNLOCK(nfsGlob.llock);
fprintf(stderr,"NFS UMOUNT -- %s\n", clnt_sperrno(stat));
errno = EIO;
return -1;
@@ -2008,9 +2039,8 @@ u_long uid,gid;
nfsDestroy(mt_entry->fs_info);
mt_entry->fs_info = 0;
- LOCK(nfsGlob.llock);
- nfsGlob.num_mounted_fs--;
- UNLOCK(nfsGlob.llock);
+ nfsGlob.num_mounted_fs--;
+UNLOCK(nfsGlob.llock);
return 0;
}
@@ -2084,8 +2114,8 @@ mode_t type = S_IFMT & mode;
if ( nfscall( node->nfs->server,
NFSPROC_CREATE,
- xdr_createargs, &SERP_FILE(node),
- xdr_diropres, &res)
+ (xdrproc_t)xdr_createargs, &SERP_FILE(node),
+ (xdrproc_t)xdr_diropres, &res)
|| (NFS_OK != (errno = res.status)) ) {
#if DEBUG & DEBUG_SYSCALLS
perror("nfs_mknod");
@@ -2145,8 +2175,8 @@ NfsNode node = loc->node_access;
if ( nfscall( node->nfs->server,
NFSPROC_SYMLINK,
- xdr_symlinkargs, &SERP_FILE(node),
- xdr_nfsstat, &status)
+ (xdrproc_t)xdr_symlinkargs, &SERP_FILE(node),
+ (xdrproc_t)xdr_nfsstat, &status)
|| (NFS_OK != (errno = status)) ) {
#if DEBUG & DEBUG_SYSCALLS
perror("nfs_symlink");
@@ -2174,16 +2204,16 @@ int rval;
if ( (rval = nfscall(nfs->server,
NFSPROC_READLINK,
- xdr_nfs_fh, &SERP_FILE(node),
- xdr_readlinkres_strbuf, &rr)) ) {
+ (xdrproc_t)xdr_nfs_fh, &SERP_FILE(node),
+ (xdrproc_t)xdr_readlinkres_strbuf, &rr)) ) {
if (wasAlloced)
- xdr_free( xdr_strbuf, (caddr_t)&rr.strbuf );
+ xdr_free( (xdrproc_t)xdr_strbuf, (caddr_t)&rr.strbuf );
}
if (NFS_OK != rr.status) {
if (wasAlloced)
- xdr_free( xdr_strbuf, (caddr_t)&rr.strbuf );
+ xdr_free( (xdrproc_t)xdr_strbuf, (caddr_t)&rr.strbuf );
rtems_set_errno_and_return_minus_one(rr.status);
}
@@ -2413,10 +2443,10 @@ struct rtems_libio_tt {
rtems_driver_name_t *driver;
off_t size; /* size of file */
off_t offset; /* current offset into file */
- unsigned32 flags;
+ uint32_t flags;
rtems_filesystem_location_info_t pathinfo;
Objects_Id sem;
- unsigned32 data0; /* private to "driver" */
+ uint32_t data0; /* private to "driver" */
void *data1; /* ... */
void *file_info; /* used by file handlers */
rtems_filesystem_file_handlers_r *handlers; /* type specific handlers */
@@ -2427,8 +2457,8 @@ struct rtems_libio_tt {
static int nfs_file_open(
rtems_libio_t *iop,
const char *pathname,
- unsigned32 flag,
- unsigned32 mode
+ uint32_t flag,
+ uint32_t mode
)
{
iop->file_info = 0;
@@ -2443,8 +2473,8 @@ static int nfs_file_open(
static int nfs_dir_open(
rtems_libio_t *iop,
const char *pathname,
- unsigned32 flag,
- unsigned32 mode
+ uint32_t flag,
+ uint32_t mode
)
{
NfsNode node = iop->pathinfo.node_access;
@@ -2499,7 +2529,7 @@ static int nfs_dir_close(
static int nfs_file_read(
rtems_libio_t *iop,
void *buffer,
- unsigned32 count
+ uint32_t count
)
{
readres rr;
@@ -2517,8 +2547,8 @@ Nfs nfs = node->nfs;
if ( nfscall( nfs->server,
NFSPROC_READ,
- xdr_readargs, &SERP_FILE(node),
- xdr_readres, &rr) ) {
+ (xdrproc_t)xdr_readargs, &SERP_FILE(node),
+ (xdrproc_t)xdr_readres, &rr) ) {
return -1;
}
@@ -2544,7 +2574,7 @@ Nfs nfs = node->nfs;
static int nfs_dir_read(
rtems_libio_t *iop,
void *buffer,
- unsigned32 count
+ uint32_t count
)
{
DirInfo di = iop->file_info;
@@ -2585,8 +2615,8 @@ RpcUdpServer server = ((Nfs)iop->pathinfo.mt_entry->fs_info)->server;
if ( nfscall(
server,
NFSPROC_READDIR,
- xdr_readdirargs, &di->readdirargs,
- xdr_dir_info, di) ) {
+ (xdrproc_t)xdr_readdirargs, &di->readdirargs,
+ (xdrproc_t)xdr_dir_info, di) ) {
return -1;
}
@@ -2603,7 +2633,7 @@ RpcUdpServer server = ((Nfs)iop->pathinfo.mt_entry->fs_info)->server;
static int nfs_file_write(
rtems_libio_t *iop,
const void *buffer,
- unsigned32 count
+ uint32_t count
)
{
NfsNode node = iop->pathinfo.node_access;
@@ -2613,8 +2643,16 @@ int e;
if (count > NFS_MAXDATA)
count = NFS_MAXDATA;
+
SERP_ARGS(node).writearg.beginoffset = 0xdeadbeef;
- SERP_ARGS(node).writearg.offset = iop->offset;
+ if ( LIBIO_FLAGS_APPEND & iop->flags ) {
+ if ( updateAttr(node, 0) ) {
+ return -1;
+ }
+ SERP_ARGS(node).writearg.offset = SERP_ATTR(node).size;
+ } else {
+ SERP_ARGS(node).writearg.offset = iop->offset;
+ }
SERP_ARGS(node).writearg.totalcount = 0xdeadbeef;
SERP_ARGS(node).writearg.data.data_len = count;
SERP_ARGS(node).writearg.data.data_val = (void*)buffer;
@@ -2625,8 +2663,8 @@ int e;
if ( nfscall( nfs->server,
NFSPROC_WRITE,
- xdr_writeargs, &SERP_FILE(node),
- xdr_attrstat, &node->serporid) ) {
+ (xdrproc_t)xdr_writeargs, &SERP_FILE(node),
+ (xdrproc_t)xdr_attrstat, &node->serporid) ) {
return -1;
}
@@ -2649,7 +2687,7 @@ int e;
#ifdef DECLARE_BODY
static int nfs_file_ioctl(
rtems_libio_t *iop,
- unsigned32 command,
+ uint32_t command,
void *buffer
)DECLARE_BODY
#else
@@ -2671,6 +2709,21 @@ static int nfs_file_lseek(
length,
whence);
#endif
+ if ( SEEK_END == whence ) {
+ /* rtems (4.6.2) libcsupport code 'lseek' uses iop->size to
+ * compute the offset. We don't want to track the file size
+ * by updating 'iop->size' constantly.
+ * Since lseek is the only place using iop->size, we work
+ * around this by tweaking the offset here...
+ */
+ NfsNode node = iop->pathinfo.node_access;
+ fattr *fa = &SERP_ATTR(node);
+
+ if (updateAttr(node, 0 /* only if old */)) {
+ return -1;
+ }
+ iop->offset = fa->size;
+ }
/* this is particularly easy :-) */
return iop->offset;
@@ -2837,24 +2890,26 @@ u_int mode;
if (mask & SATTR_MODE) {
mode &= S_IFMT;
mode |= arg->mode & ~S_IFMT;
+ } else {
+ mode = -1;
}
SERP_ARGS(node).sattrarg.attributes.mode = mode;
SERP_ARGS(node).sattrarg.attributes.uid =
- (mask & SATTR_UID) ? arg->uid : SERP_ATTR(node).uid;
+ (mask & SATTR_UID) ? arg->uid : -1;
SERP_ARGS(node).sattrarg.attributes.gid =
- (mask & SATTR_GID) ? arg->gid : SERP_ATTR(node).gid;
+ (mask & SATTR_GID) ? arg->gid : -1;
SERP_ARGS(node).sattrarg.attributes.size =
- (mask & SATTR_SIZE) ? arg->size : SERP_ATTR(node).size;
+ (mask & SATTR_SIZE) ? arg->size : -1;
if (mask & SATTR_ATIME)
t = arg->atime;
else if (mask & SATTR_TOUCHA)
t = nfsnow;
else
- t = SERP_ATTR(node).atime;
+ t.seconds = t.useconds = -1;
SERP_ARGS(node).sattrarg.attributes.atime = t;
if (mask & SATTR_ATIME)
@@ -2862,15 +2917,15 @@ u_int mode;
else if (mask & SATTR_TOUCHA)
t = nfsnow;
else
- t = SERP_ATTR(node).mtime;
+ t.seconds = t.useconds = -1;
SERP_ARGS(node).sattrarg.attributes.mtime = t;
node->serporid.status = NFS_OK;
if ( nfscall( node->nfs->server,
NFSPROC_SETATTR,
- xdr_sattrargs, &SERP_FILE(node),
- xdr_attrstat, &node->serporid) ) {
+ (xdrproc_t)xdr_sattrargs, &SERP_FILE(node),
+ (xdrproc_t)xdr_attrstat, &node->serporid) ) {
#if DEBUG & DEBUG_SYSCALLS
fprintf(stderr,
"nfs_sattr (mask 0x%08x): %s",
@@ -2919,9 +2974,13 @@ static int nfs_file_ftruncate(
sattr arg;
arg.size = length;
+ /* must not modify any other attribute; if we are not the owner
+ * of the file or directory but only have write access changing
+ * any attribute besides 'size' will fail...
+ */
return nfs_sattr(iop->pathinfo.node_access,
&arg,
- SATTR_SIZE | SATTR_TOUCH);
+ SATTR_SIZE);
}
#define nfs_dir_ftruncate 0