diff options
Diffstat (limited to 'umount.c')
-rw-r--r-- | umount.c | 291 |
1 files changed, 150 insertions, 141 deletions
@@ -1,3 +1,4 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
1 | /* | 2 | /* |
2 | * Mini umount implementation for busybox | 3 | * Mini umount implementation for busybox |
3 | * | 4 | * |
@@ -28,24 +29,23 @@ | |||
28 | #include <fstab.h> | 29 | #include <fstab.h> |
29 | #include <errno.h> | 30 | #include <errno.h> |
30 | 31 | ||
31 | static const char umount_usage[] = | 32 | static const char umount_usage[] = |
32 | "umount [flags] filesystem|directory\n\n" | 33 | "umount [flags] filesystem|directory\n\n" |
33 | "Flags:\n" | 34 | "Flags:\n" "\t-a:\tUnmount all file systems" |
34 | "\t-a:\tUnmount all file systems" | ||
35 | #ifdef BB_MTAB | 35 | #ifdef BB_MTAB |
36 | " in /etc/mtab\n\t-n:\tDon't erase /etc/mtab entries\n" | 36 | " in /etc/mtab\n\t-n:\tDon't erase /etc/mtab entries\n" |
37 | #else | 37 | #else |
38 | "\n" | 38 | "\n" |
39 | #endif | 39 | #endif |
40 | #ifdef BB_FEATURE_REMOUNT | 40 | #ifdef BB_FEATURE_REMOUNT |
41 | "\t-r:\tTry to remount devices as read-only if mount is busy\n" | 41 | "\t-r:\tTry to remount devices as read-only if mount is busy\n" |
42 | #endif | 42 | #endif |
43 | ; | 43 | ; |
44 | 44 | ||
45 | struct _mtab_entry_t { | 45 | struct _mtab_entry_t { |
46 | char *device; | 46 | char *device; |
47 | char *mountpt; | 47 | char *mountpt; |
48 | struct _mtab_entry_t *next; | 48 | struct _mtab_entry_t *next; |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static struct _mtab_entry_t *mtab_cache = NULL; | 51 | static struct _mtab_entry_t *mtab_cache = NULL; |
@@ -55,113 +55,112 @@ static struct _mtab_entry_t *mtab_cache = NULL; | |||
55 | static int useMtab = TRUE; | 55 | static int useMtab = TRUE; |
56 | static int umountAll = FALSE; | 56 | static int umountAll = FALSE; |
57 | static int doRemount = FALSE; | 57 | static int doRemount = FALSE; |
58 | extern const char mtab_file[]; /* Defined in utility.c */ | 58 | extern const char mtab_file[]; /* Defined in utility.c */ |
59 | 59 | ||
60 | #define MIN(x,y) (x > y ? x : y) | 60 | #define MIN(x,y) (x > y ? x : y) |
61 | 61 | ||
62 | static int | 62 | static int do_umount(const char *name, int useMtab) |
63 | do_umount(const char* name, int useMtab) | ||
64 | { | 63 | { |
65 | int status; | 64 | int status; |
66 | char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE); | 65 | char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE); |
67 | 66 | ||
68 | if (blockDevice && strcmp(blockDevice, name) == 0) | 67 | if (blockDevice && strcmp(blockDevice, name) == 0) |
69 | name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT); | 68 | name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT); |
70 | 69 | ||
71 | status = umount(name); | 70 | status = umount(name); |
72 | 71 | ||
73 | #if defined BB_FEATURE_MOUNT_LOOP | 72 | #if defined BB_FEATURE_MOUNT_LOOP |
74 | if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9)) | 73 | if (blockDevice != NULL && !strncmp("/dev/loop", blockDevice, 9)) |
75 | /* this was a loop device, delete it */ | 74 | /* this was a loop device, delete it */ |
76 | del_loop(blockDevice); | 75 | del_loop(blockDevice); |
77 | #endif | 76 | #endif |
78 | #if defined BB_FEATURE_REMOUNT | 77 | #if defined BB_FEATURE_REMOUNT |
79 | if ( status != 0 && doRemount == TRUE && errno == EBUSY ) { | 78 | if (status != 0 && doRemount == TRUE && errno == EBUSY) { |
80 | status = mount(blockDevice, name, NULL, | 79 | status = mount(blockDevice, name, NULL, |
81 | MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL); | 80 | MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL); |
82 | if (status == 0) { | 81 | if (status == 0) { |
83 | fprintf(stderr, "umount: %s busy - remounted read-only\n", | 82 | fprintf(stderr, "umount: %s busy - remounted read-only\n", |
84 | blockDevice); | 83 | blockDevice); |
85 | /* TODO: update mtab if BB_MTAB is defined */ | 84 | /* TODO: update mtab if BB_MTAB is defined */ |
86 | } else { | 85 | } else { |
87 | fprintf(stderr, "umount: Cannot remount %s read-only\n", | 86 | fprintf(stderr, "umount: Cannot remount %s read-only\n", |
88 | blockDevice); | 87 | blockDevice); |
88 | } | ||
89 | } | 89 | } |
90 | } | ||
91 | #endif | 90 | #endif |
92 | if ( status == 0 ) { | 91 | if (status == 0) { |
93 | #if defined BB_MTAB | 92 | #if defined BB_MTAB |
94 | if ( useMtab==TRUE ) | 93 | if (useMtab == TRUE) |
95 | erase_mtab(name); | 94 | erase_mtab(name); |
96 | #endif | 95 | #endif |
97 | return( TRUE); | 96 | return (TRUE); |
98 | } | 97 | } |
99 | return(FALSE); | 98 | return (FALSE); |
100 | } | 99 | } |
101 | 100 | ||
102 | static int | 101 | static int umount_all(int useMtab) |
103 | umount_all(int useMtab) | ||
104 | { | 102 | { |
105 | int status = TRUE; | 103 | int status = TRUE; |
106 | char *mountpt; | 104 | char *mountpt; |
107 | void *iter; | 105 | void *iter; |
108 | 106 | ||
109 | for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) { | 107 | for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) { |
110 | status=do_umount (mountpt, useMtab); | 108 | status = do_umount(mountpt, useMtab); |
111 | if (status != 0) { | ||
112 | /* Don't bother retrying the umount on busy devices */ | ||
113 | if (errno == EBUSY) { | ||
114 | perror(mountpt); | ||
115 | continue; | ||
116 | } | ||
117 | status = do_umount (mountpt, useMtab); | ||
118 | if (status != 0) { | 109 | if (status != 0) { |
119 | printf ("Couldn't umount %s on %s: %s\n", | 110 | /* Don't bother retrying the umount on busy devices */ |
120 | mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE), strerror(errno)); | 111 | if (errno == EBUSY) { |
112 | perror(mountpt); | ||
113 | continue; | ||
114 | } | ||
115 | status = do_umount(mountpt, useMtab); | ||
116 | if (status != 0) { | ||
117 | printf("Couldn't umount %s on %s: %s\n", | ||
118 | mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE), | ||
119 | strerror(errno)); | ||
120 | } | ||
121 | } | 121 | } |
122 | } | 122 | } |
123 | } | 123 | return (status); |
124 | return (status); | ||
125 | } | 124 | } |
126 | 125 | ||
127 | extern int | 126 | extern int umount_main(int argc, char **argv) |
128 | umount_main(int argc, char** argv) | ||
129 | { | 127 | { |
130 | if (argc < 2) { | 128 | if (argc < 2) { |
131 | usage( umount_usage); | 129 | usage(umount_usage); |
132 | } | 130 | } |
133 | 131 | ||
134 | /* Parse any options */ | 132 | /* Parse any options */ |
135 | while (--argc > 0 && **(++argv) == '-') { | 133 | while (--argc > 0 && **(++argv) == '-') { |
136 | while (*++(*argv)) switch (**argv) { | 134 | while (*++(*argv)) |
137 | case 'a': | 135 | switch (**argv) { |
138 | umountAll = TRUE; | 136 | case 'a': |
139 | break; | 137 | umountAll = TRUE; |
138 | break; | ||
140 | #ifdef BB_MTAB | 139 | #ifdef BB_MTAB |
141 | case 'n': | 140 | case 'n': |
142 | useMtab = FALSE; | 141 | useMtab = FALSE; |
143 | break; | 142 | break; |
144 | #endif | 143 | #endif |
145 | #ifdef BB_FEATURE_REMOUNT | 144 | #ifdef BB_FEATURE_REMOUNT |
146 | case 'r': | 145 | case 'r': |
147 | doRemount = TRUE; | 146 | doRemount = TRUE; |
148 | break; | 147 | break; |
149 | #endif | 148 | #endif |
150 | default: | 149 | default: |
151 | usage( umount_usage); | 150 | usage(umount_usage); |
151 | } | ||
152 | } | ||
153 | |||
154 | mtab_read(); | ||
155 | if (umountAll == TRUE) { | ||
156 | exit(umount_all(useMtab)); | ||
157 | } | ||
158 | if (do_umount(*argv, useMtab) == 0) | ||
159 | exit(TRUE); | ||
160 | else { | ||
161 | perror("umount"); | ||
162 | exit(FALSE); | ||
152 | } | 163 | } |
153 | } | ||
154 | |||
155 | mtab_read(); | ||
156 | if (umountAll==TRUE) { | ||
157 | exit(umount_all(useMtab)); | ||
158 | } | ||
159 | if ( do_umount(*argv,useMtab) == 0 ) | ||
160 | exit (TRUE); | ||
161 | else { | ||
162 | perror("umount"); | ||
163 | exit(FALSE); | ||
164 | } | ||
165 | } | 164 | } |
166 | 165 | ||
167 | 166 | ||
@@ -172,79 +171,89 @@ umount_main(int argc, char** argv) | |||
172 | */ | 171 | */ |
173 | void mtab_read(void) | 172 | void mtab_read(void) |
174 | { | 173 | { |
175 | struct _mtab_entry_t *entry = NULL; | 174 | struct _mtab_entry_t *entry = NULL; |
176 | struct mntent *e; | 175 | struct mntent *e; |
177 | FILE *fp; | 176 | FILE *fp; |
178 | 177 | ||
179 | if (mtab_cache != NULL) return; | 178 | if (mtab_cache != NULL) |
180 | 179 | return; | |
181 | if ((fp = setmntent(mtab_file, "r")) == NULL) { | 180 | |
182 | fprintf(stderr, "Cannot open %s\n", mtab_file); | 181 | if ((fp = setmntent(mtab_file, "r")) == NULL) { |
183 | return; | 182 | fprintf(stderr, "Cannot open %s\n", mtab_file); |
184 | } | 183 | return; |
185 | while ((e = getmntent(fp))) { | 184 | } |
186 | entry = malloc(sizeof(struct _mtab_entry_t)); | 185 | while ((e = getmntent(fp))) { |
187 | entry->device = strdup(e->mnt_fsname); | 186 | entry = malloc(sizeof(struct _mtab_entry_t)); |
188 | entry->mountpt = strdup(e->mnt_dir); | 187 | |
189 | entry->next = mtab_cache; | 188 | entry->device = strdup(e->mnt_fsname); |
190 | mtab_cache = entry; | 189 | entry->mountpt = strdup(e->mnt_dir); |
191 | } | 190 | entry->next = mtab_cache; |
192 | endmntent(fp); | 191 | mtab_cache = entry; |
192 | } | ||
193 | endmntent(fp); | ||
193 | } | 194 | } |
194 | 195 | ||
195 | char *mtab_getinfo(const char *match, const char which) | 196 | char *mtab_getinfo(const char *match, const char which) |
196 | { | 197 | { |
197 | struct _mtab_entry_t *cur = mtab_cache; | 198 | struct _mtab_entry_t *cur = mtab_cache; |
198 | while (cur) { | 199 | |
199 | if (strcmp(cur->mountpt, match) == 0 || | 200 | while (cur) { |
200 | strcmp(cur->device, match) == 0) { | 201 | if (strcmp(cur->mountpt, match) == 0 || |
201 | if (which == MTAB_GETMOUNTPT) { | 202 | strcmp(cur->device, match) == 0) { |
202 | return cur->mountpt; | 203 | if (which == MTAB_GETMOUNTPT) { |
203 | } else { | 204 | return cur->mountpt; |
205 | } else { | ||
204 | #if !defined BB_MTAB | 206 | #if !defined BB_MTAB |
205 | if (strcmp(cur->device, "/dev/root") == 0) { | 207 | if (strcmp(cur->device, "/dev/root") == 0) { |
206 | struct fstab* fstabItem; | 208 | struct fstab *fstabItem; |
207 | fstabItem = getfsfile ("/"); | 209 | |
208 | if (fstabItem != NULL) return fstabItem->fs_spec; | 210 | fstabItem = getfsfile("/"); |
209 | } | 211 | if (fstabItem != NULL) |
212 | return fstabItem->fs_spec; | ||
213 | } | ||
210 | #endif | 214 | #endif |
211 | return cur->device; | 215 | return cur->device; |
212 | } | 216 | } |
217 | } | ||
218 | cur = cur->next; | ||
213 | } | 219 | } |
214 | cur = cur->next; | 220 | return NULL; |
215 | } | ||
216 | return NULL; | ||
217 | } | 221 | } |
218 | 222 | ||
219 | char *mtab_first(void **iter) | 223 | char *mtab_first(void **iter) |
220 | { | 224 | { |
221 | struct _mtab_entry_t *mtab_iter; | 225 | struct _mtab_entry_t *mtab_iter; |
222 | if (!iter) return NULL; | 226 | |
223 | mtab_iter = mtab_cache; | 227 | if (!iter) |
224 | *iter = (void *)mtab_iter; | 228 | return NULL; |
225 | return mtab_next(iter); | 229 | mtab_iter = mtab_cache; |
230 | *iter = (void *) mtab_iter; | ||
231 | return mtab_next(iter); | ||
226 | } | 232 | } |
227 | 233 | ||
228 | char *mtab_next(void **iter) | 234 | char *mtab_next(void **iter) |
229 | { | 235 | { |
230 | char *mp; | 236 | char *mp; |
231 | if (iter == NULL || *iter == NULL) return NULL; | 237 | |
232 | mp = ((struct _mtab_entry_t *)(*iter))->mountpt; | 238 | if (iter == NULL || *iter == NULL) |
233 | *iter = (void *)((struct _mtab_entry_t *)(*iter))->next; | 239 | return NULL; |
234 | return mp; | 240 | mp = ((struct _mtab_entry_t *) (*iter))->mountpt; |
241 | *iter = (void *) ((struct _mtab_entry_t *) (*iter))->next; | ||
242 | return mp; | ||
235 | } | 243 | } |
236 | 244 | ||
237 | void mtab_free(void) | 245 | void mtab_free(void) |
238 | { | 246 | { |
239 | struct _mtab_entry_t *this, *next; | 247 | struct _mtab_entry_t *this, *next; |
240 | |||
241 | this = mtab_cache; | ||
242 | while (this) { | ||
243 | next = this->next; | ||
244 | if (this->device) free(this->device); | ||
245 | if (this->mountpt) free(this->mountpt); | ||
246 | free(this); | ||
247 | this = next; | ||
248 | } | ||
249 | } | ||
250 | 248 | ||
249 | this = mtab_cache; | ||
250 | while (this) { | ||
251 | next = this->next; | ||
252 | if (this->device) | ||
253 | free(this->device); | ||
254 | if (this->mountpt) | ||
255 | free(this->mountpt); | ||
256 | free(this); | ||
257 | this = next; | ||
258 | } | ||
259 | } | ||