diff options
author | Jeremy Katz <katzj@redhat.com> | 2003-04-24 15:46:31 +0000 |
---|---|---|
committer | Jeremy Katz <katzj@redhat.com> | 2003-04-24 15:46:31 +0000 |
commit | 0a562126d84c59a113231ae7ab38984f92d62153 (patch) | |
tree | 5e87b9094f4ebdc328979e3a0640dee5f1fc40cb /loader2/undomounts.c | |
parent | dd200d781bd9012f562399c2ee69c23fe60d86b9 (diff) | |
download | anaconda-0a562126d84c59a113231ae7ab38984f92d62153.tar.gz anaconda-0a562126d84c59a113231ae7ab38984f92d62153.tar.xz anaconda-0a562126d84c59a113231ae7ab38984f92d62153.zip |
another taroon merge. tagged before as before-taroon-merge, after as
after-taroon-merge
this one adds s390 fixes, basic i/p series platform support, support for
multiple kernels and one second stage, cmdline kickstart mode (nice for s390),
some warning cleanups.
Diffstat (limited to 'loader2/undomounts.c')
-rw-r--r-- | loader2/undomounts.c | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/loader2/undomounts.c b/loader2/undomounts.c new file mode 100644 index 000000000..07892af57 --- /dev/null +++ b/loader2/undomounts.c @@ -0,0 +1,228 @@ +/* + * undomounts.c + * + * Handles some basic unmounting stuff for init + * Broken out so that it can be used on s390 in a shutdown binary + * + * Erik Troan <ewt@redhat.com> + * Jeremy Katz <katzj@redhat.com> + * + * Copyright 1996 - 2003 Red Hat, Inc. + * + * This software may be freely redistributed under the terms of the GNU + * public license. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <sys/swap.h> +#include <unistd.h> + +#include "devt.h" + +struct unmountInfo { + char * name; + int mounted; + int loopDevice; + enum { FS, LOOP } what; +} ; + +extern int testing; + +void undoLoop(struct unmountInfo * fs, int numFs, int this); + +static void printstr(char * string) { + write(1, string, strlen(string)); +} + +void undoMount(struct unmountInfo * fs, int numFs, int this) { + int len = strlen(fs[this].name); + int i; + + if (!fs[this].mounted) return; + fs[this].mounted = 0; + + /* unmount everything underneath this */ + for (i = 0; i < numFs; i++) { + if (fs[i].name && (strlen(fs[i].name) >= len) && + (fs[i].name[len] == '/') && + !strncmp(fs[this].name, fs[i].name, len)) { + if (fs[i].what == LOOP) + undoLoop(fs, numFs, i); + else + undoMount(fs, numFs, i); + } + } + + printf("\t%s", fs[this].name); + /* don't need to unmount /tmp. it is busy anyway. */ + if (!testing) { + if (umount2(fs[this].name, 0) < 0) { + printf(" umount failed (%d)", errno); + } else { + printf(" done"); + } + } + printf("\n"); +} + +void undoLoop(struct unmountInfo * fs, int numFs, int this) { + int i; + int fd; + + if (!fs[this].mounted) return; + fs[this].mounted = 0; + + /* find the device mount */ + for (i = 0; i < numFs; i++) { + if (fs[i].what == FS && (fs[i].loopDevice == fs[this].loopDevice)) + break; + } + + if (i < numFs) { + /* the device is mounted, unmount it (and recursively, anything + * underneath) */ + undoMount(fs, numFs, i); + } + + unlink("/tmp/loop"); + mknod("/tmp/loop", 0600 | S_IFBLK, (7 << 8) | fs[this].loopDevice); + printf("\tdisabling /dev/loop%d", fs[this].loopDevice); + if ((fd = open("/tmp/loop", O_RDONLY, 0)) < 0) { + printf(" failed to open device: %d", errno); + } else { + if (!testing && ioctl(fd, LOOP_CLR_FD, 0)) + printf(" LOOP_CLR_FD failed: %d", errno); + close(fd); + } + + printf("\n"); +} + +void unmountFilesystems(void) { + int fd, size; + char buf[65535]; /* this should be big enough */ + char * chptr, * start; + struct unmountInfo filesystems[500]; + int numFilesystems = 0; + int i; + struct loop_info li; + char * device; + struct stat sb; + + fd = open("/proc/mounts", O_RDONLY, 0); + if (fd < 1) { + /* FIXME: was perror */ + printstr("failed to open /proc/mounts"); + sleep(2); + return; + } + + size = read(fd, buf, sizeof(buf) - 1); + buf[size] = '\0'; + + close(fd); + + chptr = buf; + while (*chptr) { + device = chptr; + while (*chptr != ' ') chptr++; + *chptr++ = '\0'; + start = chptr; + while (*chptr != ' ') chptr++; + *chptr++ = '\0'; + + if (strcmp(start, "/") && strcmp(start, "/tmp")) { + filesystems[numFilesystems].name = strdup(start); + filesystems[numFilesystems].what = FS; + filesystems[numFilesystems].mounted = 1; + + stat(start, &sb); + if ((sb.st_dev >> 8) == 7) { + filesystems[numFilesystems].loopDevice = sb.st_dev & 0xf; + } else { + filesystems[numFilesystems].loopDevice = -1; + } + + numFilesystems++; + } + + while (*chptr != '\n') chptr++; + chptr++; + } + + for (i = 0; i < 7; i++) { + unlink("/tmp/loop"); + mknod("/tmp/loop", 0600 | S_IFBLK, (7 << 8) | i); + if ((fd = open("/tmp/loop", O_RDONLY, 0)) >= 0) { + if (!ioctl(fd, LOOP_GET_STATUS, &li) && li.lo_name[0]) { + filesystems[numFilesystems].name = strdup(li.lo_name); + filesystems[numFilesystems].what = LOOP; + filesystems[numFilesystems].mounted = 1; + filesystems[numFilesystems].loopDevice = i; + numFilesystems++; + } + + close(fd); + } + } + + for (i = 0; i < numFilesystems; i++) { + if (filesystems[i].what == LOOP) { + undoLoop(filesystems, numFilesystems, i); + } + } + + for (i = 0; i < numFilesystems; i++) { + if ((filesystems[i].mounted) && (filesystems[i].name)) { + undoMount(filesystems, numFilesystems, i); + } + } + + for (i = 0; i < numFilesystems; i++) + free(filesystems[i].name); +} + +void disableSwap(void) { + int fd; + char buf[4096]; + int i; + char * start; + char * chptr; + + if ((fd = open("/proc/swaps", O_RDONLY, 0)) < 0) return; + + i = read(fd, buf, sizeof(buf) - 1); + close(fd); + if (i < 0) return; + buf[i] = '\0'; + + start = buf; + while (*start) { + while (*start != '\n' && *start) start++; + if (!*start) return; + + start++; + if (*start != '/') return; + chptr = start; + while (*chptr && *chptr != ' ') chptr++; + if (!(*chptr)) return; + *chptr = '\0'; + printf("\t%s", start); + if (swapoff(start)) + printf(" failed (%d)", errno); + printf("\n"); + + start = chptr + 1; + } +} |