diff options
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | src/inp.c | 3 | ||||
-rw-r--r-- | src/patch.c | 4 | ||||
-rw-r--r-- | src/pch.c | 4 | ||||
-rw-r--r-- | src/util.c | 44 | ||||
-rw-r--r-- | src/util.h | 4 | ||||
-rw-r--r-- | tests/unmodified-files | 4 |
7 files changed, 51 insertions, 24 deletions
@@ -48,6 +48,18 @@ * src/util.h: Replace memory_fatal() with xalloc_die(). * src/pch.c: Don't leak memory with strlen (base_name (...)). + * src/util.c (create_file): Add to_dir_known_to_exist argument and + try to create parent directories when set and the create failed with + ENOENT. + (copy_file, create_backup_copy): Pass the new to_dir_known_to_exist + argument through. + (create_backup): Don't assume the target directory exists when making + a backup copy. + * src/util.h (create_file, copy_file): Change the declarations. + * src/patch.c, src/pch.c, src/inp.c: In the calls to create_file() and + copy_file(), assume the parent directory exists. + * tests/unmodified-files: Test the create_backup() fix. + 2009-04-04 Andreas Gruenbacher <agruen@suse.de> * pch.c (another_hunk): Add (back) the line number ranges to the @@ -340,7 +340,8 @@ plan_b (char const *filename) pfatal ("Can't open file %s", quotearg (filename)); exclusive = TMPINNAME_needs_removal ? 0 : O_EXCL; TMPINNAME_needs_removal = 1; - tifd = create_file (TMPINNAME, O_RDWR | O_BINARY | exclusive, (mode_t) 0); + tifd = create_file (TMPINNAME, O_RDWR | O_BINARY | exclusive, (mode_t) 0, + true); i = 0; len = 0; maxlen = 1; diff --git a/src/patch.c b/src/patch.c index 241e8fa..d8c7390 100644 --- a/src/patch.c +++ b/src/patch.c @@ -443,7 +443,7 @@ main (int argc, char **argv) { if (! written_to_rejname) { - copy_file (TMPREJNAME, rejname, 0, 0, 0666); + copy_file (TMPREJNAME, rejname, 0, 0, 0666, true); written_to_rejname = true; } else @@ -1323,7 +1323,7 @@ static FILE * create_output_file (char const *name, int open_flags) { int fd = create_file (name, O_WRONLY | binary_transput | open_flags, - instat.st_mode); + instat.st_mode, true); FILE *f = fdopen (fd, binary_transput ? "wb" : "w"); if (! f) pfatal ("Can't create file %s", quotearg (name)); @@ -129,7 +129,7 @@ open_patch_file (char const *filename) TMPPATNAME_needs_removal = 1; pfp = fdopen (create_file (TMPPATNAME, O_RDWR | O_BINARY | exclusive, - (mode_t) 0), + (mode_t) 0, true), "w+b"); if (!pfp) pfatal ("Can't open stream for file %s", quotearg (TMPPATNAME)); @@ -2033,7 +2033,7 @@ do_ed_script (FILE *ofp) int exclusive = TMPOUTNAME_needs_removal ? 0 : O_EXCL; assert (! inerrno); TMPOUTNAME_needs_removal = 1; - copy_file (inname, TMPOUTNAME, 0, exclusive, instat.st_mode); + copy_file (inname, TMPOUTNAME, 0, exclusive, instat.st_mode, true); sprintf (buf, "%s %s%s", ed_program, verbosity == VERBOSE ? "" : "- ", TMPOUTNAME); fflush (stdout); @@ -127,11 +127,12 @@ contains_slash (const char *s) } static void -create_backup_copy (char const *from, char const *to, struct stat *st) +create_backup_copy (char const *from, char const *to, struct stat *st, + bool to_dir_known_to_exist) { struct utimbuf utimbuf; - copy_file (from, to, 0, 0, st->st_mode); + copy_file (from, to, 0, 0, st->st_mode, to_dir_known_to_exist); utimbuf.actime = st->st_atime; utimbuf.modtime = st->st_mtime; if (utime (to, &utimbuf) != 0) @@ -223,7 +224,7 @@ create_backup (char *to, struct stat *to_st, int *to_errno, pfatal ("Can't close file %s", quotearg (bakname)); } else if (leave_original) - create_backup_copy (to, bakname, to_st); + create_backup_copy (to, bakname, to_st, try_makedirs_errno == 0); else { if (debug & 4) @@ -238,7 +239,8 @@ create_backup (char *to, struct stat *to_st, int *to_errno, } else if (errno == EXDEV) { - create_backup_copy (to, bakname, to_st); + create_backup_copy (to, bakname, to_st, + try_makedirs_errno == 0); unlink (to); break; } @@ -301,9 +303,7 @@ move_file (char const *from, int volatile *from_needs_removal, else if (errno != ENOENT) pfatal ("Can't remove file %s", quotearg (to)); } - if (! to_dir_known_to_exist) - makedirs (to); - copy_file (from, to, &tost, 0, mode); + copy_file (from, to, &tost, 0, mode, to_dir_known_to_exist); insert_file (&tost); return; } @@ -335,16 +335,29 @@ move_file (char const *from, int volatile *from_needs_removal, we can read and write the file and that the file is not executable. Return the file descriptor. */ int -create_file (char const *file, int open_flags, mode_t mode) +create_file (char const *file, int open_flags, mode_t mode, + bool to_dir_known_to_exist) { + int try_makedirs_errno = to_dir_known_to_exist ? 0 : ENOENT; int fd; mode |= S_IRUSR | S_IWUSR; mode &= ~ (S_IXUSR | S_IXGRP | S_IXOTH); - if (! (O_CREAT && O_TRUNC)) - close (creat (file, mode)); - fd = open (file, O_CREAT | O_TRUNC | open_flags, mode); - if (fd < 0) - pfatal ("Can't create file %s", quotearg (file)); + do + { + if (! (O_CREAT && O_TRUNC)) + close (creat (file, mode)); + fd = open (file, O_CREAT | O_TRUNC | open_flags, mode); + if (fd < 0) + { + char *f; + if (errno != try_makedirs_errno) + pfatal ("Can't create file %s", quotearg (file)); + f = xstrdup (file); + makedirs (f); + free (f); + try_makedirs_errno = 0; + } + } while (fd < 0); return fd; } @@ -371,14 +384,15 @@ copy_to_fd (const char *from, int tofd) void copy_file (char const *from, char const *to, struct stat *tost, - int to_flags, mode_t mode) + int to_flags, mode_t mode, bool to_dir_known_to_exist) { int tofd; if (debug & 4) say ("Copying file %s to %s\n", quotearg_n (0, from), quotearg_n (1, to)); - tofd = create_file (to, O_WRONLY | O_BINARY | to_flags, mode); + tofd = create_file (to, O_WRONLY | O_BINARY | to_flags, mode, + to_dir_known_to_exist); copy_to_fd (from, tofd); if ((tost && fstat (tofd, tost) != 0) || close (tofd) != 0) @@ -52,11 +52,11 @@ char *savebuf (char const *, size_t); char *savestr (char const *); char const *version_controller (char const *, bool, struct stat const *, char **, char **); bool version_get (char const *, char const *, bool, bool, char const *, struct stat *); -int create_file (char const *, int, mode_t); +int create_file (char const *, int, mode_t, bool); int systemic (char const *); char *format_linenum (char[LINENUM_LENGTH_BOUND + 1], LINENUM); void Fseek (FILE *, file_offset, int); -void copy_file (char const *, char const *, struct stat *, int, mode_t); +void copy_file (char const *, char const *, struct stat *, int, mode_t, bool); void append_to_file (char const *, char const *); void exit_with_signal (int) __attribute__ ((noreturn)); void ignore_signals (void); diff --git a/tests/unmodified-files b/tests/unmodified-files index 8d5bd5c..c970c3d 100644 --- a/tests/unmodified-files +++ b/tests/unmodified-files @@ -29,7 +29,7 @@ EOF echo three > a ln a a.first -check 'patch -b a < a.diff || echo "Status: $?"' <<EOF +check 'patch -b -B backup/ a < a.diff || echo "Status: $?"' <<EOF patching file a Hunk #1 FAILED at 1. 1 out of 1 hunk FAILED -- saving rejects to file a.rej @@ -38,7 +38,7 @@ EOF ncheck 'test a -ef a.first' -check 'cat a.orig' <<EOF +check 'cat backup/a' <<EOF three EOF |