diff --git a/Readme.md b/Readme.md index 7aaa5c5..251f108 100644 --- a/Readme.md +++ b/Readme.md @@ -38,6 +38,10 @@ Usage $ symlinks -rc [path] +### Convert absolute symlinks in an embedded rootfs, which lies within the + system rootfs, e.g. in /gpfs/sys/ubuntu11.04. Make sure to cd into rootfs before executing: + $ cd /gpfs/sys/ubuntu11.04 + $ symlinks -rec [path] ### More options: diff --git a/symlinks.8 b/symlinks.8 index aa443cf..f551e26 100644 --- a/symlinks.8 +++ b/symlinks.8 @@ -102,6 +102,11 @@ would do if .B -c were specified, but without really changing anything. .TP +.I -e +work on an embedded rootfs which is relative to the system rootfs without +the need to chroot / fakechroot into it, e.g. in /gpfs/sys/ubuntu11.04. +Make sure to cd into rootfs before executing +.TP .I -v show all symbolic links. By default, .B relative diff --git a/symlinks.c b/symlinks.c index 243f7b4..0244cdf 100644 --- a/symlinks.c +++ b/symlinks.c @@ -33,12 +33,14 @@ static char *progname; static int verbose = 0, - fix_links = 0, - recurse = 0, - delete = 0, - shorten = 0, - testing = 0, - single_fs = 1; + fix_links = 0, + recurse = 0, + delete = 0, + shorten = 0, + testing = 0, + single_fs = 1, + emb_rootfs = 0; + /* * tidypath removes excess slashes and "." references from a path string @@ -211,13 +213,13 @@ ughh: } -static void fix_symlink(char *path, dev_t my_dev) { +static void fix_symlink(char *cwd, char *path, dev_t my_dev) { static char lpath[PATH_MAX], new[PATH_MAX], abspath[PATH_MAX]; char *p, *np, *lp, *tail, *msg; struct stat stbuf, lstbuf; int fix_abs = 0, fix_messy = 0, fix_long = 0; size_t c; - + if ((c = readlink(path, lpath, sizeof(lpath))) == -1) { perror(path); return; @@ -232,23 +234,29 @@ static void fix_symlink(char *path, dev_t my_dev) { c = strlen(abspath); if ((c > 0) && (abspath[c - 1] == '/')) { - abspath[c - 1] = '\0'; /* cut trailing / */ + abspath[c - 1] = '\0'; /* cut trailing / */ } if ((p = strrchr(abspath, '/')) != NULL) { - *p = '\0'; /* cut last component */ + *p = '\0'; /* cut last component */ } strcat(abspath, "/"); + } else { + if (emb_rootfs) { + // we have an absolute path and work on an embbedded rootfs, + // so we have to add the rootfs prefix from cwd in order to find + // the targets of absolute symlinks + strcpy(abspath, cwd); + } } - + strcat(abspath, lpath); (void) tidy_path(abspath); /* check for various things */ if (stat(abspath, &stbuf) == -1) { - printf("dangling: %s -> %s\n", path, lpath); - + printf("dangling: %s -> %s (reason: %s)\n", path, lpath, strerror(errno)); if (delete) { if (unlink(path)) { perror(path); @@ -256,7 +264,6 @@ static void fix_symlink(char *path, dev_t my_dev) { printf("deleted: %s -> %s\n", path, lpath); } } - return; } @@ -290,7 +297,11 @@ static void fix_symlink(char *path, dev_t my_dev) { } if (msg != NULL) { - printf("%s %s -> %s\n", msg, path, lpath); + if (fix_abs && emb_rootfs) { + printf("%s %s -> %s (resolved to %s)\n", msg, path, lpath, abspath); + } else { + printf("%s %s -> %s\n", msg, path, lpath); + } } if (!(fix_links || testing) || !(fix_messy || fix_abs || fix_long)) { @@ -303,7 +314,7 @@ static void fix_symlink(char *path, dev_t my_dev) { /* point p at first part of path that differs from lpath */ (void) tidy_path(lpath); tail = lp = lpath; - p = path; + p = path + strlen(cwd); // skip rootfs prefix while (*p && (*p == *lp)) { if (*lp++ == '/') { @@ -337,7 +348,7 @@ static void fix_symlink(char *path, dev_t my_dev) { } shorten_path(new, path); - + if (!testing) { if (unlink(path)) { perror(path); @@ -353,7 +364,7 @@ static void fix_symlink(char *path, dev_t my_dev) { printf("changed: %s -> %s\n", path, new); } -static void dirwalk(char *path, unsigned long pathlen, dev_t dev) { +static void dirwalk(char *cwd, char *path, unsigned long pathlen, dev_t dev) { char *name; DIR *dfd; static struct stat st; @@ -378,9 +389,9 @@ static void dirwalk(char *path, unsigned long pathlen, dev_t dev) { perror(path); } else if (st.st_dev == dev) { if (S_ISLNK(st.st_mode)) { - fix_symlink(path, dev); + fix_symlink(cwd, path, dev); } else if (recurse && S_ISDIR(st.st_mode)) { - dirwalk(path, strlen(path), dev); + dirwalk(cwd, path, strlen(path), dev); } } } @@ -400,7 +411,10 @@ static void usage_error(void) { "\t-r recurse into subdirs\n" "\t-s shorten lengthy links (displayed in output only when -c not specified)\n" "\t-t show what would be done by -c\n" - "\t-v verbose (show all symlinks)\n\n"); + "\t-e work on an embedded rootfs which is relative to the system rootfs without\n" + "\t the need to chroot / fakechroot into it, e.g. in /gpfs/sys/ubuntu11.04.\n" + "\t Make sure to cd into rootfs before executing %s\n" + "\t-v verbose (show all symlinks)\n\n", progname); exit(1); } @@ -423,7 +437,7 @@ int main(int argc, char **argv) { if (!*cwd || cwd[strlen(cwd) - 1] != '/') { strcat(cwd, "/"); } - + while (--argc) { p = *++argv; @@ -433,20 +447,20 @@ int main(int argc, char **argv) { } while ((c = *p++)) { - if (c == 'c') { fix_links = 1; - } else if (c == 'd') { delete = 1; - } else if (c == 'o') { single_fs = 0; - } else if (c == 'r') { recurse = 1; - } else if (c == 's') { shorten = 1; - } else if (c == 't') { testing = 1; - } else if (c == 'v') { verbose = 1; + if (c == 'c') { fix_links = 1; + } else if (c == 'd') { delete = 1; + } else if (c == 'o') { single_fs = 0; + } else if (c == 'r') { recurse = 1; + } else if (c == 's') { shorten = 1; + } else if (c == 't') { testing = 1; + } else if (c == 'e') { emb_rootfs = 1; + } else if (c == 'v') { verbose = 1; } else { usage_error(); } } } else { struct stat st; - if (*p == '/') { *path = '\0'; } else { @@ -458,7 +472,7 @@ int main(int argc, char **argv) { if (lstat(path, &st) == -1) { perror(path); } else { - dirwalk(path, strlen(path), st.st_dev); + dirwalk(cwd, path, strlen(path), st.st_dev); } ++dircount;