[comp.unix.wizards] ftruncate broken? - Sun-based NFS

mouse@mcgill-vision.UUCP (der Mouse) (07/09/89)

The ftruncate() call appears to be broken on at least some systems with
NFS implementations based on Sun's.  I've tried this on a Sun-3 with
release 3.5 and on a VAX running mtXinu 4.3+NFS.  I also tried it on a
MicroVAX running real 4.3, and it did not exhibit the broken behavior.
But it's not directly an NFS problem, because it happens even when the
file is on a ufs filesystem.

The problem is that ftruncate() fails if the file modes prohibit
writing, even if the file descriptor used does permit writing.  For
example, try the following program on a handy Sun.  Notice that (unless
you try it as super-user), the ftruncate call fails.  Try it on a 4.3
machine, though, and everything's fine.

(I checked the Sun manpage, and there's not even a note in the BUGS
section warning about this, so presumably someone thinks it should
work the way it does on 4.3.)

Anybody have a simple fix?  (Patch a couple of bytes to noops somewhere
in the OBJ/ files perhaps?)  Will it be fixed in newer releases (4.x)?
I'm about ready to try to work out a fix on the mtXinu system, to which
we have source, but that's not much help on the Suns.

	#include <sys/file.h>
	
	int fd;
	char junk[8192];
	
	main()
	{
	 unlink("test.file");
	 fd = open("test.file",O_RDWR|O_CREAT|O_TRUNC,0666);
	 if (fd < 0)
	  { perror("open/create test.file");
	    exit(1);
	  }
	 if (write(fd,&junk[0],8192) != 8192)
	  { perror("write #1");
	    exit(1);
	  }
	 if (fchmod(fd,0444) < 0)
	  { perror("fchmod");
	    exit(1);
	  }
	 if (write(fd,&junk[0],8192) != 8192)
	  { perror("write #2");
	    exit(1);
	  }
	 if (ftruncate(fd,(unsigned long int)16000) < 0)
	  { perror("ftruncate");
	    exit(1);
	  }
	 if (close(fd) < 0)
	  { perror("close");
	    exit(1);
	  }
	 exit(0);
	}

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

guy@auspex.auspex.com (Guy Harris) (07/11/89)

>The problem is that ftruncate() fails if the file modes prohibit
>Anybody have a simple fix?  (Patch a couple of bytes to noops somewhere
>in the OBJ/ files perhaps?)

Sure, you can probably no-op out the code in "ufs_setattr" that calls
"iaccess" to check whether you have write permission.  Of course, this
would let you make NFS RPC calls directly to truncate files to which you
don't have write access, which I suspect you don't want....

>Will it be fixed in newer releases (4.x)?

It's not fixed in 4.0; I've noted the problem to somebody at Sun.  The
problem is that truncating a file should be treated like writing it -
i.e., the permission checks should be made:

	1) at the system call layer (which is already done for both
	   calls)

and

	2) at the NFS server layer (which is already done for "write"
	   but not for "setattr" setting the length)

but *not* at the UFS layer.

I can't see any problems with making the requisite changes (i.e., get
rid of the "iaccess()" call in "ufs_setattr", put in a VOP_ACCESS call in
"rfs_setattr" - i.e., in the server code - if you're trying to set the
size, and make sure there are no *other* calls to VOP_SETATTR that might
set the size and that are relying on the underlying file system to do
any permissions checking), but that doesn't mean no such problems exist,
so be careful.