summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/patch/patch.126
-rw-r--r--usr.bin/patch/patch.c38
-rw-r--r--usr.bin/patch/pch.c10
-rw-r--r--usr.bin/patch/util.c153
-rw-r--r--usr.bin/patch/util.h5
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)));