aboutsummaryrefslogtreecommitdiff
path: root/umount.c
diff options
context:
space:
mode:
Diffstat (limited to 'umount.c')
-rw-r--r--umount.c291
1 files changed, 150 insertions, 141 deletions
diff --git a/umount.c b/umount.c
index b65caf76e..a2ca8c74a 100644
--- a/umount.c
+++ b/umount.c
@@ -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
31static const char umount_usage[] = 32static 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
45struct _mtab_entry_t { 45struct _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
51static struct _mtab_entry_t *mtab_cache = NULL; 51static struct _mtab_entry_t *mtab_cache = NULL;
@@ -55,113 +55,112 @@ static struct _mtab_entry_t *mtab_cache = NULL;
55static int useMtab = TRUE; 55static int useMtab = TRUE;
56static int umountAll = FALSE; 56static int umountAll = FALSE;
57static int doRemount = FALSE; 57static int doRemount = FALSE;
58extern const char mtab_file[]; /* Defined in utility.c */ 58extern 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
62static int 62static int do_umount(const char *name, int useMtab)
63do_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
102static int 101static int umount_all(int useMtab)
103umount_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
127extern int 126extern int umount_main(int argc, char **argv)
128umount_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 */
173void mtab_read(void) 172void 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
195char *mtab_getinfo(const char *match, const char which) 196char *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
219char *mtab_first(void **iter) 223char *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
228char *mtab_next(void **iter) 234char *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
237void mtab_free(void) 245void 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}