Colin Percival recently pointed out some issues
with tar and fdescfs.  Part of the problem
here is tar; I need to rethink some of the
traversal logic.

But fdescfs is really wonky:

 * This is a nit, but:  ls /dev/fd/18 should not
   return EBADF; it should return ENOENT, just
   like any other reference to a non-existent filename.
   (Just because a filename reflects a file descriptor
   does not mean it is a file descriptor.)

 * The fairly routine recursive directory walker
   below gets hung in fdescfs.  It appears that
   the two opendir() invocations active at the
   same time interfere with each other.

 * A similar chdir()-based version of the directory
   walker below breaks badly; you can chdir() into
   a directory under /dev/fd, but you can't chdir("..")
   to get back out of it.  (This is the particular
   problem that tar is running afoul of.)

 * Running "find /dev/fd" generates bogus ENOENT errors
   because you can opendir() a directory inside of /dev/fd,
   and read the entries, but you can't access those entries
   because path searches don't work through fdescfs.

I think the right solution here is to add a VOP_ACCESS
handler to fdescfs that bars all access to directory
nodes under /dev/fd.  Basically, if your program has a
directory open, that should be reflected as a directory
node that you can't do anything with.  The current implementation
allows you to chdir(), opendir(), etc, those directory
nodes, but the machinery to fully support those operations
is missing so they just screw things up.

I have a candidate vop_access handler partly written, but I'm
a little new to filesystem work, so it will take me
a little while to satisfy myself that it works.

/*
 *  Non-chdir directory walker.
 */
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static char curpath[512];

void
visit(char *f, int depth)
{
        DIR *d;
        struct dirent *dp;
        size_t l = strlen(curpath);

        strcat(curpath, "/");
        strcat(curpath, f);
        printf("%3d: %s\n", depth, curpath);

        d = opendir(curpath);
        if (d != NULL) {
                while ((dp = readdir(d)) != NULL) {
                        if (dp->d_name[0] == '.')
                                continue;
                        visit(dp->d_name, depth + 1);
                }
                closedir(d);
        }
        curpath[l] = '\0';
}

int
main(int argc, char **argv)
{
        visit("/dev/fd", 0);
        exit(0);
}
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"

Reply via email to