1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/mount.h>
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/stat.h>
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h>
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/loop.h>
9baf6b6bdebd6e91c401f64e8013fed49697ed2ccJeff Brown#include <errno.h>
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
11940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall#define LOOPDEV_MAXLEN 64
12940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall#define LOOP_MAJOR 7
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
14940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrallstatic int is_loop(char *dev)
15940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall{
16940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall    struct stat st;
17940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall    int ret = 0;
18940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall
19940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall    if (stat(dev, &st) == 0) {
20940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall        if (S_ISBLK(st.st_mode) && (major(st.st_rdev) == LOOP_MAJOR)) {
21940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall            ret = 1;
22940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall        }
23940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall    }
24940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall
25940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall    return ret;
26940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall}
27940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall
28940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrallstatic int is_loop_mount(const char* path, char *loopdev)
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    FILE* f;
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int count;
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char device[256];
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char mount_path[256];
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char rest[256];
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int result = 0;
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int path_length = strlen(path);
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    f = fopen("/proc/mounts", "r");
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!f) {
40baf6b6bdebd6e91c401f64e8013fed49697ed2ccJeff Brown        fprintf(stdout, "could not open /proc/mounts: %s\n", strerror(errno));
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do {
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        count = fscanf(f, "%255s %255s %255s\n", device, mount_path, rest);
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (count == 3) {
47940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall            if (is_loop(device) && strcmp(path, mount_path) == 0) {
48940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall                strlcpy(loopdev, device, LOOPDEV_MAXLEN);
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                result = 1;
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } while (count == 3);
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fclose(f);
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return result;
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint umount_main(int argc, char *argv[])
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int loop, loop_fd;
62940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall    char loopdev[LOOPDEV_MAXLEN];
63940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(argc != 2) {
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"umount <path>\n");
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 1;
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
69940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall    loop = is_loop_mount(argv[1], loopdev);
70baf6b6bdebd6e91c401f64e8013fed49697ed2ccJeff Brown    if (umount(argv[1])) {
71baf6b6bdebd6e91c401f64e8013fed49697ed2ccJeff Brown        fprintf(stderr, "failed: %s\n", strerror(errno));
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 1;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (loop) {
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // free the loop device
77940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall        loop_fd = open(loopdev, O_RDONLY);
78940c81078e7291096b22f05f6b953658f1e1d730Ken Sumrall        if (loop_fd < 0) {
79baf6b6bdebd6e91c401f64e8013fed49697ed2ccJeff Brown            fprintf(stderr, "open loop device failed: %s\n", strerror(errno));
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 1;
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (ioctl(loop_fd, LOOP_CLR_FD, 0) < 0) {
83baf6b6bdebd6e91c401f64e8013fed49697ed2ccJeff Brown            fprintf(stderr, "ioctl LOOP_CLR_FD failed: %s\n", strerror(errno));
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 1;
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        close(loop_fd);
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
92