Improve portability of patch(1):
authorJoerg Sonnenberger <joerg@dragonflybsd.org>
Mon, 10 Apr 2006 08:11:43 +0000 (08:11 +0000)
committerJoerg Sonnenberger <joerg@dragonflybsd.org>
Mon, 10 Apr 2006 08:11:43 +0000 (08:11 +0000)
- basename(3) and dirname(3) can either return a pointer to
  static storage (like on all BSDs) or modify the argument
  (like on Linux). strdup the argument to support both.
- fix argument range of ctype macros.

usr.bin/patch/backupfile.c
usr.bin/patch/inp.c
usr.bin/patch/patch.c
usr.bin/patch/pch.c
usr.bin/patch/util.c

index 4b0506f..d0e4859 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * $OpenBSD: backupfile.c,v 1.18 2004/08/05 21:47:24 deraadt Exp $
- * $DragonFly: src/usr.bin/patch/backupfile.c,v 1.2 2004/09/28 19:09:50 joerg Exp $
+ * $DragonFly: src/usr.bin/patch/backupfile.c,v 1.3 2006/04/10 08:11:43 joerg Exp $
  */
 
 /*
@@ -30,7 +30,7 @@
 #include "backupfile.h"
 
 
-#define ISDIGIT(c) (isascii (c) && isdigit (c))
+#define ISDIGIT(c) (isascii ((unsigned char)c) && isdigit ((unsigned char)c))
 
 /* Which type of backup file names are generated. */
 enum backup_type backup_type = none;
@@ -56,21 +56,32 @@ static void invalid_arg(const char *, const char *, int);
 char *
 find_backup_file_name(const char *file)
 {
-       char    *dir, *base_versions;
+       char    *dir, *base_versions, *tmp_file;
        int     highest_backup;
 
        if (backup_type == simple)
                return concat(file, simple_backup_suffix);
-       base_versions = concat(basename(file), ".~");
+       tmp_file = strdup(file);
+       if (tmp_file == NULL)
+               return NULL;
+       base_versions = concat(basename(tmp_file), ".~");
+       free(tmp_file);
        if (base_versions == NULL)
                return NULL;
-       dir = dirname(file);
+       tmp_file = strdup(file);
+       if (tmp_file == NULL) {
+               free(base_versions);
+               return NULL;
+       }
+       dir = dirname(tmp_file);
        if (dir == NULL) {
                free(base_versions);
+               free(tmp_file);
                return NULL;
        }
        highest_backup = max_backup_version(base_versions, dir);
        free(base_versions);
+       free(tmp_file);
        if (backup_type == numbered_existing && highest_backup == 0)
                return concat(file, simple_backup_suffix);
        return make_version_name(file, highest_backup + 1);
index 8c81010..099f490 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * $OpenBSD: inp.c,v 1.32 2004/08/05 21:47:24 deraadt Exp $
- * $DragonFly: src/usr.bin/patch/inp.c,v 1.3 2004/12/26 15:55:23 swildner Exp $
+ * $DragonFly: src/usr.bin/patch/inp.c,v 1.4 2006/04/10 08:11:43 joerg Exp $
  */
 
 /*
@@ -176,9 +176,14 @@ plan_a(const char *filename)
            ((filestat.st_mode & 0022) == 0 && filestat.st_uid != getuid())) {
                const char      *cs = NULL, *filebase, *filedir;
                struct stat     cstat;
+               char *tmp_filename1, *tmp_filename2;
 
-               filebase = basename(filename);
-               filedir = dirname(filename);
+               tmp_filename1 = strdup(filename);
+               tmp_filename2 = strdup(filename);
+               if (tmp_filename1 == NULL || tmp_filename2 == NULL)
+                       fatal("strdupping filename");
+               filebase = basename(tmp_filename1);
+               filedir = dirname(tmp_filename2);
 
                /* Leave room in lbuf for the diff command.  */
                s = lbuf + 20;
@@ -199,6 +204,10 @@ plan_a(const char *filename)
                        cs = "SCCS";
                } else if (statfailed)
                        fatal("can't find %s\n", filename);
+
+               free(tmp_filename1);
+               free(tmp_filename2);
+
                /*
                 * else we can't write to it but it's not under a version
                 * control system, so just proceed.
@@ -461,11 +470,11 @@ rev_in_string(const char *string)
        if (revision == NULL)
                return true;
        patlen = strlen(revision);
-       if (strnEQ(string, revision, patlen) && isspace(string[patlen]))
+       if (strnEQ(string, revision, patlen) && isspace((unsigned char)string[patlen]))
                return true;
        for (s = string; *s; s++) {
-               if (isspace(*s) && strnEQ(s + 1, revision, patlen) &&
-                   isspace(s[patlen + 1])) {
+               if (isspace((unsigned char)*s) && strnEQ(s + 1, revision, patlen) &&
+                   isspace((unsigned char)s[patlen + 1])) {
                        return true;
                }
        }
index 4ede0e4..5b84e21 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * $OpenBSD: patch.c,v 1.43 2004/11/19 20:08:11 otto Exp $
- * $DragonFly: src/usr.bin/patch/patch.c,v 1.4 2005/01/10 21:45:33 swildner Exp $
+ * $DragonFly: src/usr.bin/patch/patch.c,v 1.5 2006/04/10 08:11:43 joerg Exp $
  */
 
 /*
@@ -506,7 +506,7 @@ get_some_switches(void)
                        break;
                case 'D':
                        do_defines = true;
-                       if (!isalpha(*optarg) && *optarg != '_')
+                       if (!isalpha((unsigned char)*optarg) && *optarg != '_')
                                fatal("argument to -D is not an identifier\n");
                        snprintf(if_defined, sizeof if_defined,
                            "#ifdef %s\n", optarg);
@@ -1033,12 +1033,12 @@ static bool
 similar(const char *a, const char *b, int len)
 {
        while (len) {
-               if (isspace(*b)) {      /* whitespace (or \n) to match? */
-                       if (!isspace(*a))       /* no corresponding whitespace? */
+               if (isspace((unsigned char)*b)) {       /* whitespace (or \n) to match? */
+                       if (!isspace((unsigned char)*a))        /* no corresponding whitespace? */
                                return false;
-                       while (len && isspace(*b) && *b != '\n')
+                       while (len && isspace((unsigned char)*b) && *b != '\n')
                                b++, len--;     /* skip pattern whitespace */
-                       while (isspace(*a) && *a != '\n')
+                       while (isspace((unsigned char)*a) && *a != '\n')
                                a++;    /* skip target whitespace */
                        if (*a == '\n' || *b == '\n')
                                return (*a == *b);      /* should end in sync */
index 90cd9c2..e9904f8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * $OpenBSD: pch.c,v 1.35 2004/08/05 21:47:24 deraadt Exp $
- * $DragonFly: src/usr.bin/patch/pch.c,v 1.2 2004/09/28 19:09:50 joerg Exp $
+ * $DragonFly: src/usr.bin/patch/pch.c,v 1.3 2006/04/10 08:11:43 joerg Exp $
  */
 
 /*
@@ -286,9 +286,9 @@ intuit_diff_type(void)
                        else
                                indent++;
                }
-               for (t = s; isdigit(*t) || *t == ','; t++)
+               for (t = s; isdigit((unsigned char)*t) || *t == ','; t++)
                        ;
-               this_is_a_command = (isdigit(*s) &&
+               this_is_a_command = (isdigit((unsigned char)*s) &&
                    (*t == 'd' || *t == 'c' || *t == 'a'));
                if (first_command_line < 0L && this_is_a_command) {
                        first_command_line = this_line;
@@ -309,10 +309,10 @@ intuit_diff_type(void)
                        names[INDEX_FILE].path = fetchname(s + 6,
                            &names[INDEX_FILE].exists, strippath);
                else if (strnEQ(s, "Prereq:", 7)) {
-                       for (t = s + 7; isspace(*t); t++)
+                       for (t = s + 7; isspace((unsigned char)*t); t++)
                                ;
                        revision = savestr(t);
-                       for (t = revision; *t && !isspace(*t); t++)
+                       for (t = revision; *t && !isspace((unsigned char)*t); t++)
                                ;
                        *t = '\0';
                        if (*revision == '\0') {
@@ -571,17 +571,17 @@ another_hunk(void)
                                        p_end--;
                                        return false;
                                }
-                               for (s = buf; *s && !isdigit(*s); s++)
+                               for (s = buf; *s && !isdigit((unsigned char)*s); s++)
                                        ;
                                if (!*s)
                                        malformed();
                                if (strnEQ(s, "0,0", 3))
                                        memmove(s, s + 2, strlen(s + 2) + 1);
                                p_first = (LINENUM) atol(s);
-                               while (isdigit(*s))
+                               while (isdigit((unsigned char)*s))
                                        s++;
                                if (*s == ',') {
-                                       for (; *s && !isdigit(*s); s++)
+                                       for (; *s && !isdigit((unsigned char)*s); s++)
                                                ;
                                        if (!*s)
                                                malformed();
@@ -640,15 +640,15 @@ another_hunk(void)
                                                return false;
                                        }
                                        p_char[p_end] = '=';
-                                       for (s = buf; *s && !isdigit(*s); s++)
+                                       for (s = buf; *s && !isdigit((unsigned char)*s); s++)
                                                ;
                                        if (!*s)
                                                malformed();
                                        p_newfirst = (LINENUM) atol(s);
-                                       while (isdigit(*s))
+                                       while (isdigit((unsigned char)*s))
                                                s++;
                                        if (*s == ',') {
-                                               for (; *s && !isdigit(*s); s++)
+                                               for (; *s && !isdigit((unsigned char)*s); s++)
                                                        ;
                                                if (!*s)
                                                        malformed();
@@ -678,7 +678,7 @@ another_hunk(void)
                change_line:
                                if (buf[1] == '\n' && canonicalize)
                                        strlcpy(buf + 1, " \n", sizeof buf - 1);
-                               if (!isspace(buf[1]) && buf[1] != '>' &&
+                               if (!isspace((unsigned char)buf[1]) && buf[1] != '>' &&
                                    buf[1] != '<' &&
                                    repl_beginning && repl_could_be_missing) {
                                        repl_missing = true;
@@ -725,7 +725,7 @@ another_hunk(void)
                                }
                                break;
                        case ' ':
-                               if (!isspace(buf[1]) &&
+                               if (!isspace((unsigned char)buf[1]) &&
                                    repl_beginning && repl_could_be_missing) {
                                        repl_missing = true;
                                        goto hunk_done;
@@ -853,11 +853,11 @@ hunk_done:
                if (!*s)
                        malformed();
                p_first = (LINENUM) atol(s);
-               while (isdigit(*s))
+               while (isdigit((unsigned char)*s))
                        s++;
                if (*s == ',') {
                        p_ptrn_lines = (LINENUM) atol(++s);
-                       while (isdigit(*s))
+                       while (isdigit((unsigned char)*s))
                                s++;
                } else
                        p_ptrn_lines = 1;
@@ -866,11 +866,11 @@ hunk_done:
                if (*s != '+' || !*++s)
                        malformed();
                p_newfirst = (LINENUM) atol(s);
-               while (isdigit(*s))
+               while (isdigit((unsigned char)*s))
                        s++;
                if (*s == ',') {
                        p_repl_lines = (LINENUM) atol(++s);
-                       while (isdigit(*s))
+                       while (isdigit((unsigned char)*s))
                                s++;
                } else
                        p_repl_lines = 1;
@@ -1013,16 +1013,16 @@ hunk_done:
                p_context = 0;
                ret = pgets(buf, sizeof buf, pfp);
                p_input_line++;
-               if (ret == NULL || !isdigit(*buf)) {
+               if (ret == NULL || !isdigit((unsigned char)*buf)) {
                        next_intuit_at(line_beginning, p_input_line);
                        return false;
                }
                p_first = (LINENUM) atol(buf);
-               for (s = buf; isdigit(*s); s++)
+               for (s = buf; isdigit((unsigned char)*s); s++)
                        ;
                if (*s == ',') {
                        p_ptrn_lines = (LINENUM) atol(++s) - p_first + 1;
-                       while (isdigit(*s))
+                       while (isdigit((unsigned char)*s))
                                s++;
                } else
                        p_ptrn_lines = (*s != 'a');
@@ -1030,7 +1030,7 @@ hunk_done:
                if (hunk_type == 'a')
                        p_first++;      /* do append rather than insert */
                min = (LINENUM) atol(++s);
-               for (; isdigit(*s); s++)
+               for (; isdigit((unsigned char)*s); s++)
                        ;
                if (*s == ',')
                        max = (LINENUM) atol(++s);
@@ -1388,11 +1388,11 @@ do_ed_script(void)
                        break;
                }
                p_input_line++;
