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