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. 38
      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

38
symlinks.c

@ -38,7 +38,9 @@ static int verbose = 0,
delete = 0,
shorten = 0,
testing = 0,
single_fs = 1;
single_fs = 1,
emb_rootfs = 0;
/*
* 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];
char *p, *np, *lp, *tail, *msg;
struct stat stbuf, lstbuf;
@ -240,6 +242,13 @@ static void fix_symlink(char *path, dev_t my_dev) {
}
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);
@ -247,8 +256,7 @@ static void fix_symlink(char *path, dev_t my_dev) {
/* 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,8 +297,12 @@ static void fix_symlink(char *path, dev_t my_dev) {
}
if (msg != NULL) {
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)) {
return;
@ -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++ == '/') {
@ -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);
}
@ -439,6 +453,7 @@ int main(int argc, char **argv) {
} 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();
@ -446,7 +461,6 @@ int main(int argc, char **argv) {
}
} 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