]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
rename: use function pointer to select file or symlink operation
authorSami Kerola <kerolasa@iki.fi>
Sun, 25 May 2014 23:41:06 +0000 (00:41 +0100)
committerSami Kerola <kerolasa@iki.fi>
Fri, 18 Jul 2014 17:34:15 +0000 (18:34 +0100)
Add separate functions to different functionality, and add a function for
the stuff that is in common for both.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
misc-utils/rename.c

index 3270aa51022fa3309522cbfbdabb19603b78bb42..9064bc3f3aa0fbf20dbe483c1cb0db490d8a40ed 100644 (file)
@@ -31,94 +31,85 @@ for i in $@; do N=`echo "$i" | sed "s/$FROM/$TO/g"`; mv "$i" "$N"; done
 #define RENAME_EXIT_NOTHING    4
 #define RENAME_EXIT_UNEXPLAINED        64
 
-static int do_rename(char *from, char *to, char *s, int verbose, int symtarget)
+static int string_replace(char *from, char *to, char *s, char *orig, char **newname)
 {
-       char *newname = NULL, *where, *p, *q, *target = NULL;
-       int flen, tlen, slen, ret = 1;
-       struct stat sb;
-
-       if (symtarget) {
-               if (lstat(s, &sb) == -1) {
-                       warn(_("%s: lstat failed"), s);
-                       return 2;
-               }
-               if (!S_ISLNK(sb.st_mode)) {
-                       warnx(_("%s: not a symbolic link"), s);
-                       return 2;
-               }
-
-               target = xmalloc(sb.st_size + 1);
-               if (readlink(s, target, sb.st_size + 1) < 0) {
-                       warn(_("%s: readlink failed"), s);
-                       ret = 2;
-                       goto out;
-               }
-
-               target[sb.st_size] = '\0';
-               where = strstr(target, from);
-       } else {
-               char *file;
-
-               file = rindex(s, '/');
-               if (file == NULL)
-                       file = s;
-               where = strstr(file, from);
-       }
-       if (where == NULL) {
-               free(target);
-               return 0;
-       }
-
-       flen = strlen(from);
-       tlen = strlen(to);
-       if (symtarget) {
-               slen = strlen(target);
-               p = target;
-       } else {
-               slen = strlen(s);
-               p = s;
-       }
-       newname = xmalloc(tlen + slen + 1);
-
-       q = newname;
+       char *p, *q, *where;
+
+       where = strstr(s, from);
+       if (where == NULL)
+               return 1;
+       p = orig;
+       *newname = xmalloc(strlen(orig) + strlen(to) + 1);
+       q = *newname;
        while (p < where)
                *q++ = *p++;
        p = to;
        while (*p)
                *q++ = *p++;
-       p = where + flen;
+       p = where + strlen(from);
        while (*p)
                *q++ = *p++;
        *q = 0;
+       return 0;
+}
 
-       if (symtarget) {
-               if (0 > unlink(s)) {
-                       warn(_("%s: unlink failed"), s);
-                       ret = 2;
-                       goto out;
-               }
-               if (symlink(newname, s) != 0) {
-                       warn(_("%s: symlinking to %s failed"), s, newname);
-                       ret = 2;
-                       goto out;
-               }
-               if (verbose)
-                       printf("%s: `%s' -> `%s'\n", s, target, newname);
-       } else {
-               if (rename(s, newname) != 0) {
-                       warn(_("%s: rename to %s failed"), s, newname);
-                       ret = 2;
-                       goto out;
-               }
-               if (verbose)
-                       printf("`%s' -> `%s'\n", s, newname);
+static int do_symlink(char *from, char *to, char *s, int verbose)
+{
+       char *newname = NULL, *target = NULL;
+       int ret = 1;
+       struct stat sb;
+
+       if (lstat(s, &sb) == -1) {
+               warn(_("%s: lstat failed"), s);
+               return 2;
+       }
+       if (!S_ISLNK(sb.st_mode)) {
+               warnx(_("%s: not a symbolic link"), s);
+               return 2;
+       }
+       target = xmalloc(sb.st_size + 1);
+       if (readlink(s, target, sb.st_size + 1) < 0) {
+               warn(_("%s: readlink failed"), s);
+               free(target);
+               return 2;
+       }
+       target[sb.st_size] = '\0';
+       if (string_replace(from, to, target, target, &newname))
+               ret = 0;
+       else if (0 > unlink(s)) {
+               warn(_("%s: unlink failed"), s);
+               ret = 2;
+       } else if (symlink(newname, s) != 0) {
+               warn(_("%s: symlinking to %s failed"), s, newname);
+               ret = 2;
        }
- out:
+       if (verbose && ret == 1)
+               printf("%s: `%s' -> `%s'\n", s, target, newname);
        free(newname);
        free(target);
        return ret;
 }
 
+static int do_file(char *from, char *to, char *s, int verbose)
+{
+       char *newname = NULL, *file;
+       int ret = 1;
+
+       file = rindex(s, '/');
+       if (file == NULL)
+               file = s;
+       if (string_replace(from, to, file, s, &newname))
+               return 0;
+       else if (rename(s, newname) != 0) {
+               warn(_("%s: rename to %s failed"), s, newname);
+               ret = 2;
+       }
+       if (verbose && ret == 1)
+               printf("`%s' -> `%s'\n", s, newname);
+       free(newname);
+       return ret;
+}
+
 static void __attribute__ ((__noreturn__)) usage(FILE * out)
 {
        fputs(USAGE_HEADER, out);
@@ -138,7 +129,8 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
 int main(int argc, char **argv)
 {
        char *from, *to;
-       int i, c, ret = 0, symtarget = 0, verbose = 0;
+       int i, c, ret = 0, verbose = 0;
+       int (*do_rename)(char *from, char *to, char *s, int verbose) = do_file;
 
        static const struct option longopts[] = {
                {"verbose", no_argument, NULL, 'v'},
@@ -159,7 +151,7 @@ int main(int argc, char **argv)
                        verbose = 1;
                        break;
                case 's':
-                       symtarget = 1;
+                       do_rename = do_symlink;
                        break;
                case 'V':
                        printf(UTIL_LINUX_VERSION);
@@ -182,7 +174,7 @@ int main(int argc, char **argv)
        to = argv[1];
 
        for (i = 2; i < argc; i++)
-               ret |= do_rename(from, to, argv[i], verbose, symtarget);
+               ret |= do_rename(from, to, argv[i], verbose);
 
        switch (ret) {
        case 0: