From a6fc8b07f9fff4e055949e2386f8b494201d02ac Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 9 Jun 2009 13:24:11 +0200 Subject: [PATCH] switch_root: rewrite to use fstatat() and unlinkat() Signed-off-by: Peter Jones Signed-off-by: Karel Zak --- sys-utils/switch_root.c | 87 +++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/sys-utils/switch_root.c b/sys-utils/switch_root.c index 15203872..3c42c3d1 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) -- 2.39.5