Re: open() of device special files

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Aug 15, 2011 at 10:03:49PM -0700, Myklebust, Trond wrote:
> > -----Original Message-----
> > From: J. Bruce Fields [mailto:bfields@xxxxxxxxxxxx]
> > The long description of NFS4ERR_INVAL from rfc 3530:
> > 
> > 	"Invalid argument or unsupported argument for an operation. Two
> > 	examples are attempting a READLINK on an object other than a
> > 	symbolic link or specifying a value for an enum field that is
> > 	not defined in the protocol (e.g., nfs_ftype4)."
> > 
> > So the text does recommend NFS4ERR_INVAL for the case where the
> > operation doesn't make sense for the type of object given.  (In the
> > readlink example there's no pathname resolution, though).
> 
> Right. In the case of readlink, you pass a file handle, which points to
> an object for which you _can_ check the type before attempting the
> readlink operation.
> 
> OPEN (and LOOKUP, RENAME, REMOVE,...) takes a filename, which could
> point to anything. There is no way for the client to know a priori the
> type of the object being pointed to.
> 
> > EINVAL seems to be used in the kernel for some such cases as well
> (e.g.
> > attempt to truncate a device special file).
> 
> My reading of the manpages and the posix spec is that truncate() will
> return EINVAL if and only if the length argument is wrong. Ftruncate()
> will in addition return EINVAL if the file descriptor points to a
> non-regular file (the assumption presumably being that you should have
> tried to fstat() first).
> 
> IOW: The criterion that they apply is that "if the user should have
> known better" then EINVAL is correct. If there is no way for the user to
> be sure a priori, then it is not. So, for instance, rmdir() will not
> return EINVAL if you try to apply it to a file.

That's perfectly logical, but, taking the example of (f)truncate:

	- truncate(2) as far as I can tell doesn't specify behavior for
	  truncate in this case, only for ftruncate.

	- http://pubs.opengroup.org/onlinepubs/009695399/ says behavior
	  is undefined for ftruncate, and says nothing for truncate.

	- linux actually returns EINVAL in both cases:

	  $ sudo mknod tmp c 1 3 -m 666
	  $ make trunc-vs-ftrunc
	  cc     trunc-vs-ftrunc.c   -o trunc-vs-ftrunc
	  $ ./trunc-vs-ftrunc tmp
	  trunc-vs-ftrunc: truncate: Invalid argument
	  trunc-vs-ftrunc: ftruncate: Invalid argument

But I don't really know why I'm arguing here--I don't disagree.  You
have a reasonable way to define EINVAL.  This just appears to be easy to
get wrong....

--b.

trunc-vs-ftrunc.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <err.h>

int main(int argc, char *argv[])
{
	int fd, ret;

	if (argc != 2)
		errx(1, "usage: %s path\n", argv[0]);
	ret = truncate(argv[1], 0);
	if (ret)
		warn("truncate");
	fd = open(argv[1], O_WRONLY);
	if (fd < 0)
		err(1, "open");
	ret = ftruncate(fd, 0);
	if (ret)
		warn("ftruncate");
}
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux