diff --git a/ChangeLog b/ChangeLog index fbde23e..c22e07d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2009-04-26 Andreas Gruenbacher + * src/inp.c (get_input_file), src/pch.c (there_is_another_patch, + intuit_diff_type): Use lstat instead of stat. This causes patch to + refuse patching symlinks (get_input_file() will refuse to read them). + * src/util.c (create_backup): Refuse to create backups of symlinks. + * tests/symlinks: New test case. + * tests/Makefile.am (TESTS): Add test case. + * bootstrap.conf: Use the gnulib lstat module. + * src/pch.c (intuit_diff_type): Only check for reversed patches when the input file is patchable in the first place. diff --git a/bootstrap.conf b/bootstrap.conf index 1d4ddc5..b5c061f 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -33,6 +33,7 @@ getopt-gnu gettime git-version-gen hash +lstat malloc memchr minmax diff --git a/src/inp.c b/src/inp.c index a96b9a7..bf01c53 100644 --- a/src/inp.c +++ b/src/inp.c @@ -143,7 +143,7 @@ get_input_file (char const *filename, char const *outname) char *getbuf; if (inerrno == -1) - inerrno = stat (filename, &instat) == 0 ? 0 : errno; + inerrno = lstat (filename, &instat) == 0 ? 0 : errno; /* Perhaps look for RCS or SCCS versions. */ if (patch_get diff --git a/src/patch.c b/src/patch.c index f3415dc..158cfcd 100644 --- a/src/patch.c +++ b/src/patch.c @@ -479,7 +479,7 @@ main (int argc, char **argv) struct stat oldst; int olderrno; - olderrno = stat (rej, &oldst) ? errno : 0; + olderrno = lstat (rej, &oldst) ? errno : 0; if (olderrno && olderrno != ENOENT) write_fatal (); if (! olderrno && file_already_seen (&oldst)) diff --git a/src/pch.c b/src/pch.c index 47e4ee8..cebbe83 100644 --- a/src/pch.c +++ b/src/pch.c @@ -283,7 +283,7 @@ there_is_another_patch (bool need_header) { inname = savebuf (buf, t - buf); inname[t - buf - 1] = 0; - if (stat (inname, &instat) == 0) + if (lstat (inname, &instat) == 0) { inerrno = 0; invc = -1; @@ -656,7 +656,7 @@ intuit_diff_type (bool need_header) if (! stat_errno[i]) st[i] = st[i0]; } - else if (stat (p_name[i], &st[i]) != 0) + else if (lstat (p_name[i], &st[i]) != 0) stat_errno[i] = errno; else { @@ -747,7 +747,7 @@ intuit_diff_type (bool need_header) { if (inname) { - inerrno = stat (inname, &instat) == 0 ? 0 : errno; + inerrno = lstat (inname, &instat) == 0 ? 0 : errno; if (inerrno || S_ISREG (instat.st_mode)) maybe_reverse (inname, inerrno, inerrno || instat.st_size == 0); } diff --git a/src/util.c b/src/util.c index 5fc2a19..e8a9c4c 100644 --- a/src/util.c +++ b/src/util.c @@ -157,7 +157,10 @@ create_backup (char *to, struct stat *to_st, int *to_errno, to_st = &tmp_st; to_errno = &tmp_errno; } - *to_errno = stat (to, to_st) == 0 ? 0 : errno; + *to_errno = lstat (to, to_st) == 0 ? 0 : errno; + + if (! to_errno && ! S_ISREG (to_st->st_mode)) + fatal ("File %s is not a regular file -- can't create backup", to); if (! *to_errno && file_already_seen (to_st)) { diff --git a/tests/Makefile.am b/tests/Makefile.am index bf26e7f..76c936a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -38,6 +38,7 @@ TESTS = \ reject-format \ remember-backup-files \ remember-reject-files \ + symlinks \ unmodified-files XFAIL_TESTS = \ diff --git a/tests/symlinks b/tests/symlinks new file mode 100644 index 0000000..3472791 --- /dev/null +++ b/tests/symlinks @@ -0,0 +1,76 @@ +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# Copying and distribution of this file, with or without modification, +# in any medium, are permitted without royalty provided the copyright +# notice and this notice are preserved. + +# Symlink related tests + +. $srcdir/test-lib.sh + +require_cat +use_local_patch +use_tmpdir + +# ============================================================== + +cat > create.diff < f +ncheck 'ln -s f l' + +check 'patch < create.diff || echo "Status: $?"' < f +ncheck 'ln -s f l' + +cat > modify.diff < f +ncheck 'ln -s f l' + +cat > delete.diff <