diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2006-09-16 20:03:56 +0000 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2006-09-16 20:03:56 +0000 |
commit | b67faf329cebf0805b2b73cc775ccfc7a05390de (patch) | |
tree | 61071dc36a049a4685e757f637bc36ac928ade0e /src/install.c | |
parent | adbad7626cbbf81745482b4ddb4a0bcea97a6db6 (diff) | |
download | coreutils-b67faf329cebf0805b2b73cc775ccfc7a05390de.tar.xz |
* NEWS: Document that mkdir -p and install -d now fork on occasion.
* bootstrap.conf (gnulib_modules): Add savewd.
* src/install.c: Include savewd.h.
(process_dir): New function.
(main, install_file_in_file_parents): Use it, along with the new
savewd module, to avoid some race conditions.
* src/mkdir.c: Include savewd.h.
(struct mkdir_options): New members make_ancestor_function, mode,
mode_bits.
(make_ancestor): Return 1 if the resulting directory is not readable.
(process_dir): New function.
(main): Use it, along with new savewd module, to avoid some
race conditions. Fill in new slots of struct mkdir_options, so
that callees get the values.
* tests/install/basic-1: Test for coreutils 5.97 bug that was
fixed in coreutils 6.0, and which should still be fixed with
this change.
* tests/mkdir/p-3: Likewise.
Diffstat (limited to 'src/install.c')
-rw-r--r-- | src/install.c | 67 |
1 files changed, 48 insertions, 19 deletions
diff --git a/src/install.c b/src/install.c index 78fa28e0b..9c5150fbc 100644 --- a/src/install.c +++ b/src/install.c @@ -35,6 +35,7 @@ #include "mkdir-p.h" #include "modechange.h" #include "quote.h" +#include "savewd.h" #include "stat-time.h" #include "utimens.h" #include "xstrtol.h" @@ -193,11 +194,23 @@ target_directory_operand (char const *file) return is_a_dir; } +/* Process a command-line file name, for the -d option. */ +static int +process_dir (char *dir, struct savewd *wd, void *options) +{ + return (make_dir_parents (dir, wd, + make_ancestor, options, + dir_mode, announce_mkdir, + dir_mode_bits, owner_id, group_id, false) + ? EXIT_SUCCESS + : EXIT_FAILURE); +} + int main (int argc, char **argv) { int optc; - bool ok = true; + int exit_status = EXIT_SUCCESS; const char *specified_mode = NULL; bool make_backups = false; char *backup_suffix_string; @@ -361,13 +374,7 @@ main (int argc, char **argv) get_ids (); if (dir_arg) - { - int i; - for (i = 0; i < n_files; i++) - ok &= make_dir_parents (file[i], make_ancestor, &x, - dir_mode, announce_mkdir, - dir_mode_bits, owner_id, group_id, false); - } + exit_status = savewd_process_files (n_files, file, process_dir, &x); else { /* FIXME: it's a little gross that this initialization is @@ -376,23 +383,22 @@ main (int argc, char **argv) if (!target_directory) { - if (mkdir_and_install) - ok = install_file_in_file_parents (file[0], file[1], &x); - else - ok = install_file_in_file (file[0], file[1], &x); + if (! (mkdir_and_install + ? install_file_in_file_parents (file[0], file[1], &x) + : install_file_in_file (file[0], file[1], &x))) + exit_status = EXIT_FAILURE; } else { int i; dest_info_init (&x); for (i = 0; i < n_files; i++) - { - ok &= install_file_in_dir (file[i], target_directory, &x); - } + if (! install_file_in_dir (file[i], target_directory, &x)) + exit_status = EXIT_FAILURE; } } - exit (ok ? EXIT_SUCCESS : EXIT_FAILURE); + exit (exit_status); } /* Copy file FROM onto file TO, creating any missing parent directories of TO. @@ -402,13 +408,36 @@ static bool install_file_in_file_parents (char const *from, char *to, struct cp_options *x) { - if (mkancesdirs (to, make_ancestor, x) != 0) + bool save_working_directory = + ! (IS_ABSOLUTE_FILE_NAME (from) && IS_ABSOLUTE_FILE_NAME (to)); + int status = EXIT_SUCCESS; + + struct savewd wd; + savewd_init (&wd); + if (! save_working_directory) + savewd_finish (&wd); + + if (mkancesdirs (to, &wd, make_ancestor, x) == -1) { error (0, errno, _("cannot create directory %s"), to); - return false; + status = EXIT_FAILURE; + } + + if (save_working_directory) + { + int restore_result = savewd_restore (&wd, status); + int restore_errno = errno; + savewd_finish (&wd); + if (EXIT_SUCCESS < restore_result) + return false; + if (restore_result < 0 && status == EXIT_SUCCESS) + { + error (0, restore_errno, _("cannot create directory %s"), to); + return false; + } } - return install_file_in_file (from, to, x); + return (status == EXIT_SUCCESS && install_file_in_file (from, to, x)); } /* Copy file FROM onto file TO and give TO the appropriate |