current repository: stat() doesn't set inode number correctly for magic devices

Jonathan Kamens
Mon Oct 29 12:02:00 GMT 2001

With the current repository, if you call stat() on a device, e.g.,
"/dev/null", the returned stat structure will have st_ino set to 0.
If you open() the same device and then call fstat() on it, the
returned stat structure will have st_ino correctly set to a non-zero
value.  This is demonstrated by the program below.

The problem is that the namehash field of the fhandler structure is
only set when open() is called.  It is not set when the various
constructors for magic devices, e.g.,
fhandler_dev_null::fhandler_dev_null, are called.

This bug causes "echo foo > /dev/null" to fail in bash, because bash
stats a file before opening it, fstats it afterwards, and then
compares the inode numbers from before and after to confirm that it
hasn't been swapped out from under it.

I'm not submitting a patch because I've been unable to convince myself
where the correct place to fix this is.  I suspect Corinna has an
opinion, since she just wrote this code, so she should probably be the
one to figure it out :-).

When I was thinking about how this might be fixed, I wanted to avoid
adding separate calls to hash_path_name in every one of the
constructors for magic devices, so I thought that the correct place to
fix this would be in build_fhandler_from_name.  Unfortunately, it
can't be done there because "namehash" is a private field and there's
no public setter for it.  I don't know which is the most appropriate
fix -- adding separate calls to hash_path_name to set the hash in
every one of the device constructors; adding a public setter for the
namehash field so that it can be set from buildhandler_from_name;
making namehash a public field so it can be set directly; or some
other solution I haven't considered.

This probably needs to be fixed before 1.3.4 is released (sorry!).



#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>

#define STATFILE "/dev/null"

  struct stat buf;
  int r = stat(STATFILE, &buf);
  int fd;

  if (r < 0) {

  printf("inode number of unopened %s is %d\n", STATFILE, buf.st_ino);

  fd = open(STATFILE, O_RDONLY, 0);
  if (fd < 0) {

  r = fstat(fd, &buf);
  if (r < 0) {
  printf("inode number of opened %s is %d\n", STATFILE, buf.st_ino);


More information about the Cygwin-developers mailing list