Proposed extension to stat(1)

Gleb Kurtsou gleb at freebsd.org
Thu May 8 07:44:23 UTC 2014


On (07/05/2014 11:12), Thomas Quinot wrote:
> I'm proposing the addition of a command line switch -H to stat(1),
> causing arguments to be interpreted as NFS file handles instead of file
> names. This comes in handy when investigating NFS load issues.
> 
> (A further possible extension would be to optionally include information
> from statfs/fhstatfs, but that's next on my list :) ).
> 
> Thomas.
> 
> Index: usr.bin/stat/stat.1
> ===================================================================
> --- usr.bin/stat/stat.1	(révision 265192)
> +++ usr.bin/stat/stat.1	(copie de travail)
> @@ -38,7 +38,7 @@
>  .Nd display file status
>  .Sh SYNOPSIS
>  .Nm
> -.Op Fl FLnq
> +.Op Fl FHLnq
>  .Op Fl f Ar format | Fl l | r | s | x
>  .Op Fl t Ar timefmt
>  .Op Ar
> @@ -124,6 +124,12 @@
>  .Fl F
>  implies
>  .Fl l .
> +.It Fl H
> +Treat each argument as the hexadecimal representation of an NFS file handle,
> +and use
> +.Xr fhstat 2
> +instead of
> +.Xr lstat 2 .

Noting that it requires root may be helpful. 'each argument' confused me
a lot.

>  .It Fl L
>  Use
>  .Xr stat 2
> Index: usr.bin/stat/stat.c
> ===================================================================
> --- usr.bin/stat/stat.c	(révision 265192)
> +++ usr.bin/stat/stat.c	(copie de travail)
> @@ -50,6 +50,7 @@
>  #include <sys/param.h>
>  #include <sys/types.h>
>  #include <sys/stat.h>
> +#include <sys/mount.h>
>  
>  #include <ctype.h>
>  #include <err.h>
> @@ -203,9 +204,10 @@
>  {
>  	struct stat st;
>  	int ch, rc, errs, am_readlink;
> -	int lsF, fmtchar, usestat, fn, nonl, quiet;
> +	int lsF, fmtchar, usestat, nfs_handle, fn, nonl, quiet;
>  	const char *statfmt, *options, *synopsis;
>  	char dname[sizeof _PATH_DEV + SPECNAMELEN] = _PATH_DEV;
> +        fhandle_t fhnd;

whitespace?

>  	const char *file;
>  
>  	am_readlink = 0;
> @@ -212,6 +214,7 @@
>  	lsF = 0;
>  	fmtchar = '\0';
>  	usestat = 0;
> +        nfs_handle = 0;

whitespace?

>  	nonl = 0;
>  	quiet = 0;
>  	linkfail = 0;
> @@ -226,9 +229,9 @@
>  		fmtchar = 'f';
>  		quiet = 1;
>  	} else {
> -		options = "f:FlLnqrst:x";
> +		options = "f:FHlLnqrst:x";
>  		synopsis = "[-FLnq] [-f format | -l | -r | -s | -x] "
> -		    "[-t timefmt] [file ...]";
> +		    "[-t timefmt] [file|handle ...]";
>  	}
>  
>  	while ((ch = getopt(argc, argv, options)) != -1)
> @@ -236,6 +239,9 @@
>  		case 'F':
>  			lsF = 1;
>  			break;
> +                case 'H':
> +			nfs_handle = 1;
> +			break;

Whitespace.

>  		case 'L':
>  			usestat = 1;
>  			break;
> @@ -320,8 +326,33 @@
>  				file = "(stdin)";
>  			rc = fstat(STDIN_FILENO, &st);
>  		} else {
> +			int j;
> +			char *inval;
> +
>  			file = argv[0];
> -			if (usestat) {
> +			if (nfs_handle) {
> +				rc = 0;
> +				bzero (&fhnd, sizeof fhnd);

Style. Extra space after bzero.

> +				j = MIN(2 * sizeof fhnd, strlen(file));

sizeof style.

> +				if (j & 1) {
> +					rc = -1;
> +				} else {
> +					while (j) {
> +						((char*) &fhnd)[j / 2 - 1] = strtol(&file[j - 2], &inval, 16);

It's badly broken:
- Result for excessive "01" vs "0102" will differ in
  strlen(file) > sizeof(fhnd) * 2 case.
- Will "+1-2" be considered a valid file handle?
- why do we care about strlen(file) != sizeof(fh) case?


> +						if (inval != NULL) {

According to strtol(3) such error handling is insufficient.
At least it won't work for strlen(file) > sizeof(fhnd) * 2 case.


> +							rc = -1;
> +							break;
> +						}
> +						argv[0][j - 2] = '\0';

First we initialize file = argv[0].
Then we set every third character in argv[0] to '\0'.
Afterwards file is used to print error message or actual result.

> +						j -= 2;
> +					}
> +					if (!rc)

style. rc is not bool.

> +						rc = fhstat(&fhnd, &st);
> +					else
> +						errno = EINVAL;
> +				}
> +
> +			} else if (usestat) {
>  				/*
>  				 * Try stat() and if it fails, fall back to
>  				 * lstat() just in case we're examining a


More information about the freebsd-arch mailing list