> Am 24.05.2025 um 10:36 schrieb Paul Eggert <egg...@cs.ucla.edu>: > > On 2025-05-24 00:51, Peter Dyballa wrote: >> You are saying that the GNUlib function target_directory_operand() is known >> to fail when the target of cp or mv is a file? So I do not need to debug >> further? > > No, I'm saying that target_directory_operand is supposed to fail if it's > given the name of a regular file. (It should succeed only on directories.) > You're reporting that it succeeded, which means there's something wrong here.
This function in lib/targetdir.c, target_directory_operand(), seems to work OK: 63 if (must_be_working_directory (file)) evaluates to false 72 if (!O_DIRECTORY) evaluates to false – and we come to: 88 if (try_to_open) 89 { 90 fd = open (file, O_PATHSEARCH | O_DIRECTORY); 91 92 /* On platforms lacking O_PATH, using O_SEARCH | O_DIRECTORY to 93 open an overly-protected non-directory can fail with either 94 EACCES or ENOTDIR. Prefer ENOTDIR as it makes for better 95 diagnostics. */ 96 if (O_PATHSEARCH == O_SEARCH && fd < 0 && errno == EACCES) 97 errno = (((O_DIRECTORY ? stat (file, st) : stat_result) == 0 98 && !S_ISDIR (st->st_mode)) 99 ? ENOTDIR : EACCES); 100 } open() on line #90 returns 7, so the if on line #96 evaluates to false and we're on line 117 return fd - (AT_FDCWD == -1 && fd < 0); AT_FDCWD is replaced by a large negative value (found by pre-processing the source) and fd is larger than 0: how can an integer minus a logical expression, that evaluates to FALSE, be evaluated and returned? (Because TRUE and FALSE are some integer values…) Anyway, back in mv.c fd is still 7. And we come to function target_dirfd_valid() in lib/targetdir.h (no openat in Tiger): 29 /* Return a file descriptor open to FILE, for use in openat. 30 As an optimization, return AT_FDCWD if FILE must be the working directory. 31 As a side effect, possibly set *ST to the file's status. 32 Fail and set errno if FILE is not a directory. 33 On failure return -2 if AT_FDCWD is -1, -1 otherwise. */ 34 extern int target_directory_operand (char const *file, struct stat *st); 35 36 /* Return true if FD represents success for target_directory_operand. */ 37 TARGETDIR_INLINE _GL_ATTRIBUTE_PURE bool 38 target_dirfd_valid (int fd) 39 { 40 return fd != -1 - (AT_FDCWD == -1); 41 } In pre-processed output of src/mv.c is this line: 14590 return fd != -1 - ((-3041965) == -1); This is TRUE minus FALSE, isn't it? It must be true – because Gdb executes this block in src/mv.c: 461 { 462 x.rename_errno = -1; 463 target_dirfd = fd; 464 target_directory = lastfile; 465 n_files--; 466 } And the target file has turned into a target directory… Is the old way of checking with S_IFDIR and stat() or fstat() too out-fashioned? Why is the value of O_DIRECTORY used for complicated different things when it can be used directly? Besides, the decisive function, target_dirfd_valid(), seems to check only if the file descriptor is valid. I cannot see that it makes a distinction whether fd is that of a(n ordinary) file or a directory. -- Greetings Pete No one is patriotic about taxes. – George Orwell, Orwell Diaries 1938-1942, (1940-08-09)