Upgrade patch to understand creating and deleting files.
authorRob Landley <rob@landley.net>
Thu, 20 Dec 2007 12:30:19 +0000 (06:30 -0600)
committerRob Landley <rob@landley.net>
Thu, 20 Dec 2007 12:30:19 +0000 (06:30 -0600)
lib/lib.c
lib/lib.h
toys/patch.c
toys/toylist.h

index 510b830..985c580 100644 (file)
--- 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)
 {
index fdead96..28ff0da 100644 (file)
--- 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);
index 1ad983c..b296b1e 100644 (file)
@@ -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);
+       }
 }
index 61e89c1..05d70b1 100644 (file)
@@ -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 {