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