/*! * \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; }
/*! * \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; }