From owner-freebsd-hackers@FreeBSD.ORG Fri May 8 03:07:47 2009 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DE3A61065672 for ; Fri, 8 May 2009 03:07:47 +0000 (UTC) (envelope-from kientzle@freebsd.org) Received: from kientzle.com (kientzle.com [66.166.149.50]) by mx1.freebsd.org (Postfix) with ESMTP id 92CB28FC25 for ; Fri, 8 May 2009 03:07:47 +0000 (UTC) (envelope-from kientzle@freebsd.org) Received: (from root@localhost) by kientzle.com (8.14.3/8.14.3) id n4837loT010654 for freebsd-hackers@freebsd.org; Thu, 7 May 2009 20:07:47 -0700 (PDT) (envelope-from kientzle@freebsd.org) Received: from dark.x.kientzle.com (fw2.kientzle.com [10.123.1.2]) by kientzle.com with SMTP id 2ni49tfrgu5h5pr23if86uhb62; for freebsd-hackers@freebsd.org; Thu, 07 May 2009 20:07:46 -0700 (PDT) (envelope-from kientzle@freebsd.org) Message-ID: <4A03A202.2050101@freebsd.org> Date: Thu, 07 May 2009 20:07:46 -0700 From: Tim Kientzle User-Agent: Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.8.1.21) Gecko/20090409 SeaMonkey/1.1.15 MIME-Version: 1.0 To: "'freebsd-hackers@freebsd.org'" Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: fdescfs brokenness X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 08 May 2009 03:07:48 -0000 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 #include #include #include #include #include #include #include #include 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); }