|
|
|
@ -37,11 +37,24 @@ static const char umount_usage[] =
|
|
|
|
|
#else
|
|
|
|
|
"\n"
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef BB_FEATURE_REMOUNT
|
|
|
|
|
"\t-r:\tTry to remount devices as read-only if mount is busy\n"
|
|
|
|
|
#endif
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
struct _mtab_entry_t {
|
|
|
|
|
char *device;
|
|
|
|
|
char *mountpt;
|
|
|
|
|
struct _mtab_entry_t *next;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct _mtab_entry_t *mtab_cache = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int useMtab = TRUE;
|
|
|
|
|
static int umountAll = FALSE;
|
|
|
|
|
static int doRemount = FALSE;
|
|
|
|
|
extern const char mtab_file[]; /* Defined in utility.c */
|
|
|
|
|
|
|
|
|
|
#define MIN(x,y) (x > y ? x : y)
|
|
|
|
@ -50,21 +63,10 @@ static int
|
|
|
|
|
do_umount(const char* name, int useMtab)
|
|
|
|
|
{
|
|
|
|
|
int status;
|
|
|
|
|
struct mntent *m;
|
|
|
|
|
FILE *mountTable;
|
|
|
|
|
const char *blockDevice = NULL;
|
|
|
|
|
char *blockDevice = mtab_getinfo(name, MTAB_GETDEVICE);
|
|
|
|
|
|
|
|
|
|
if ((mountTable = setmntent (mtab_file, "r"))) {
|
|
|
|
|
while ((m = getmntent (mountTable)) != 0) {
|
|
|
|
|
if (strncmp(m->mnt_dir, name,
|
|
|
|
|
MIN(strlen(m->mnt_dir),strlen(name))) == 0)
|
|
|
|
|
blockDevice = m->mnt_fsname;
|
|
|
|
|
else if (strcmp(m->mnt_fsname, name) == 0) {
|
|
|
|
|
blockDevice = name;
|
|
|
|
|
name = m->mnt_dir;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (blockDevice && strcmp(blockDevice, name) == 0)
|
|
|
|
|
name = mtab_getinfo(blockDevice, MTAB_GETMOUNTPT);
|
|
|
|
|
|
|
|
|
|
status = umount(name);
|
|
|
|
|
|
|
|
|
@ -73,57 +75,53 @@ do_umount(const char* name, int useMtab)
|
|
|
|
|
/* this was a loop device, delete it */
|
|
|
|
|
del_loop(blockDevice);
|
|
|
|
|
#endif
|
|
|
|
|
#if defined BB_MTAB
|
|
|
|
|
#if defined BB_FEATURE_REMOUNT
|
|
|
|
|
if ( status != 0 && doRemount == TRUE && errno == EBUSY ) {
|
|
|
|
|
status = mount(blockDevice, name, NULL,
|
|
|
|
|
MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
|
|
|
|
|
if (status == 0) {
|
|
|
|
|
fprintf(stderr, "umount: %s busy - remounted read-only\n",
|
|
|
|
|
blockDevice);
|
|
|
|
|
/* TODO: update mtab if BB_MTAB is defined */
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(stderr, "umount: Cannot remount %s read-only\n",
|
|
|
|
|
blockDevice);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
if ( status == 0 ) {
|
|
|
|
|
#if defined BB_MTAB
|
|
|
|
|
if ( useMtab==TRUE )
|
|
|
|
|
erase_mtab(name);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
#endif
|
|
|
|
|
return(status);
|
|
|
|
|
return( TRUE);
|
|
|
|
|
}
|
|
|
|
|
return(FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
umount_all(int useMtab)
|
|
|
|
|
{
|
|
|
|
|
int status;
|
|
|
|
|
struct mntent *m;
|
|
|
|
|
FILE *mountTable;
|
|
|
|
|
int status = TRUE;
|
|
|
|
|
char *mountpt;
|
|
|
|
|
void *iter;
|
|
|
|
|
|
|
|
|
|
if ((mountTable = setmntent (mtab_file, "r"))) {
|
|
|
|
|
while ((m = getmntent (mountTable)) != 0) {
|
|
|
|
|
char *blockDevice = m->mnt_fsname;
|
|
|
|
|
#if ! defined BB_MTAB
|
|
|
|
|
if (strcmp (blockDevice, "/dev/root") == 0) {
|
|
|
|
|
struct fstab* fstabItem;
|
|
|
|
|
fstabItem = getfsfile ("/");
|
|
|
|
|
if (fstabItem != NULL) {
|
|
|
|
|
blockDevice = fstabItem->fs_spec;
|
|
|
|
|
}
|
|
|
|
|
for (mountpt = mtab_first(&iter); mountpt; mountpt = mtab_next(&iter)) {
|
|
|
|
|
status=do_umount (mountpt, useMtab);
|
|
|
|
|
if (status != 0) {
|
|
|
|
|
/* Don't bother retrying the umount on busy devices */
|
|
|
|
|
if (errno == EBUSY) {
|
|
|
|
|
perror(mountpt);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
/* Don't umount /proc when doing umount -a */
|
|
|
|
|
if (strcmp (blockDevice, "proc") == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
status=do_umount (m->mnt_dir, useMtab);
|
|
|
|
|
if (status!=0) {
|
|
|
|
|
/* Don't bother retrying the umount on busy devices */
|
|
|
|
|
if (errno==EBUSY) {
|
|
|
|
|
perror(m->mnt_dir);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
status=do_umount (blockDevice, useMtab);
|
|
|
|
|
if (status!=0) {
|
|
|
|
|
printf ("Couldn't umount %s on %s (type %s): %s\n",
|
|
|
|
|
blockDevice, m->mnt_dir, m->mnt_type, strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
status = do_umount (mountpt, useMtab);
|
|
|
|
|
if (status != 0) {
|
|
|
|
|
printf ("Couldn't umount %s on %s: %s\n",
|
|
|
|
|
mountpt, mtab_getinfo(mountpt, MTAB_GETDEVICE), strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
endmntent (mountTable);
|
|
|
|
|
}
|
|
|
|
|
return( TRUE);
|
|
|
|
|
return (status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern int
|
|
|
|
@ -143,14 +141,19 @@ umount_main(int argc, char** argv)
|
|
|
|
|
case 'n':
|
|
|
|
|
useMtab = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef BB_FEATURE_REMOUNT
|
|
|
|
|
case 'r':
|
|
|
|
|
doRemount = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
default:
|
|
|
|
|
usage( umount_usage);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(umountAll==TRUE) {
|
|
|
|
|
mtab_read();
|
|
|
|
|
if (umountAll==TRUE) {
|
|
|
|
|
exit(umount_all(useMtab));
|
|
|
|
|
}
|
|
|
|
|
if ( do_umount(*argv,useMtab) == 0 )
|
|
|
|
@ -161,3 +164,87 @@ umount_main(int argc, char** argv)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* These functions are here because the getmntent functions do not appear
|
|
|
|
|
* to be re-entrant, which leads to all sorts of problems when we try to
|
|
|
|
|
* use them recursively - randolph
|
|
|
|
|
*/
|
|
|
|
|
void mtab_read(void)
|
|
|
|
|
{
|
|
|
|
|
struct _mtab_entry_t *entry = NULL;
|
|
|
|
|
struct mntent *e;
|
|
|
|
|
FILE *fp;
|
|
|
|
|
|
|
|
|
|
if (mtab_cache != NULL) return;
|
|
|
|
|
|
|
|
|
|
if ((fp = setmntent(mtab_file, "r")) == NULL) {
|
|
|
|
|
fprintf(stderr, "Cannot open %s\n", mtab_file);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
while ((e = getmntent(fp))) {
|
|
|
|
|
entry = malloc(sizeof(struct _mtab_entry_t));
|
|
|
|
|
entry->device = strdup(e->mnt_fsname);
|
|
|
|
|
entry->mountpt = strdup(e->mnt_dir);
|
|
|
|
|
entry->next = mtab_cache;
|
|
|
|
|
mtab_cache = entry;
|
|
|
|
|
}
|
|
|
|
|
endmntent(fp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *mtab_getinfo(const char *match, const char which)
|
|
|
|
|
{
|
|
|
|
|
struct _mtab_entry_t *cur = mtab_cache;
|
|
|
|
|
while (cur) {
|
|
|
|
|
if (strcmp(cur->mountpt, match) == 0 ||
|
|
|
|
|
strcmp(cur->device, match) == 0) {
|
|
|
|
|
if (which == MTAB_GETMOUNTPT) {
|
|
|
|
|
return cur->mountpt;
|
|
|
|
|
} else {
|
|
|
|
|
#if !defined BB_MTAB
|
|
|
|
|
if (strcmp(cur->device, "/dev/root") == 0) {
|
|
|
|
|
struct fstab* fstabItem;
|
|
|
|
|
fstabItem = getfsfile ("/");
|
|
|
|
|
if (fstabItem != NULL) return fstabItem->fs_spec;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return cur->device;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
cur = cur->next;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *mtab_first(void **iter)
|
|
|
|
|
{
|
|
|
|
|
struct _mtab_entry_t *mtab_iter;
|
|
|
|
|
if (!iter) return NULL;
|
|
|
|
|
mtab_iter = mtab_cache;
|
|
|
|
|
*iter = (void *)mtab_iter;
|
|
|
|
|
return mtab_next(iter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *mtab_next(void **iter)
|
|
|
|
|
{
|
|
|
|
|
char *mp;
|
|
|
|
|
if (iter == NULL || *iter == NULL) return NULL;
|
|
|
|
|
mp = ((struct _mtab_entry_t *)(*iter))->mountpt;
|
|
|
|
|
*iter = (void *)((struct _mtab_entry_t *)(*iter))->next;
|
|
|
|
|
return mp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void mtab_free(void)
|
|
|
|
|
{
|
|
|
|
|
struct _mtab_entry_t *this, *next;
|
|
|
|
|
|
|
|
|
|
this = mtab_cache;
|
|
|
|
|
while (this) {
|
|
|
|
|
next = this->next;
|
|
|
|
|
if (this->device) free(this->device);
|
|
|
|
|
if (this->mountpt) free(this->mountpt);
|
|
|
|
|
free(this);
|
|
|
|
|
this = next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|