]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
rename: continue despite something failed
authorSami Kerola <kerolasa@iki.fi>
Sat, 28 Jun 2014 17:42:49 +0000 (18:42 +0100)
committerSami Kerola <kerolasa@iki.fi>
Fri, 18 Jul 2014 17:34:15 +0000 (18:34 +0100)
Try to do all file operations even when one or some of them fail, and
use exit value to inform what happen.

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

index 47059575255911143bce15567e4f99de1f6164f9..30d9c710a6d6209dec38665bf923208876738412 100644 (file)
@@ -55,6 +55,26 @@ the command will perform the action without any questions.  For example, the
 result can be quite drastic when the command is run as root in the /lib
 directory.  Always make a backup before running the command, unless you truly
 know what you are doing.
+.SH "EXIT STATUS"
+.RS
+.PD 0
+.TP
+.B 0
+all requested rename operations were successful
+.TP
+.B 1
+all rename operations failed
+.TP
+.B 2
+some rename operations failed
+.TP
+.B 4
+nothing was renamed
+.TP
+.B 64
+unanticipated error occurred
+.PD
+.RE
 .SH "SEE ALSO"
 .BR mv (1)
 .SH AVAILABILITY
index b945aaab7099746f2be7b0c37afd06b400ae0dad..3270aa51022fa3309522cbfbdabb19603b78bb42 100644 (file)
@@ -27,22 +27,32 @@ for i in $@; do N=`echo "$i" | sed "s/$FROM/$TO/g"`; mv "$i" "$N"; done
 #include "c.h"
 #include "closestream.h"
 
+#define RENAME_EXIT_SOMEOK     2
+#define RENAME_EXIT_NOTHING    4
+#define RENAME_EXIT_UNEXPLAINED        64
+
 static int do_rename(char *from, char *to, char *s, int verbose, int symtarget)
 {
-       char *newname, *where, *p, *q, *target = NULL;
-       int flen, tlen, slen;
+       char *newname = NULL, *where, *p, *q, *target = NULL;
+       int flen, tlen, slen, ret = 1;
        struct stat sb;
 
        if (symtarget) {
-               if (lstat(s, &sb) == -1)
-                       err(EXIT_FAILURE, _("%s: lstat failed"), s);
-
-               if (!S_ISLNK(sb.st_mode))
-                       errx(EXIT_FAILURE, _("%s: not a symbolic link"), s);
+               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)
-                       err(EXIT_FAILURE, _("%s: readlink failed"), s);
+               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);
@@ -82,22 +92,31 @@ static int do_rename(char *from, char *to, char *s, int verbose, int symtarget)
        *q = 0;
 
        if (symtarget) {
-               if (0 > unlink(s))
-                       err(EXIT_FAILURE, _("%s: unlink failed"), s);
-               if (symlink(newname, s) != 0)
-                       err(EXIT_FAILURE, _("%s: symlinking to %s failed"), s, newname);
+               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)
-                       err(EXIT_FAILURE, _("%s: rename to %s failed"), s, newname);
+               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);
        }
-
+ out:
        free(newname);
        free(target);
-       return 1;
+       return ret;
 }
 
 static void __attribute__ ((__noreturn__)) usage(FILE * out)
@@ -119,7 +138,7 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
 int main(int argc, char **argv)
 {
        char *from, *to;
-       int i, c, symtarget=0, verbose = 0;
+       int i, c, ret = 0, symtarget = 0, verbose = 0;
 
        static const struct option longopts[] = {
                {"verbose", no_argument, NULL, 'v'},
@@ -163,7 +182,18 @@ int main(int argc, char **argv)
        to = argv[1];
 
        for (i = 2; i < argc; i++)
-               do_rename(from, to, argv[i], verbose, symtarget);
-
-       return EXIT_SUCCESS;
+               ret |= do_rename(from, to, argv[i], verbose, symtarget);
+
+       switch (ret) {
+       case 0:
+               return RENAME_EXIT_NOTHING;
+       case 1:
+               return EXIT_SUCCESS;
+       case 2:
+               return EXIT_FAILURE;
+       case 3:
+               return RENAME_EXIT_SOMEOK;
+       default:
+               return RENAME_EXIT_UNEXPLAINED;
+       }
 }