# HG changeset patch # User Rob Landley # Date 1198153819 21600 # Node ID 98820d1eaa79aa0b1b1cf692386ae09add19e37f # Parent db91356e3c43687c61802be9bac31fb72b83de9b Upgrade patch to understand creating and deleting files. diff -r db91356e3c43 -r 98820d1eaa79 lib/lib.c --- a/lib/lib.c Thu Dec 20 06:29:59 2007 -0600 +++ b/lib/lib.c Thu Dec 20 06:30:19 2007 -0600 @@ -178,6 +178,12 @@ 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 -r db91356e3c43 -r 98820d1eaa79 lib/lib.h --- a/lib/lib.h Thu Dec 20 06:29:59 2007 -0600 +++ b/lib/lib.h Thu Dec 20 06:30:19 2007 -0600 @@ -60,6 +60,7 @@ 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 -r db91356e3c43 -r 98820d1eaa79 toys/patch.c --- a/toys/patch.c Thu Dec 20 06:29:59 2007 -0600 +++ b/toys/patch.c Thu Dec 20 06:30:19 2007 -0600 @@ -135,7 +135,7 @@ 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 @@ apply_hunk(); // Open a new file? - if (!strncmp("+++ ", patchline, 4)) { - int i; - char *s, *start; - - // Finish old file. - if (TT.tempfile) - replace_tempfile(TT.filein, TT.fileout, &TT.tempfile); + 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++; - *s = i = 0; - for (s = start = patchline+4; *s;) { + + TT.oldname = xstrdup(patchline+4); + } else if (!strncmp("+++ ", patchline, 4)) { + int i = 0, del = 0; + char *s, *start; + + // Finish old file. + 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 = 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 @@ } } + 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 @@ 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 @@ // 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 -r db91356e3c43 -r 98820d1eaa79 toys/toylist.h --- a/toys/toylist.h Thu Dec 20 06:29:59 2007 -0600 +++ b/toys/toylist.h Thu Dec 20 06:30:19 2007 -0600 @@ -74,7 +74,7 @@ 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 {