diff options
Diffstat (limited to 'package/toolbox/src/src/umount.c')
-rw-r--r-- | package/toolbox/src/src/umount.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/package/toolbox/src/src/umount.c b/package/toolbox/src/src/umount.c new file mode 100644 index 000000000..aee3bdd39 --- /dev/null +++ b/package/toolbox/src/src/umount.c @@ -0,0 +1,91 @@ + +#include <sys/mount.h> +#include <sys/stat.h> +#include <sys/sysmacros.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <linux/loop.h> +#include <errno.h> + +#define LOOPDEV_MAXLEN 64 +#define LOOP_MAJOR 7 + +static int is_loop(char *dev) +{ + struct stat st; + int ret = 0; + + if (stat(dev, &st) == 0) { + if (S_ISBLK(st.st_mode) && (major(st.st_rdev) == LOOP_MAJOR)) { + ret = 1; + } + } + + return ret; +} + +static int is_loop_mount(const char* path, char *loopdev) +{ + FILE* f; + int count; + char device[256]; + char mount_path[256]; + char rest[256]; + int result = 0; + + f = fopen("/proc/mounts", "r"); + if (!f) { + fprintf(stdout, "could not open /proc/mounts: %s\n", strerror(errno)); + return -1; + } + + do { + count = fscanf(f, "%255s %255s %255s\n", device, mount_path, rest); + if (count == 3) { + if (is_loop(device) && strcmp(path, mount_path) == 0) { + strlcpy(loopdev, device, LOOPDEV_MAXLEN); + result = 1; + break; + } + } + } while (count == 3); + + fclose(f); + return result; +} + +int main(int argc, char *argv[]) +{ + int loop, loop_fd; + char loopdev[LOOPDEV_MAXLEN]; + + if(argc != 2) { + fprintf(stderr,"umount <path>\n"); + return 1; + } + + loop = is_loop_mount(argv[1], loopdev); + if (umount(argv[1])) { + fprintf(stderr, "failed: %s\n", strerror(errno)); + return 1; + } + + if (loop) { + // free the loop device + loop_fd = open(loopdev, O_RDONLY); + if (loop_fd < 0) { + fprintf(stderr, "open loop device failed: %s\n", strerror(errno)); + return 1; + } + if (ioctl(loop_fd, LOOP_CLR_FD, 0) < 0) { + fprintf(stderr, "ioctl LOOP_CLR_FD failed: %s\n", strerror(errno)); + return 1; + } + + close(loop_fd); + } + + return 0; +} |