> From: Paul Eggert [mailto:egg...@cs.ucla.edu] > Sent: Monday, December 19, 2011 6:29 PM > To: Joachim Schmitz > Cc: 10...@debbugs.gnu.org; bug-gnulib@gnu.org > Subject: Re: bug#10305: coreutils-8.14, "rm -r" fails with EBADF > > On 12/19/11 00:11, Joachim Schmitz wrote: > > So it [opendirat] goes into fdopendir(), fdopendir_with_dup(), > > rpl_dup(), the real dup() (disguised as dup_nothrow(), with success), > > _gl_register_dup(), nothing but success, no suspicious activity against fd. > > > > Then it [fdopendir_with_dup] calls close(3) !!! > > Yes, that's what I'd expect. fdopendir_with_dup sees that fd is 3 and dupfd > is 4. > So it invokes close (3) and then fd_clone_opendir (4, ...) because it wants > fd_clone_opendir to open a file (getting fd 3) and then operate on fd 3. > > then close(4) (the fd from the dup()) errno set to ENOTSUP > > Sorry, you've jumped ahead too fast for me to follow. As I understand it, > fd_clone_opendir (4, ...) should first try openat_proc_name (..., 4, "."), > which > should fail;
Yes, it does (try and fail) > it should then try _gl_directory_name (4), and this should return the > name "D" of the directory. It does. > fd_clone_opendir should then invoke opendir ("D"), > which should then open the directory, it does > internally get file descriptor 3, and then > return a nonnull DIR * pointer that is based on file descriptor 3; this is > the value > that fd_clone_opendir should return back to fdopendir_with_dup. It calls dirfd() with that DIR *, that calls DIR_TO_FD(), which return -1 and sets errno to ENOTSUP Then dirfd() get called again and fails again. close (3), calls fs_clone_opendir() and as dupfd is 4 but older_dupfd is -1, it calls close(4) and sets errno to ENTOSUP (from save_errno) > So when fdopendir_with_dup later does that close(4), it should be OK. > since the directory is still open on file descriptor 3. As I see it we now have fds 3 and 4 closed. > When you say that errno is set to ENOTSUP, though, that suggests that my > analysis is wrong and fd_clone_opendir returns NULL with errno == ENOTSUP. > Can you please investigate why that might be? Ah, should have read to the end first... OK back a couple steps... Hmm DIR_TO_FD() is : #define DIR_TO_FD(Dir_p) -1 In config.h: /* the name of the file descriptor member of DIR */ /* #undef DIR_FD_MEMBER_NAME */ #ifdef DIR_FD_MEMBER_NAME # define DIR_TO_FD(Dir_p) ((Dir_p)->DIR_FD_MEMBER_NAME) #else # define DIR_TO_FD(Dir_p) -1 #endif So fd_clone_dir() does not return NULL, but has errno set to ENTOSUP. Our "struct DIR" has 2 shorts and one long, with funny names dd1, dd2 and dd3... looking at their content: nothing looks like a proper fd (values 7, 257 and 135067072, respectively) Where to go now? Resorting to wild guesses, I tried all 3 members of struct DIR as DIF_FD_MEMBER_NAME, no change to the EBADF