return -1;
}
+/* Find loop device associated with given @filename. Used for unmounting loop
+ * device specified by associated backing file.
+ *
+ * returns: 1 no such device/error
+ * 2 more than one loop device associated with @filename
+ * 0 exactly one loop device associated with @filename
+ * (@loopdev points to string containing full device name)
+ */
+int
+find_loopdev_by_backing_file(const char *filename, char **loopdev)
+{
+ struct looplist ll;
+ struct stat filestat;
+ int fd;
+ int devs_n = 0; /* number of loop devices found */
+ char* devname = NULL;
+
+ if (stat(filename, &filestat) == -1) {
+ perror(filename);
+ return 1;
+ }
+
+ if (looplist_open(&ll, LLFLG_USEDONLY) == -1) {
+ error(_("%s: /dev directory does not exist."), progname);
+ return 1;
+ }
+
+ while((devs_n < 2) && (fd = looplist_next(&ll)) != -1) {
+ if (is_associated(fd, &filestat, 0, 0) == 1) {
+ if (!devname)
+ devname = xstrdup(ll.name);
+ devs_n++;
+ }
+ close(fd);
+ }
+ looplist_close(&ll);
+
+ if (devs_n == 1) {
+ *loopdev = devname;
+ return 0; /* exactly one loopdev */
+ }
+ free(devname);
+ return devs_n ? 2 : 1; /* more loopdevs or error */
+}
+
#ifdef MAIN
static int
return 0;
}
+
#endif /* MAIN */
/* check if the loopfile is already associated with the same given
return 0;
}
+int
+find_loopdev_by_backing_file(const char *filename, char **loopdev)
+{
+ mutter();
+ return 1;
+}
+
#endif /* !LOOP_SET_FD */
#ifdef MAIN
extern int loopfile_used_with(char *devname, const char *filename, unsigned long long offset);
extern char *loopfile_used (const char *filename, unsigned long long offset);
extern char *loopdev_get_loopfile(const char *device);
+extern int find_loopdev_by_backing_file(const char *filename, char **loopdev);
#define SETLOOP_RDONLY (1<<0) /* Open loop read-only */
const char *file, *options;
int fstab_has_user, fstab_has_users, fstab_has_owner, fstab_has_group;
int ok;
+ struct stat statbuf;
if (!*arg) { /* "" would be expanded to `pwd` */
die(2, _("Cannot unmount \"\"\n"));
}
file = canonicalize(arg); /* mtab paths are canonicalized */
+
+ /* if file is a regular file, check if it is associated
+ * with some loop device
+ */
+ if (!stat(file, &statbuf) && S_ISREG(statbuf.st_mode)) {
+ char *loopdev = NULL;
+ switch (find_loopdev_by_backing_file(file, &loopdev)) {
+ case 0:
+ if (verbose)
+ printf(_("%s is associated with %s, trying to unmount it\n"),
+ arg, loopdev);
+ file = loopdev;
+ break;
+ case 2:
+ if (verbose)
+ printf(_("%s is associated with more than one loop device: not unmounting\n"),
+ arg);
+ break;
+ }
+ }
+
if (verbose > 1)
printf(_("Trying to unmount %s\n"), file);