]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
rename: add --symlink option for renaming symlink target
authorJan (yac) Matějka <JMatejka@suse.cz>
Mon, 26 Nov 2012 15:50:08 +0000 (16:50 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 10 Dec 2012 12:07:09 +0000 (13:07 +0100)
[kzak@redhat.com: - coding style clean up]

Signed-off-by: Karel Zak <kzak@redhat.com>
misc-utils/rename.1
misc-utils/rename.c

index 5f86b235ea5b3b106411a37db60d163c7526b675..1ce6c1296e071b1afffe6f4e610bd8e7f2aa9b62 100644 (file)
@@ -21,6 +21,9 @@ Give visual feedback which files where renamed, if any.
 \fB\-V\fR, \fB\-\-version\fR
 Display version information and exit.
 .TP
+\fB\-s\fR, \fB\-\-symlink\fR
+Peform rename on symlink target
+.TP
 \fB\-h\fR, \fB\-\-help\fR
 Display help text and exit.
 .SH EXAMPLES
index b17e03bb132b07610093e2bf1a13d7c8a5a3a9de..35c69b714d4900961d0fdf0dadee5d5a58385805 100644 (file)
@@ -18,27 +18,51 @@ for i in $@; do N=`echo "$i" | sed "s/$FROM/$TO/g"`; mv "$i" "$N"; done
 #include <stdlib.h>
 #include <errno.h>
 #include <getopt.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include "nls.h"
 #include "xalloc.h"
 #include "c.h"
 #include "closestream.h"
 
-static int do_rename(char *from, char *to, char *s, int verbose)
+static int do_rename(char *from, char *to, char *s, int verbose, int symtarget)
 {
-       char *newname, *where, *p, *q;
+       char *newname, *where, *p, *q, *target;
        int flen, tlen, slen;
+       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);
+
+               target = xmalloc(sb.st_size + 1);
+               if (readlink(s, target, sb.st_size + 1) < 0)
+                       err(EXIT_FAILURE, _("%s: readlink failed"), s);
+
+               target[sb.st_size] = '\0';
+               where = strstr(target, from);
+       } else
+               where = strstr(s, from);
 
-       where = strstr(s, from);
        if (where == NULL)
                return 0;
 
        flen = strlen(from);
        tlen = strlen(to);
-       slen = strlen(s);
+       if (symtarget) {
+               slen = strlen(target);
+               p = target;
+       } else {
+               slen = strlen(s);
+               p = s;
+       }
        newname = xmalloc(tlen + slen + 1);
 
-       p = s;
        q = newname;
        while (p < where)
                *q++ = *p++;
@@ -50,11 +74,20 @@ static int do_rename(char *from, char *to, char *s, int verbose)
                *q++ = *p++;
        *q = 0;
 
-       if (rename(s, newname) != 0)
-               err(EXIT_FAILURE, _("renaming %s to %s failed"),
-                   s, newname);
-       if (verbose)
-               printf("`%s' -> `%s'\n", s, newname);
+       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 (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 (verbose)
+                       printf("`%s' -> `%s'\n", s, newname);
+       }
+
 
        free(newname);
        return 1;
@@ -70,6 +103,7 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
        fputs(_("\nOptions:\n"), out);
        fputs(_(" -v, --verbose    explain what is being done\n"
                " -V, --version    output version information and exit\n"
+               " -s, --symlink    act on symlink target\n"
                " -h, --help       display this help and exit\n\n"), out);
 
        exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
@@ -78,12 +112,13 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
 int main(int argc, char **argv)
 {
        char *from, *to;
-       int i, c, verbose = 0;
+       int i, c, symtarget=0, verbose = 0;
 
        static const struct option longopts[] = {
                {"verbose", no_argument, NULL, 'v'},
                {"version", no_argument, NULL, 'V'},
                {"help", no_argument, NULL, 'h'},
+               {"symlink", no_argument, NULL, 's'},
                {NULL, 0, NULL, 0}
        };
 
@@ -92,11 +127,14 @@ int main(int argc, char **argv)
        textdomain(PACKAGE);
        atexit(close_stdout);
 
-       while ((c = getopt_long(argc, argv, "vVh", longopts, NULL)) != -1)
+       while ((c = getopt_long(argc, argv, "vsVh", longopts, NULL)) != -1)
                switch (c) {
                case 'v':
                        verbose = 1;
                        break;
+               case 's':
+                       symtarget = 1;
+                       break;
                case 'V':
                        printf(_("%s from %s\n"),
                               program_invocation_short_name,
@@ -120,7 +158,7 @@ int main(int argc, char **argv)
        to = argv[1];
 
        for (i = 2; i < argc; i++)
-               do_rename(from, to, argv[i], verbose);
+               do_rename(from, to, argv[i], verbose, symtarget);
 
        return EXIT_SUCCESS;
 }