Exemplo n.º 1
0
/*!
 * \brief Unmount filesystem
 *
 * This function takes the same arguments as umount(2), but returns true on
 * success and false on failure.
 *
 * This function will /proc/mounts for the mountpoint (using an exact string
 * compare). If the source path of the mountpoint is a block device and the
 * block device is a loop device, then it will be disassociated from the
 * previously attached file. Note that the return value of
 * loopdev_remove_device() is ignored and this function will always return true
 * if umount(2) is successful.
 *
 * \param target See man umount(2)
 *
 * \return True if umount(2) is successful. False if umount(2) is unsuccessful.
 */
bool umount(const char *target)
{
    struct mntent ent;
    std::string source;

    autoclose::file fp(setmntent("/proc/mounts", "r"), endmntent);
    if (fp) {
        char buf[1024];
        while (getmntent_r(fp.get(), &ent, buf, sizeof(buf))) {
            if (strcmp(ent.mnt_dir, target) == 0) {
                source = ent.mnt_fsname;
            }
        }
    } else {
        LOGW("Failed to read /proc/mounts: %s", strerror(errno));
    }

    int ret = ::umount(target);

    if (!source.empty()) {
        struct stat sb;

        if (stat(source.c_str(), &sb) == 0
                && S_ISBLK(sb.st_mode) && major(sb.st_rdev) == 7) {
            // If the source path is a loop block device, then disassociate it
            // from the image
            loopdev_remove_device(source);
        }
    }

    return ret == 0;
}
Exemplo n.º 2
0
/*!
 * \brief Unmount filesystem
 *
 * This function takes the same arguments as umount(2), but returns true on
 * success and false on failure.
 *
 * This function will /proc/mounts for the mountpoint (using an exact string
 * compare). If the source path of the mountpoint is a block device and the
 * block device is a loop device, then it will be disassociated from the
 * previously attached file. Note that the return value of
 * loopdev_remove_device() is ignored and this function will always return true
 * if umount(2) is successful.
 *
 * \param target See man umount(2)
 *
 * \return True if umount(2) is successful. False if umount(2) is unsuccessful.
 */
bool umount(const char *target)
{
    std::string source;
    std::string mnt_dir;

    autoclose::file fp(std::fopen(PROC_MOUNTS, "r"), std::fclose);
    if (fp) {
        for (MountEntry entry; get_mount_entry(fp.get(), entry);) {
            if (entry.dir == target) {
                source = entry.fsname;
            }
        }
    } else {
        LOGW(PROC_MOUNTS ": Failed to read file: %s", strerror(errno));
    }

    int ret = ::umount(target);

    int saved_errno = errno;

    if (!source.empty()) {
        struct stat sb;

        if (stat(source.c_str(), &sb) == 0
                && S_ISBLK(sb.st_mode) && major(sb.st_rdev) == 7) {
            // If the source path is a loop block device, then disassociate it
            // from the image
            LOGD("Clearing loop device %s", source.c_str());
            if (!loopdev_remove_device(source)) {
                LOGW("Failed to clear loop device: %s", strerror(errno));
            }
        }
    }

    errno = saved_errno;

    return ret == 0;
}