diff options
author | Jan (yac) Matějka | 2012-11-26 16:50:08 +0100 |
---|---|---|
committer | Karel Zak | 2012-12-10 13:07:09 +0100 |
commit | 5a2a8177f8b9cf9be26874baf51fb336760fe64b (patch) | |
tree | 82e150de541c905eeaa4c3f81881ec0ab204c081 /misc-utils/rename.c | |
parent | blkid: fix man page mess (diff) | |
download | kernel-qcow2-util-linux-5a2a8177f8b9cf9be26874baf51fb336760fe64b.tar.gz kernel-qcow2-util-linux-5a2a8177f8b9cf9be26874baf51fb336760fe64b.tar.xz kernel-qcow2-util-linux-5a2a8177f8b9cf9be26874baf51fb336760fe64b.zip |
rename: add --symlink option for renaming symlink target
[kzak@redhat.com: - coding style clean up]
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'misc-utils/rename.c')
-rw-r--r-- | misc-utils/rename.c | 64 |
1 files changed, 51 insertions, 13 deletions
diff --git a/misc-utils/rename.c b/misc-utils/rename.c index b17e03bb1..35c69b714 100644 --- a/misc-utils/rename.c +++ b/misc-utils/rename.c @@ -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; } |