On 06/19/2009 05:26 AM, Karel Zak wrote: > Signed-off-by: Karel Zak <kzak@xxxxxxxxxx> Signed-off-by: Peter Jones <pjones@xxxxxxxxxx> > --- > sys-utils/switch_root.c | 87 ++++++++++++++++++++++++----------------------- > 1 files changed, 44 insertions(+), 43 deletions(-) > > diff --git a/sys-utils/switch_root.c b/sys-utils/switch_root.c > index 1520387..3c42c3d 100644 > --- a/sys-utils/switch_root.c > +++ b/sys-utils/switch_root.c > @@ -44,70 +44,71 @@ enum { > }; > > /* remove all files/directories below dirName -- don't cross mountpoints */ > -static int > -recursiveRemove(char * dirName) > +static int recursiveRemove(char *dirName) > { > - struct stat sb,rb; > - DIR * dir; > - struct dirent * d; > - char * strBuf = alloca(strlen(dirName) + 1024); > + struct stat rb; > + DIR *dir; > + int rc = -1; > + int dfd; > > if (!(dir = opendir(dirName))) { > printf("error opening %s: %m\n", dirName); > - return 0; > + goto done; > } > > - if (fstat(dirfd(dir),&rb)) { > + dfd = dirfd(dir); > + > + if (fstat(dfd, &rb)) { > printf("unable to stat %s: %m\n", dirName); > - closedir(dir); > - return 0; > + goto done; > } > > - errno = 0; > + while(1) { > + struct dirent *d; > > - while ((d = readdir(dir))) { > errno = 0; > + if (!(d = readdir(dir))) { > + if (errno) { > + printf("error reading from %s: %m\n", dirName); > + goto done; > + } > + break; /* end of directory */ > + } > > - if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) { > - errno = 0; > + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) > continue; > - } > > - strcpy(strBuf, dirName); > - strcat(strBuf, "/"); > - strcat(strBuf, d->d_name); > + if (d->d_type == DT_DIR) { > + struct stat sb; > > - if (lstat(strBuf, &sb)) { > - printf("failed to stat %s: %m\n", strBuf); > - errno = 0; > - continue; > - } > + if (fstatat(dfd, d->d_name, &sb, AT_SYMLINK_NOFOLLOW)) { > + printf("failed to stat %s/%s: %m\n", > + dirName, d->d_name); > + continue; > + } > > - /* only descend into subdirectories if device is same as dir */ > - if (S_ISDIR(sb.st_mode)) { > + /* remove subdirectories if device is same as dir */ > if (sb.st_dev == rb.st_dev) { > - recursiveRemove(strBuf); > - if (rmdir(strBuf)) > - printf("failed to rmdir %s: %m\n", strBuf); > - } > - errno = 0; > - continue; > - } > - if (unlink(strBuf)) { > - printf("failed to remove %s: %m\n", strBuf); > - errno = 0; > - continue; > + char subdir[ strlen(dirName) + > + strlen(d->d_name) + 2 ]; > + > + sprintf(subdir, "%s/%s", dirName, d->d_name); > + recursiveRemove(subdir); > + } else > + continue; > } > - } > > - if (errno) { > - closedir(dir); > - printf("error reading from %s: %m\n", dirName); > - return 1; > + if (unlinkat(dfd, d->d_name, > + d->d_type == DT_DIR ? AT_REMOVEDIR : 0)) > + printf("failed to unlink %s/%s: %m\n", dirName, d->d_name); > } > > - closedir(dir); > - return 0; > + rc = 0; /* success */ > + > +done: > + if (dir) > + closedir(dir); > + return rc; > } > > static int switchroot(const char *newroot) -- Peter Gravity is a habit that is hard to shake off. -- Pratchett -- To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html