1 2#include <sys/mount.h> 3#include <sys/stat.h> 4#include <fcntl.h> 5#include <stdio.h> 6#include <string.h> 7#include <unistd.h> 8#include <linux/loop.h> 9#include <errno.h> 10 11#define LOOPDEV_MAXLEN 64 12#define LOOP_MAJOR 7 13 14static int is_loop(char *dev) 15{ 16 struct stat st; 17 int ret = 0; 18 19 if (stat(dev, &st) == 0) { 20 if (S_ISBLK(st.st_mode) && (major(st.st_rdev) == LOOP_MAJOR)) { 21 ret = 1; 22 } 23 } 24 25 return ret; 26} 27 28static int is_loop_mount(const char* path, char *loopdev) 29{ 30 FILE* f; 31 int count; 32 char device[256]; 33 char mount_path[256]; 34 char rest[256]; 35 int result = 0; 36 int path_length = strlen(path); 37 38 f = fopen("/proc/mounts", "r"); 39 if (!f) { 40 fprintf(stdout, "could not open /proc/mounts: %s\n", strerror(errno)); 41 return -1; 42 } 43 44 do { 45 count = fscanf(f, "%255s %255s %255s\n", device, mount_path, rest); 46 if (count == 3) { 47 if (is_loop(device) && strcmp(path, mount_path) == 0) { 48 strlcpy(loopdev, device, LOOPDEV_MAXLEN); 49 result = 1; 50 break; 51 } 52 } 53 } while (count == 3); 54 55 fclose(f); 56 return result; 57} 58 59int umount_main(int argc, char *argv[]) 60{ 61 int loop, loop_fd; 62 char loopdev[LOOPDEV_MAXLEN]; 63 64 if(argc != 2) { 65 fprintf(stderr,"umount <path>\n"); 66 return 1; 67 } 68 69 loop = is_loop_mount(argv[1], loopdev); 70 if (umount(argv[1])) { 71 fprintf(stderr, "failed: %s\n", strerror(errno)); 72 return 1; 73 } 74 75 if (loop) { 76 // free the loop device 77 loop_fd = open(loopdev, O_RDONLY); 78 if (loop_fd < 0) { 79 fprintf(stderr, "open loop device failed: %s\n", strerror(errno)); 80 return 1; 81 } 82 if (ioctl(loop_fd, LOOP_CLR_FD, 0) < 0) { 83 fprintf(stderr, "ioctl LOOP_CLR_FD failed: %s\n", strerror(errno)); 84 return 1; 85 } 86 87 close(loop_fd); 88 } 89 90 return 0; 91} 92