From: "Jan (yac) Matějka" <JMatejka@xxxxxxx> --- misc-utils/rename.1 | 3 ++ misc-utils/rename.c | 69 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 59 insertions(+), 13 deletions(-) diff --git a/misc-utils/rename.1 b/misc-utils/rename.1 index 5f86b23..1ce6c12 100644 --- a/misc-utils/rename.1 +++ b/misc-utils/rename.1 @@ -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 diff --git a/misc-utils/rename.c b/misc-utils/rename.c index b17e03b..c71fab1 100644 --- a/misc-utils/rename.c +++ b/misc-utils/rename.c @@ -18,27 +18,55 @@ 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 symlink_) { - char *newname, *where, *p, *q; + char *newname, *where, *p, *q, *target; int flen, tlen, slen; + struct stat sb; + + if (symlink_) { + if (lstat(s, &sb) == -1) { + err(EXIT_FAILURE, _("lstat failed")); + } + + if(!S_ISLNK(sb.st_mode)) + /* Check the file is symlink before allocating the size of it */ + errx(EXIT_FAILURE, _("%s is not a symbolic link"), s); + + target = xmalloc(sb.st_size + 1); + if(0 > readlink(s, target, sb.st_size+1)) { + err(EXIT_FAILURE, _("readlink %s 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(symlink_) { + 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 +78,21 @@ 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(symlink_) { + if (0 > unlink(s)) + err(EXIT_FAILURE, _("unlinking %s failed"), s); + if (symlink(newname, s) != 0) + err(EXIT_FAILURE, _("symlinking %s to %s failed"), s, newname); + if (verbose) + printf("%s: `%s' -> `%s'\n", s, target, newname); + }else{ + if (rename(s, newname) != 0) + err(EXIT_FAILURE, _("renaming %s to %s failed"), + s, newname); + if (verbose) + printf("`%s' -> `%s'\n", s, newname); + } + free(newname); return 1; @@ -70,6 +108,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 +117,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, symlink=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 +132,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': + symlink = 1; + break; case 'V': printf(_("%s from %s\n"), program_invocation_short_name, @@ -120,7 +163,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, symlink); return EXIT_SUCCESS; } -- 1.7.8.6 -- To unsubscribe from this list: send the line "unsubscribe util-linux" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html