Browse Source

Symlinks now also works on embedded root filesystems relative to the system rootfs.

Now it's possible to fix and change symlinks in embedded root filesystems (e.g. /gpfs/sys/ubuntu11.04) without the need of chroot or fakechroot.
Therefore option -e has been added, to tell symlinks that it operates in a relative rootfs.
The current working directory is taken as the relative path to the system root, so symlinks has to be called within the rootfs directory.
pull/2/head
Philipp Lutz 10 years ago
parent
commit
1358d567a6
  1. 4
      Readme.md
  2. 5
      symlinks.8
  3. 68
      symlinks.c

4
Readme.md

@ -38,6 +38,10 @@ Usage
$ symlinks -rc [path] $ 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: ### More options:

5
symlinks.8

@ -102,6 +102,11 @@ would do if
.B -c .B -c
were specified, but without really changing anything. were specified, but without really changing anything.
.TP .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 .I -v
show all symbolic links. By default, show all symbolic links. By default,
.B relative .B relative

68
symlinks.c

@ -33,12 +33,14 @@
static char *progname; static char *progname;
static int verbose = 0, 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 * tidypath removes excess slashes and "." references from a path string
@ -211,7 +213,7 @@ 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]; static char lpath[PATH_MAX], new[PATH_MAX], abspath[PATH_MAX];
char *p, *np, *lp, *tail, *msg; char *p, *np, *lp, *tail, *msg;
struct stat stbuf, lstbuf; struct stat stbuf, lstbuf;
@ -232,14 +234,21 @@ static void fix_symlink(char *path, dev_t my_dev) {
c = strlen(abspath); c = strlen(abspath);
if ((c > 0) && (abspath[c - 1] == '/')) { if ((c > 0) && (abspath[c - 1] == '/')) {
abspath[c - 1] = '\0'; /* cut trailing / */
abspath[c - 1] = '\0'; /* cut trailing / */
} }
if ((p = strrchr(abspath, '/')) != NULL) { if ((p = strrchr(abspath, '/')) != NULL) {
*p = '\0'; /* cut last component */
*p = '\0'; /* cut last component */
} }
strcat(abspath, "/"); 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); strcat(abspath, lpath);
@ -247,8 +256,7 @@ static void fix_symlink(char *path, dev_t my_dev) {
/* check for various things */ /* check for various things */
if (stat(abspath, &stbuf) == -1) { 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 (delete) {
if (unlink(path)) { if (unlink(path)) {
perror(path); perror(path);
@ -256,7 +264,6 @@ static void fix_symlink(char *path, dev_t my_dev) {
printf("deleted: %s -> %s\n", path, lpath); printf("deleted: %s -> %s\n", path, lpath);
} }
} }
return; return;
} }
@ -290,7 +297,11 @@ static void fix_symlink(char *path, dev_t my_dev) {
} }
if (msg != NULL) { 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)) { 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 */ /* point p at first part of path that differs from lpath */
(void) tidy_path(lpath); (void) tidy_path(lpath);
tail = lp = lpath; tail = lp = lpath;
p = path;
p = path + strlen(cwd); // skip rootfs prefix
while (*p && (*p == *lp)) { while (*p && (*p == *lp)) {
if (*lp++ == '/') { if (*lp++ == '/') {
@ -353,7 +364,7 @@ static void fix_symlink(char *path, dev_t my_dev) {
printf("changed: %s -> %s\n", path, new); 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; char *name;
DIR *dfd; DIR *dfd;
static struct stat st; static struct stat st;
@ -378,9 +389,9 @@ static void dirwalk(char *path, unsigned long pathlen, dev_t dev) {
perror(path); perror(path);
} else if (st.st_dev == dev) { } else if (st.st_dev == dev) {
if (S_ISLNK(st.st_mode)) { if (S_ISLNK(st.st_mode)) {
fix_symlink(path, dev);
fix_symlink(cwd, path, dev);
} else if (recurse && S_ISDIR(st.st_mode)) { } 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-r recurse into subdirs\n"
"\t-s shorten lengthy links (displayed in output only when -c not specified)\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-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); exit(1);
} }
@ -433,20 +447,20 @@ int main(int argc, char **argv) {
} }
while ((c = *p++)) { 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 { } else {
usage_error(); usage_error();
} }
} }
} else { } else {
struct stat st; struct stat st;
if (*p == '/') { if (*p == '/') {
*path = '\0'; *path = '\0';
} else { } else {
@ -458,7 +472,7 @@ int main(int argc, char **argv) {
if (lstat(path, &st) == -1) { if (lstat(path, &st) == -1) {
perror(path); perror(path);
} else { } else {
dirwalk(path, strlen(path), st.st_dev);
dirwalk(cwd, path, strlen(path), st.st_dev);
} }
++dircount; ++dircount;

Loading…
Cancel
Save