-               for (t = buf; isdigit(*t) || *t == ','; t++)
+               for (t = buf; isdigit((unsigned char)*t) || *t == ','; t++)
                        ;
                /* POSIX defines allowed commands as {a,c,d,i,s} */
-               if (isdigit(*buf) && (*t == 'a' || *t == 'c' || *t == 'd' ||
-                   *t == 'i' || *t == 's')) {
+               if (isdigit((unsigned char)*buf) && (*t == 'a' || *t == 'c' ||
+                   *t == 'd' || *t == 'i' || *t == 's')) {
                        if (pipefp != NULL)
                                fputs(buf, pipefp);
                        if (*t != 'd') {
index d3d3c23..c70e7ba 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * $OpenBSD: util.c,v 1.29 2004/11/19 20:00:57 otto Exp $
- * $DragonFly: src/usr.bin/patch/util.c,v 1.6 2006/02/03 21:20:29 corecode Exp $
+ * $DragonFly: src/usr.bin/patch/util.c,v 1.7 2006/04/10 08:11:43 joerg Exp $
  */
 
 /*
@@ -141,10 +141,10 @@ backup_file(const char *orig)
        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++)
+               for (s = simplename; *s && !islower((unsigned char)*s); s++)
                        ;
                if (*s)
-                       *s = toupper(*s);
+                       *s = toupper((unsigned char)*s);
                else
                        memmove(simplename, simplename + 1,
                            strlen(simplename + 1) + 1);
@@ -346,7 +346,7 @@ fetchname(const char *at, bool *exists, int strip_leading)
 
        if (at == NULL || *at == '\0')
                return NULL;
-       while (isspace(*at))
+       while (isspace((unsigned char)*at))
                at++;
 #ifdef DEBUGGING
        if (debug & 128)
@@ -360,7 +360,7 @@ fetchname(const char *at, bool *exists, int strip_leading)
        tab = strchr(t, '\t') != NULL;
        /* Strip off up to `strip_leading' path components and NUL terminate. */
        for (sleading = strip_leading; *t != '\0' && ((tab && *t != '\t') ||
-           !isspace(*t)); t++) {
+           !isspace((unsigned char)*t)); t++) {
                if (t[0] == '/' && t[1] != '/' && t[1] != '\0')
                        if (--sleading >= 0)
                                name = t + 1;