diff options
-rw-r--r-- | usr.bin/patch/patch.1 | 26 | ||||
-rw-r--r-- | usr.bin/patch/patch.c | 38 | ||||
-rw-r--r-- | usr.bin/patch/pch.c | 10 | ||||
-rw-r--r-- | usr.bin/patch/util.c | 153 | ||||
-rw-r--r-- | usr.bin/patch/util.h | 5 |
5 files changed, 121 insertions, 111 deletions
diff --git a/usr.bin/patch/patch.1 b/usr.bin/patch/patch.1 index de7f5e45aa7..8e4cd81571d 100644 --- a/usr.bin/patch/patch.1 +++ b/usr.bin/patch/patch.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: patch.1,v 1.11 2003/07/24 14:35:22 millert Exp $ +.\" $OpenBSD: patch.1,v 1.12 2003/07/25 02:12:45 millert Exp $ .\" Copyright 1986, Larry Wall .\" .\" Redistribution and use in source and binary forms, with or without @@ -42,10 +42,10 @@ By default, the patched version is put in place of the original, with the original file backed up to the same name with the extension .Qq .orig , or as specified by the -.Fl b , .Fl B , +.Fl V , or -.Fl V +.Fl z options. The extension used for making backup files may also be specified in the .Ev SIMPLE_BACKUP_SUFFIX @@ -192,15 +192,20 @@ mentioned previously. .Pp The options are as follows: .Bl -tag -width Ds -.It Fl b , Fl Fl suffix -Causes the next argument to be interpreted as the backup extension, to be -used in place of -.Qq .orig . +.It Fl b , Fl Fl backup +Save a backup copy of the file before it is modified. +By default the original file is saved with a backup extension of +.Qq .orig +unless the file already has a numbered backup, in which case a numbered +backup is made. +This is equivalent to specifying +.Qo Fl V Ar existing Qc . +This option is currently the default but that will change in a future release. .It Fl B , Fl Fl prefix Causes the next argument to be interpreted as a prefix to the backup file name. If this argument is specified, any argument from -.Fl b +.Fl z will be ignored. .It Fl c , Fl Fl context Forces @@ -401,7 +406,6 @@ Always make numbered backups. .It nil , existing Make numbered backups of files that already have them, simple backups of the others. -This is the default. .It never , simple Always make simple backups. .El @@ -412,6 +416,10 @@ Always make simple backups. Sets internal debugging flags, and is of interest only to .Nm patchers. +.It Fl z , Fl Fl suffix +Causes the next argument to be interpreted as the backup extension, to be +used in place of +.Qq .orig . .El .Sh NOTES FOR PATCH SENDERS There are several things you should bear in mind if you are going to diff --git a/usr.bin/patch/patch.c b/usr.bin/patch/patch.c index 8c067e55a7d..55ea6ce6c14 100644 --- a/usr.bin/patch/patch.c +++ b/usr.bin/patch/patch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: patch.c,v 1.26 2003/07/23 07:31:21 otto Exp $ */ +/* $OpenBSD: patch.c,v 1.27 2003/07/25 02:12:45 millert Exp $ */ /* * patch - a program to apply diffs to original files @@ -27,7 +27,7 @@ */ #ifndef lint -static const char rcsid[] = "$OpenBSD: patch.c,v 1.26 2003/07/23 07:31:21 otto Exp $"; +static const char rcsid[] = "$OpenBSD: patch.c,v 1.27 2003/07/25 02:12:45 millert Exp $"; #endif /* not lint */ #include <sys/types.h> @@ -127,14 +127,19 @@ main(int argc, char *argv[]) else simple_backup_suffix = ORIGEXT; - v = getenv("VERSION_CONTROL"); - backup_type = get_version(v); /* OK to pass NULL. */ - /* parse switches */ Argc = argc; Argv = argv; get_some_switches(); + if (backup_type == none) { + v = getenv("VERSION_CONTROL"); +#ifdef notyet + if (v != NULL) +#endif + backup_type = get_version(v); /* OK to pass NULL. */ + } + /* make sure we clean up /tmp in case of disaster */ set_signals(0); @@ -371,8 +376,9 @@ reinitialize_almost_everything(void) static void get_some_switches(void) { - const char *options = "b:B:cCd:D:eEfF:lnNo:p::r:RstuvV:x:"; + const char *options = "b::B:cCd:D:eEfF:lnNo:p::r:RstuvV:x:z:"; static struct option longopts[] = { + {"backup", no_argument, 0, 'b'}, {"batch", no_argument, 0, 't'}, {"check", no_argument, 0, 'C'}, {"context", no_argument, 0, 'c'}, @@ -393,7 +399,7 @@ get_some_switches(void) {"reverse", no_argument, 0, 'R'}, {"silent", no_argument, 0, 's'}, {"strip", optional_argument, 0, 'p'}, - {"suffix", required_argument, 0, 'b'}, + {"suffix", required_argument, 0, 'z'}, {"unified", no_argument, 0, 'u'}, {"version", no_argument, 0, 'v'}, {"version-control", required_argument, 0, 'V'}, @@ -410,6 +416,18 @@ get_some_switches(void) while ((ch = getopt_long(Argc, Argv, options, longopts, NULL)) != -1) { switch (ch) { case 'b': +#ifdef notyet + if (backup_type == none) + backup_type = numbered_existing; +#endif + if (optarg == NULL) + break; + if (verbose) + say("Warning, the ``-b suffix'' option has been" + " obsoleted by the -z option.\n"); + /* FALLTHROUGH */ + case 'z': + /* must directly follow 'b' case for backwards compat */ simple_backup_suffix = savestr(optarg); break; case 'B': @@ -512,9 +530,9 @@ static __dead void usage(void) { fprintf(stderr, -"usage: patch [-cCeEflnNRstuv] [-b backup-ext] [-B backup-prefix] [-d directory]\n" -" [-D symbol] [-Fmax-fuzz] [-o out-file] [-p[strip-count]]\n" -" [-r rej-name] [-V {numbered,existing,simple}]\n" +"usage: patch [-bcCeEflnNRstuv] [-B backup-prefix] [-d directory] [-D symbol]\n" +" [-Fmax-fuzz] [-o out-file] [-p[strip-count]] [-r rej-name]\n" +" [-V {numbered,existing,simple}] [-z backup-ext]\n" " [origfile [patchfile]]\n"); my_exit(1); } diff --git a/usr.bin/patch/pch.c b/usr.bin/patch/pch.c index e59eec91429..dbe00665af6 100644 --- a/usr.bin/patch/pch.c +++ b/usr.bin/patch/pch.c @@ -1,7 +1,7 @@ -/* $OpenBSD: pch.c,v 1.23 2003/07/22 17:52:20 deraadt Exp $ */ +/* $OpenBSD: pch.c,v 1.24 2003/07/25 02:12:45 millert Exp $ */ #ifndef lint -static const char rcsid[] = "$OpenBSD: pch.c,v 1.23 2003/07/22 17:52:20 deraadt Exp $"; +static const char rcsid[] = "$OpenBSD: pch.c,v 1.24 2003/07/25 02:12:45 millert Exp $"; #endif /* not lint */ #include <sys/types.h> @@ -1315,8 +1315,10 @@ do_ed_script(void) FILE *pipefp; if (!skip_rest_of_patch) { - unlink(TMPOUTNAME); - copy_file(filearg[0], TMPOUTNAME); + if (copy_file(filearg[0], TMPOUTNAME) < 0) { + unlink(TMPOUTNAME); + fatal("can't create temp file %s", TMPOUTNAME); + } if (verbose) snprintf(buf, sizeof buf, "/bin/ed %s", TMPOUTNAME); else diff --git a/usr.bin/patch/util.c b/usr.bin/patch/util.c index a958b480ac5..0874dac002f 100644 --- a/usr.bin/patch/util.c +++ b/usr.bin/patch/util.c @@ -1,7 +1,7 @@ -/* $OpenBSD: util.c,v 1.17 2003/07/22 17:52:20 deraadt Exp $ */ +/* $OpenBSD: util.c,v 1.18 2003/07/25 02:12:45 millert Exp $ */ #ifndef lint -static const char rcsid[] = "$OpenBSD: util.c,v 1.17 2003/07/22 17:52:20 deraadt Exp $"; +static const char rcsid[] = "$OpenBSD: util.c,v 1.18 2003/07/25 02:12:45 millert Exp $"; #endif /* not lint */ #include <sys/param.h> @@ -29,7 +29,6 @@ static const char rcsid[] = "$OpenBSD: util.c,v 1.17 2003/07/22 17:52:20 der int move_file(char *from, char *to) { - char bakname[MAXPATHLEN], *s; int i, fromfd; /* to stdout? */ @@ -48,114 +47,95 @@ move_file(char *from, char *to) close(fromfd); return 0; } + if (backup_file(to) < 0) { + say("Can't backup %s, output is in %s: %s\n", to, from, + strerror(errno)); + return -1; + } +#ifdef DEBUGGING + if (debug & 4) + say("Moving %s to %s.\n", from, to); +#endif + if (rename(from, to) < 0) { + if (errno != EXDEV || copy_file(from, to) < 0) { + say("Can't create %s, output is in %s: %s\n", + to, from, strerror(errno)); + return -1; + } + } + return 0; +} + +/* Backup the original file. */ + +int +backup_file(char *orig) +{ + char bakname[MAXPATHLEN], *s, *simplename; + dev_t orig_device; + ino_t orig_inode; + + if (backup_type == none || stat(orig, &filestat) != 0) + return 0; /* nothing to do */ + orig_device = filestat.st_dev; + orig_inode = filestat.st_ino; + if (origprae) { if (strlcpy(bakname, origprae, sizeof(bakname)) >= sizeof(bakname) || - strlcat(bakname, to, sizeof(bakname)) >= sizeof(bakname)) + strlcat(bakname, orig, sizeof(bakname)) >= sizeof(bakname)) fatal("filename %s too long for buffer\n", origprae); } else { - char *backupname = find_backup_file_name(to); - if (backupname == (char *) 0) + if ((s = find_backup_file_name(orig)) == NULL) fatal("out of memory\n"); - if (strlcpy(bakname, backupname, sizeof(bakname)) >= sizeof(bakname)) - fatal("filename %s too long for buffer\n", backupname); - free(backupname); + if (strlcpy(bakname, s, sizeof(bakname)) >= sizeof(bakname)) + fatal("filename %s too long for buffer\n", s); + free(s); } - if (stat(to, &filestat) == 0) { /* output file exists */ - dev_t to_device = filestat.st_dev; - ino_t to_inode = filestat.st_ino; - char *simplename = bakname; - - for (s = bakname; *s; s++) { - if (*s == '/') - simplename = s + 1; - } - - /* - * Find a backup name that is not the same file. Change the - * first lowercase char into uppercase; if that isn't - * sufficient, chop off the first char and try again. - */ - while (stat(bakname, &filestat) == 0 && - to_device == filestat.st_dev && to_inode == filestat.st_ino) { - /* Skip initial non-lowercase chars. */ - for (s = simplename; *s && !islower(*s); s++) - ; - if (*s) - *s = toupper(*s); - else - memmove(simplename, simplename + 1, - strlen(simplename + 1) + 1); - } - unlink(bakname); + if ((simplename = strrchr(bakname, '/')) != NULL) + simplename = simplename + 1; + else + simplename = bakname; -#ifdef DEBUGGING - if (debug & 4) - say("Moving %s to %s.\n", to, bakname); -#endif - if (link(to, bakname) < 0) { - /* - * Maybe `to' is a symlink into a different file - * system. Copying replaces the symlink with a file; - * using rename would be better. - */ - int tofd, bakfd; - - bakfd = creat(bakname, 0666); - if (bakfd < 0) { - say("Can't backup %s, output is in %s: %s\n", - to, from, strerror(errno)); - return -1; - } - tofd = open(to, O_RDONLY); - if (tofd < 0) - pfatal("internal error, can't open %s", to); - while ((i = read(tofd, buf, sizeof buf)) > 0) - if (write(bakfd, buf, i) != i) - pfatal("write failed"); - close(tofd); - close(bakfd); - } - unlink(to); + /* + * Find a backup name that is not the same file. Change the + * first lowercase char into uppercase; if that isn't + * sufficient, chop off the first char and try again. + */ + while (stat(bakname, &filestat) == 0 && + orig_device == filestat.st_dev && orig_inode == filestat.st_ino) { + /* Skip initial non-lowercase chars. */ + for (s = simplename; *s && !islower(*s); s++) + ; + if (*s) + *s = toupper(*s); + else + memmove(simplename, simplename + 1, + strlen(simplename + 1) + 1); } #ifdef DEBUGGING if (debug & 4) - say("Moving %s to %s.\n", from, to); + say("Moving %s to %s.\n", orig, bakname); #endif - if (link(from, to) < 0) { /* different file system? */ - int tofd; - - tofd = creat(to, 0666); - if (tofd < 0) { - say("Can't create %s, output is in %s: %s\n", - to, from, strerror(errno)); + if (rename(orig, bakname) < 0) { + if (errno != EXDEV || copy_file(orig, bakname) < 0) return -1; - } - fromfd = open(from, O_RDONLY); - if (fromfd < 0) - pfatal("internal error, can't reopen %s", from); - while ((i = read(fromfd, buf, sizeof buf)) > 0) - if (write(tofd, buf, i) != i) - pfatal("write failed"); - close(fromfd); - close(tofd); } - unlink(from); return 0; } /* * Copy a file. */ -void +int copy_file(char *from, char *to) { int tofd, fromfd, i; - tofd = creat(to, 0666); + tofd = open(to, O_CREAT|O_TRUNC|O_WRONLY, 0666); if (tofd < 0) - pfatal("can't create %s", to); - fromfd = open(from, O_RDONLY); + return -1; + fromfd = open(from, O_RDONLY, 0); if (fromfd < 0) pfatal("internal error, can't reopen %s", from); while ((i = read(fromfd, buf, sizeof buf)) > 0) @@ -163,6 +143,7 @@ copy_file(char *from, char *to) pfatal("write to %s failed", to); close(fromfd); close(tofd); + return 0; } /* diff --git a/usr.bin/patch/util.h b/usr.bin/patch/util.h index 17e7747c5a8..41495ea0401 100644 --- a/usr.bin/patch/util.h +++ b/usr.bin/patch/util.h @@ -1,8 +1,9 @@ -/* $OpenBSD: util.h,v 1.8 2003/07/22 17:21:07 deraadt Exp $ */ +/* $OpenBSD: util.h,v 1.9 2003/07/25 02:12:45 millert Exp $ */ char *fetchname(char *, int, int); +int backup_file(char *); int move_file(char *, char *); -void copy_file(char *, char *); +int copy_file(char *, char *); void say(char *, ...); void fatal(char *, ...) __attribute__((__format__(__printf__, 1, 2))); |