Hello, Paul Eggert wrote, On 01/24/2013 12:03 PM: > Thanks, could you please try the following patch? > This is a gnulib patch, so it also fixes modules/fdopendir -- > you needn't worry about that part of the patch, > as it doesn't apply to coreutils. > I'm CC'ing this possible patch to bug-gnulib to give > the Gnulib people a heads-up.
With this patch, the recursive loop is gone, but it leads to another bug: descending into the directory (due to "-r") doesn't work. Example: ========== ## ## The 'setup' ## $ echo $D /Users/admin/Projects/coreutils-8.20.90-e27bfd/src $ pwd /Users/admin/Projects/coreutils-8.20.90-e27bfd/src/c $ ls -ld . d-wx--xr-x 2 admin staff 68 Jan 24 14:27 . $ ls -lh ls: .: Permission denied ## target directory is empty - works OK $ mkdir $D/a $ $D/rm -r $D/a ## target directory is not empty (and current directory unreadable) - fails $ mkdir -p $D/a/1 $ $D/rm -r $D/a /Users/admin/Projects/coreutils-8.20.90-e27bfd/src/rm: cannot remove '/Users/admin/Projects/coreutils-8.20.90-e27bfd/src/a': Permission denied ## Trying again from a readable directory - works. $ cd $D $ $D/rm -r $D/a ========== The immediate error happens in "unlinkat()", but I'm guessing the deeper cause is that somehow "a" is being deleted before "a/1" ? === $ pwd /Users/admin/Projects/coreutils-8.20.90-e27bfd/src/c $ ls -lh ls: .: Permission denied $ ls -ld $D/a drwxr-xr-x 3 admin staff 102 Jan 24 15:15 /Users/admin/Projects/coreutils-8.20.90-e27bfd/src/a $ ls -ld $D/a/1 drwxr-xr-x 2 admin staff 68 Jan 24 15:15 /Users/admin/Projects/coreutils-8.20.90-e27bfd/src/a/1 $ gdb /Users/admin/Projects/coreutils-8.20.90-e27bfd/src/rm (gdb) b unlinkat (gdb) r -r /Users/admin/Projects/coreutils-8.20.90-e27bfd/src/a ## ## Just before the call to "unlinkat" ## Breakpoint 1, excise (fts=0x100100080, ent=0x100100210, x=0x7fff5fbff9f0, is_dir=true) at remove.c:369 369 if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0) (gdb) bt #0 excise (fts=0x100100080, ent=0x100100210, x=0x7fff5fbff9f0, is_dir=true) at remove.c:369 #1 0x0000000100003244 in rm_fts (fts=0x100100080, ent=0x100100210, x=0x7fff5fbff9f0) at remove.c:509 #2 0x0000000100003487 in rm (file=0x7fff5fbffa70, x=0x7fff5fbff9f0) at remove.c:568 #3 0x0000000100001b10 in main (argc=3, argv=0x7fff5fbffa60) at rm.c:349 (gdb) p *fts $1 = { fts_cur = 0x100100210, fts_child = 0x0, fts_array = 0x0, fts_dev = 234881026, fts_path = 0x100800000 "/Users/admin/Projects/coreutils-8.20.90-e27bfd/src/a", fts_rfd = 0, fts_cwd_fd = -3041965, fts_pathlen = 1280, fts_nitems = 0, fts_compar = 0, fts_options = 28, fts_leaf_optimization_works_ht = 0x0, fts_cycle = { ht = 0x100100460, state = 0x100100460 }, fts_fd_ring = { ir_data = {-1, -1, -1, -1}, ir_default_val = -1, ir_front = 0, ir_back = 0, ir_empty = true } } (gdb) p *ent $2 = { fts_cycle = 0x0, fts_parent = 0x100100100, fts_link = 0x0, fts_dirp = 0x0, fts_number = 0, fts_pointer = 0x0, fts_accpath = 0x100800000 "/Users/admin/Projects/coreutils-8.20.90-e27bfd/src/a", fts_path = 0x100800000 "/Users/admin/Projects/coreutils-8.20.90-e27bfd/src/a", fts_errno = 13, fts_symfd = 0, fts_pathlen = 52, fts_fts = 0x100100080, fts_level = 0, fts_namelen = 1, fts_n_dirs_remaining = 1, fts_info = 4, fts_flags = 0, fts_instr = 3, fts_statp = {{ st_dev = 234881026, st_mode = 16877, st_nlink = 3, st_ino = 4157629, st_uid = 502, st_gid = 20, st_rdev = 0, st_atimespec = { tv_sec = 1359058544, tv_nsec = 0 }, st_mtimespec = { tv_sec = 1359058544, tv_nsec = 0 }, st_ctimespec = { tv_sec = 1359058544, tv_nsec = 0 }, st_birthtimespec = { tv_sec = 1359058544, tv_nsec = 0 }, st_size = 102, st_blocks = 0, st_blksize = 4096, st_flags = 0, st_gen = 0, st_lspare = 0, st_qspare = {0, 0} }}, fts_name = "a" } (gdb) p flag $3 = 1 ## ## Inside "unlinkat()", (assuming "CALL_FUNC" calls MacOS's "unlink(2)" ?) - this fails. ## (gdb) n Breakpoint 2, unlinkat (fd=-3041965, file=0x100800000 "/Users/admin/Projects/coreutils-8.20.90-e27bfd/src/a", flag=1) at at-func.c:72 72 VALIDATE_FLAG (flag); (gdb) n 74 if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file)) (gdb) n 75 return CALL_FUNC (file); (gdb) n 72 VALIDATE_FLAG (flag); (gdb) n ## ## The rest is error handling in remove.c/rm.c ## excise (fts=0x100100080, ent=0x100100210, x=0x7fff5fbff9f0, is_dir=true) at remove.c:384 384 if (errno == EROFS) (gdb) n 392 if (ignorable_missing (x, errno)) (gdb) n 400 if (ent->fts_info == FTS_DNR (gdb) n 404 errno = ent->fts_errno; (gdb) n 405 error (0, errno, _("cannot remove %s"), quote (ent->fts_path)); (gdb) n /Users/admin/Projects/coreutils-8.20.90-e27bfd/src/rm: cannot remove '/Users/admin/Projects/coreutils-8.20.90-e27bfd/src/a': Permission denied 406 mark_ancestor_dirs (ent); (gdb) n 407 return RM_ERROR; (gdb) n 377 return RM_OK; (gdb) n rm_fts (fts=0x100100080, ent=0x100100210, x=0x7fff5fbff9f0) at remove.c:434 434 return RM_ERROR; (gdb) n rm (file=0x7fff5fbffa70, x=0x7fff5fbff9f0) at remove.c:570 570 assert (VALID_STATUS (s)); (gdb) n 571 UPDATE_STATUS (rm_status, s); (gdb) n 557 ent = fts_read (fts); (gdb) n 558 if (ent == NULL) (gdb) n 560 if (errno != 0) (gdb) n 574 if (fts_close (fts) != 0) (gdb) n 581 return rm_status; (gdb) n main (argc=3, argv=0x7fff5fbffa60) at rm.c:350 350 assert (VALID_STATUS (status)); (gdb) n 351 exit (status == RM_ERROR ? EXIT_FAILURE : EXIT_SUCCESS); (gdb) n Program exited with code 01. (gdb) === > > By the way, do you happen to know why OS X doesn't > yet support fdopendir? It's been in the standard for ages. > Do the OSX maintainers plan to implement it eventually? > I'm not familiar with OS-X, and rarely use it. I just happen to have a Mac Mini and wanted to put the latest GNU software on it...