Initial revision
[oweals/busybox.git] / umount.c
1 #include "internal.h"
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <errno.h>
5 #include <string.h>
6 #include <stdio.h>
7 #include <mntent.h>
8 #include <sys/mount.h>
9
10 const char      umount_usage[] = "umount {filesystem|directory}\n"
11 "\tumount -a\n"
12 "\n"
13 "\tUnmount a filesystem.\n"
14 "\t-a:\tUnmounts all mounted filesystems.\n";
15
16 static char *
17 stralloc(const char * string)
18 {
19         int     length = strlen(string) + 1;
20         char *  n = malloc(length);
21         memcpy(n, string, length);
22         return n;
23 }
24
25 extern void
26 erase_mtab(const char * name)
27 {
28         struct mntent   entries[100];
29         int             count = 0;
30         FILE *          mountTable = setmntent("/etc/mtab", "r");
31         struct mntent * m;
32
33         if ( mountTable == 0
34          && (mountTable = setmntent("/proc/mounts", "r")) == 0 ) {
35                 name_and_error("/etc/mtab");
36                 return;
37         }
38
39         while ( (m = getmntent(mountTable)) != 0 ) {
40                 entries[count].mnt_fsname = stralloc(m->mnt_fsname);
41                 entries[count].mnt_dir = stralloc(m->mnt_dir);
42                 entries[count].mnt_type = stralloc(m->mnt_type);
43                 entries[count].mnt_opts = stralloc(m->mnt_opts);
44                 entries[count].mnt_freq = m->mnt_freq;
45                 entries[count].mnt_passno = m->mnt_passno;
46                 count++;
47         }
48         endmntent(mountTable);
49         if ( (mountTable = setmntent("/etc/mtab", "w")) ) {
50                 int     i;
51                 for ( i = 0; i < count; i++ ) {
52                         int result = ( strcmp(entries[i].mnt_fsname, name) == 0
53                          || strcmp(entries[i].mnt_dir, name) == 0 );
54
55                         if ( result )
56                                 continue;
57                         else
58                                 addmntent(mountTable, &entries[i]);
59                 }
60                 endmntent(mountTable);
61         }
62         else if ( errno != EROFS )
63                 name_and_error("/etc/mtab");
64 }
65
66 static int
67 umount_all(int noMtab)
68 {
69         struct mntent   entries[100];
70         int                             count = 0;
71         FILE *                  mountTable = setmntent("/etc/mtab", "r");
72         struct mntent * m;
73         int                             status = 0;
74
75         if ( mountTable == 0
76          && (mountTable = setmntent("/proc/mounts", "r")) == 0 ) {
77                 name_and_error("/etc/mtab");
78                 return 1;
79         }
80
81         while ( (m = getmntent(mountTable)) != 0 ) {
82                 entries[count].mnt_fsname = stralloc(m->mnt_fsname);
83                 count++;
84         }
85         endmntent(mountTable);
86
87         while ( count > 0 ) {
88                 int result = umount(entries[--count].mnt_fsname) == 0;
89                 /* free(entries[count].mnt_fsname); */
90                 if ( result ) {
91                         if ( !noMtab )
92                                 erase_mtab(entries[count].mnt_fsname);
93                 }
94                 else {
95                         status = 1;
96                         name_and_error(entries[count].mnt_fsname);
97                 }
98         }
99         return status;
100 }
101
102 extern int
103 do_umount(const char * name, int noMtab)
104 {
105         if ( umount(name) == 0 ) {
106                 if ( !noMtab )
107                         erase_mtab(name);
108                 return 0;
109         }
110         return 1;
111 }
112
113 extern int
114 umount_main(struct FileInfo * i, int argc, char * * argv)
115 {
116         int     noMtab = 0;
117
118         if ( argv[1][0] == '-' ) {
119                 switch ( argv[1][1] ) {
120                 case 'a':
121                         return umount_all(noMtab);
122                 case 'n':
123                         noMtab = 1;
124                         break;
125                 default:
126                         usage(umount_usage);
127                         return 1;
128                 }
129         }
130         if ( do_umount(argv[1],noMtab) != 0 ) {
131                 fprintf(stderr, "%s: %s.\n", argv[1], strerror(errno));
132                 return 1;
133         }
134         return 0;
135 }