#include <sys/mount.h> #include <sys/stat.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; int path_length = strlen(path); 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 umount_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; }