Thinking about how to make thread-safe the directory-creating parts of cp -r, mv, tar, cpio, and even mkdir -p (i.e., don't change the initial working directory), while remaining efficient even for deep hierarchies, I realized that we need a new function, mkdirat, which I've just checked in to coreutils/lib/mkdirat.c.
Unlike the other openat-like functions, this one is in a separate file, since it's compiled unconditionally, which is because no system provides it, yet... But if my mentioning it to Ulrich works as quickly this time as it did for openat et al, it'll be in glibc by week's end :-) So far, only on Linux+PROC_FS can we emulate this without resorting to the save_cwd/fchdir/restore_cwd crutch. If anyone knows how to do the same thing using /proc on some other type of system, please tell. Note that Solaris seems not to provide this function -- I wonder why. 2005-11-30 Jim Meyering <[EMAIL PROTECTED]> * mkdirat.c (mkdirat): New file and function. * openat.h (mkdirat): Declare. 2005-11-30 Jim Meyering <[EMAIL PROTECTED]> * openat.m4 (gl_FUNC_OPENAT): Require and compile mkdirat.c. Here is the important part of the new file: /* Solaris 10 has no function like this. Create a subdirectory, FILE, with mode MODE, in the directory open on descriptor FD. If possible, do it without changing the working directory. Otherwise, resort to using save_cwd/fchdir, then mkdir/restore_cwd. If either the save_cwd or the restore_cwd fails, then give a diagnostic and exit nonzero. */ int mkdirat (int fd, char const *file, mode_t mode) { struct saved_cwd saved_cwd; int saved_errno; int err; if (fd == AT_FDCWD || IS_ABSOLUTE_FILE_NAME (file)) return mkdir (file, mode); { char *proc_file; BUILD_PROC_NAME (proc_file, fd, file); err = mkdir (proc_file, mode); /* If the syscall succeeds, or if it fails with an unexpected errno value, then return right away. Otherwise, fall through and resort to using save_cwd/restore_cwd. */ if (0 <= err || ! EXPECTED_ERRNO (errno)) return err; } if (save_cwd (&saved_cwd) != 0) openat_save_fail (errno); if (fchdir (fd) != 0) { saved_errno = errno; free_cwd (&saved_cwd); errno = saved_errno; return -1; } err = mkdir (file, mode); saved_errno = (err < 0 ? errno : 0); if (restore_cwd (&saved_cwd) != 0) openat_restore_fail (errno); free_cwd (&saved_cwd); if (saved_errno) errno = saved_errno; return err; } _______________________________________________ bug-gnulib mailing list bug-gnulib@gnu.org http://lists.gnu.org/mailman/listinfo/bug-gnulib