From 05469ee13eab7a06acb50f5a311b384c5fac238b Mon Sep 17 00:00:00 2001 From: Victor Lowther Date: Sun, 8 Mar 2009 09:15:18 -0500 Subject: [PATCH] Remove all files on the initramfs before switching root The code from pjones's tree did not include the recursive remove code, so I readded it from the nash source code. --- switch_root.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/switch_root.c b/switch_root.c index be5720ed..1db062d8 100644 --- a/switch_root.c +++ b/switch_root.c @@ -34,6 +34,7 @@ #include #include #include +#include #ifndef MS_MOVE #define MS_MOVE 8192 @@ -49,6 +50,73 @@ enum { err_usage, }; +/* remove all files/directories below dirName -- don't cross mountpoints */ +static int +recursiveRemove(char * dirName) + { + struct stat sb,rb; + DIR * dir; + struct dirent * d; + char * strBuf = alloca(strlen(dirName) + 1024); + + if (!(dir = opendir(dirName))) { + printf("error opening %s: %m\n", dirName); + return 0; + } + + if (fstat(dirfd(dir),&rb)) { + printf("unable to stat %s: %m\n", dirName); + closedir(dir); + return 0; + } + + errno = 0; + while ((d = readdir(dir))) { + errno = 0; + + if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) { + errno = 0; + continue; + } + + strcpy(strBuf, dirName); + strcat(strBuf, "/"); + strcat(strBuf, d->d_name); + + if (lstat(strBuf, &sb)) { + printf("failed to stat %s: %m\n", strBuf); + errno = 0; + continue; + } + + /* only descend into subdirectories if device is same as dir */ + if (S_ISDIR(sb.st_mode)) { + 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; + } + } + + if (errno) { + closedir(dir); + printf("error reading from %s: %m\n", dirName); + return 1; + } + + closedir(dir); + + return 0; + } + static int switchroot(const char *newroot) { /* Don't try to unmount the old "/", there's no way to do it. */ @@ -74,7 +142,7 @@ static int switchroot(const char *newroot) errno=errnum; return -1; } - + recursiveRemove("/"); if (mount(newroot, "/", NULL, MS_MOVE, NULL) < 0) { errnum = errno; fprintf(stderr, "switchroot: mount failed: %m\n");