Updated patches. I still prefer the one that's 40 lines shorter :-)

Tony.
-- 
f.a.n.finch <[EMAIL PROTECTED]> http://dotat.at/
SOUTHEAST ICELAND: SOUTHWEST BECOMING VARIABLE 4. FAIR. GOOD.


--- main.c      Mon Jul 29 13:16:44 2002
+++ main.c.two  Mon Jul 29 13:08:49 2002
@@ -413,9 +413,7 @@
        char **filename;
 {
        struct stat orig;
-       int input, output;
        char backup[MAXPATHLEN];
-       char *buffer;
 
        if (lstat(*filename, &orig) == -1)
                err(1, "lstat");
@@ -425,36 +423,36 @@
        }
 
        if (*inplace == '\0') {
-               char template[] = "/tmp/sed.XXXXXXXXXX";
-
-               output = mkstemp(template);
-               if (output == -1)
-                       err(1, "mkstemp");
-               strlcpy(backup, template, MAXPATHLEN);
+               /*
+                * This is a bit of a hack: we use mkstemp() to avoid the
+                * mktemp() link-time warning, although mktemp() would fit in
+                * this context much better. We're only interested in getting
+                * a name for use in the rename(); there aren't any security
+                * issues here that don't already exist in relation to the
+                * original file and its directory.
+                */
+               int fd;
+               strlcpy(backup, *filename, sizeof(backup));
+               strlcat(backup, ".XXXXXXXXXX", sizeof(backup));
+               fd = mkstemp(backup);
+               if (fd == -1)
+                       errx(1, "could not create backup of %s", *filename);
+               else
+                       close(fd);
        } else {
-               strlcpy(backup, *filename, MAXPATHLEN);
-               strlcat(backup, inplace, MAXPATHLEN);
-               output = open(backup, O_WRONLY | O_CREAT | O_TRUNC);
-               if (output == -1)
-                       err(1, "open(%s)", backup);
+               strlcpy(backup, *filename, sizeof(backup));
+               strlcat(backup, inplace, sizeof(backup));
        }
 
-       input = open(*filename, O_RDONLY);
-       if (input == -1)
-               err(1, "open(%s)", *filename);
-       if (fchmod(output, orig.st_mode & ~S_IFMT) == -1)
-               err(1, "chmod");
-       buffer = (char *)mmap(0, orig.st_size, PROT_READ, MAP_SHARED, input, 0);
-       if (buffer == MAP_FAILED)
-               err(1, "mmap(%s)", *filename);
-       if (write(output, buffer, orig.st_size) == -1)
-               err(1, "write(%s)", backup);
-       if (munmap(buffer, orig.st_size) == -1)
-               err(1, "munmap(%s)", *filename);
-       close(input);
-       close(output);
-       freopen(*filename, "w", stdout);
+       if (rename(*filename, backup) == -1)
+               err(1, "rename(\"%s\", \"%s\")", *filename, backup);
+       if (freopen(*filename, "w", stdout) == NULL)
+               err(1, "open(\"%s\")", *filename);
+       if (fchmod(fileno(stdout), orig.st_mode) == -1)
+               err(1, "chmod(\"%s\")", *filename);
        *filename = strdup(backup);
+       if (*filename == NULL)
+               err(1, "malloc");
        return 0;
 }
 


--- main.c      Mon Jul 29 13:16:44 2002
+++ main.c.one  Mon Jul 29 13:15:03 2002
@@ -68,6 +68,11 @@
 #include "extern.h"
 
 /*
+ * Maximum amount of data to mmap at a time when copying a file.
+ */
+#define MMAP_MAX (16*1024*1024)
+
+/*
  * Linked list of units (strings and files) to be compiled
  */
 struct s_compunit {
@@ -407,6 +412,8 @@
 
 /*
  * Modify a pointer to a filename for inplace editing and reopen stdout
+ *
+ * We remove the files before opening them in case of permissions problems
  */
 static int
 inplace_edit(filename)
@@ -416,6 +423,7 @@
        int input, output;
        char backup[MAXPATHLEN];
        char *buffer;
+       off_t off, size;
 
        if (lstat(*filename, &orig) == -1)
                err(1, "lstat");
@@ -424,37 +432,57 @@
                return -1;
        }
 
+       /* create and open the backup file */
        if (*inplace == '\0') {
-               char template[] = "/tmp/sed.XXXXXXXXXX";
+               const char *tmp;
 
-               output = mkstemp(template);
+               tmp = getenv("TMPDIR");
+               if (tmp == NULL)
+                       tmp = "/tmp";
+               strlcpy(backup, tmp, sizeof(backup));
+               strlcat(backup, "/sed.XXXXXXXXXX", sizeof(backup));
+               output = mkstemp(backup);
                if (output == -1)
                        err(1, "mkstemp");
-               strlcpy(backup, template, MAXPATHLEN);
+               if (fchmod(output, orig.st_mode & ~S_IFMT) == -1)
+                       err(1, "chmod(\"%s\")", backup);
        } else {
-               strlcpy(backup, *filename, MAXPATHLEN);
-               strlcat(backup, inplace, MAXPATHLEN);
-               output = open(backup, O_WRONLY | O_CREAT | O_TRUNC);
+               strlcpy(backup, *filename, sizeof(backup));
+               strlcat(backup, inplace, sizeof(backup));
+               if (unlink(backup) == -1 && errno != ENOENT)
+                       err(1, "unlink(\"%s\")", backup);
+               output = open(backup, O_WRONLY | O_CREAT | O_TRUNC, orig.st_mode);
                if (output == -1)
-                       err(1, "open(%s)", backup);
+                       err(1, "open(\"%s\")", backup);
        }
-
+       /* copy the original file to the backup */
        input = open(*filename, O_RDONLY);
        if (input == -1)
-               err(1, "open(%s)", *filename);
-       if (fchmod(output, orig.st_mode & ~S_IFMT) == -1)
-               err(1, "chmod");
-       buffer = (char *)mmap(0, orig.st_size, PROT_READ, MAP_SHARED, input, 0);
-       if (buffer == MAP_FAILED)
-               err(1, "mmap(%s)", *filename);
-       if (write(output, buffer, orig.st_size) == -1)
-               err(1, "write(%s)", backup);
-       if (munmap(buffer, orig.st_size) == -1)
-               err(1, "munmap(%s)", *filename);
+               err(1, "open(\"%s\")", *filename);
+       for (off = 0; off < orig.st_size; off += MMAP_MAX) {
+               size = orig.st_size - off;
+               if (size > MMAP_MAX)
+                       size = MMAP_MAX;
+               buffer = mmap(NULL, size, PROT_READ, MAP_SHARED, input, off);
+               if (buffer == MAP_FAILED)
+                       err(1, "mmap(\"%s\")", *filename);
+               if (write(output, buffer, size) == -1)
+                       err(1, "write(\"%s\")", backup);
+               if (munmap(buffer, size) == -1)
+                       err(1, "munmap(\"%s\")", *filename);
+       }
        close(input);
        close(output);
-       freopen(*filename, "w", stdout);
+       /* create the replacement for the original file */
+       if (unlink(*filename) == -1)
+               err(1, "unlink(\"%s\")", *filename);
+       if (freopen(*filename, "w", stdout) == NULL)
+               err(1, "open(\"%s\")", *filename);
+       if (fchmod(fileno(stdout), orig.st_mode) == -1)
+               err(1, "chmod(\"%s\")", *filename);
        *filename = strdup(backup);
+       if (*filename == NULL)
+               err(1, "malloc");
        return 0;
 }
 

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to