aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2007-12-20 06:30:19 -0600
committerRob Landley <rob@landley.net>2007-12-20 06:30:19 -0600
commite745d8e00eac61c91a540cd75d277cfc41606ce1 (patch)
tree21cda5d430ae1d0e953818dba378c001cc0bcc41
parentda09b7ff7e305b9a4f82e0048d1c4cc0a8565b64 (diff)
downloadtoybox-e745d8e00eac61c91a540cd75d277cfc41606ce1.tar.gz
Upgrade patch to understand creating and deleting files.
-rw-r--r--lib/lib.c6
-rw-r--r--lib/lib.h1
-rw-r--r--toys/patch.c56
-rw-r--r--toys/toylist.h2
4 files changed, 51 insertions, 14 deletions
diff --git a/lib/lib.c b/lib/lib.c
index 510b830b..985c580d 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -178,6 +178,12 @@ void xaccess(char *path, int flags)
if (access(path, flags)) perror_exit("Can't access '%s'\n", path);
}
+// Die unless we can delete a file. (File must exist to be deleted.)
+void xunlink(char *path)
+{
+ if (unlink(path)) perror_exit("unlink '%s'", path);
+}
+
// Die unless we can open/create a file, returning file descriptor.
int xcreate(char *path, int flags, int mode)
{
diff --git a/lib/lib.h b/lib/lib.h
index fdead960..28ff0da8 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -60,6 +60,7 @@ void xputc(char c);
void xflush(void);
void xexec(char **argv);
void xaccess(char *path, int flags);
+void xunlink(char *path);
int xcreate(char *path, int flags, int mode);
int xopen(char *path, int flags);
void xclose(int fd);
diff --git a/toys/patch.c b/toys/patch.c
index 1ad983c4..b296b1ea 100644
--- a/toys/patch.c
+++ b/toys/patch.c
@@ -135,7 +135,7 @@ fail_hunk:
buf->prev->next = NULL;
llist_free(buf, do_line);
}
- delete_tempfile(TT.filein, TT.fileout, &TT.tempfile);
+ delete_tempfile(TT.filein, TT.fileout, &TT.tempname);
TT.filein = -1;
}
@@ -174,19 +174,38 @@ void patch_main(void)
apply_hunk();
// Open a new file?
- if (!strncmp("+++ ", patchline, 4)) {
- int i;
+ if (!strncmp("--- ", patchline, 4)) {
+ char *s;
+ free(TT.oldname);
+
+ // Trim date from end of filename (if any). We don't care.
+ for (s = patchline+4; *s && *s!='\t'; s++)
+ if (*s=='\\' && s[1]) s++;
+
+ TT.oldname = xstrdup(patchline+4);
+ } else if (!strncmp("+++ ", patchline, 4)) {
+ int i = 0, del = 0;
char *s, *start;
// Finish old file.
- if (TT.tempfile)
- replace_tempfile(TT.filein, TT.fileout, &TT.tempfile);
+ if (TT.tempname)
+ replace_tempfile(TT.filein, TT.fileout, &TT.tempname);
// Trim date from end of filename (if any). We don't care.
for (s = patchline+4; *s && *s!='\t'; s++)
if (*s=='\\' && s[1]) s++;
- *s = i = 0;
- for (s = start = patchline+4; *s;) {
+ *s = 0;
+
+
+ // If new file is null (before -p trim), we're deleting oldname
+ start = patchline+4;
+ if (!strcmp(start, "/dev/null")) {
+ start = TT.oldname;
+ del++;
+ } else start = patchline+4;
+
+ // handle -p path truncation.
+ for (s = start; *s;) {
if ((toys.optflags & FLAG_PATHLEN) && TT.prefix == i) break;
if (*(s++)=='/') {
start = s;
@@ -194,11 +213,18 @@ void patch_main(void)
}
}
+ if (del) xunlink(TT.oldname);
// If we've got a file to open, do so.
- if (!(toys.optflags & FLAG_PATHLEN) || i <= TT.prefix) {
- printf("patching %s\n", start);
- TT.filein = xopen(start, O_RDWR);
- TT.fileout = copy_tempfile(TT.filein, start, &TT.tempfile);
+ else if (!(toys.optflags & FLAG_PATHLEN) || i <= TT.prefix) {
+ // If the old file was null, we're creating a new one.
+ if (!strcmp(TT.oldname, "/dev/null")) {
+ printf("creating %s\n", start);
+ TT.filein = xcreate(start, O_CREAT|O_RDWR, 0666);
+ } else {
+ printf("patching %s\n", start);
+ TT.filein = xopen(start, O_RDWR);
+ }
+ TT.fileout = copy_tempfile(TT.filein, start, &TT.tempname);
TT.state = 1;
TT.context = 0;
TT.linenum = 0;
@@ -210,6 +236,7 @@ void patch_main(void)
TT.state = 2;
sscanf(patchline+3, "%ld,%ld %ld,%ld", &TT.oldline,
&TT.oldlen, &TT.newline, &TT.newlen);
+ // Don't free it.
continue;
}
@@ -219,6 +246,9 @@ void patch_main(void)
// Flush pending hunk and flush data
apply_hunk();
- if (TT.tempfile) replace_tempfile(TT.filein, TT.fileout, &TT.tempfile);
- close(TT.filepatch);
+ if (TT.tempname) replace_tempfile(TT.filein, TT.fileout, &TT.tempname);
+ if (CFG_TOYBOX_FREE) {
+ close(TT.filepatch);
+ free(TT.oldname);
+ }
}
diff --git a/toys/toylist.h b/toys/toylist.h
index 61e89c1c..05d70b16 100644
--- a/toys/toylist.h
+++ b/toys/toylist.h
@@ -74,7 +74,7 @@ struct patch_data {
struct double_list *plines, *flines;
long oldline, oldlen, newline, newlen, linenum;
int context, state, filein, fileout, filepatch;
- char *tempfile;
+ char *tempname, *oldname;
};
struct sleep_data {