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. 76
      symlinks.c

4
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:

5
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

76
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;

Loading…
Cancel
Save