block: properly detect internal/external storage when tizen is run from loop-mounted... 98/273698/2
authorKarol Lewandowski <k.lewandowsk@samsung.com>
Tue, 12 Apr 2022 15:26:17 +0000 (17:26 +0200)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Thu, 14 Apr 2022 11:18:58 +0000 (11:18 +0000)
For loop-mounted devices we have to check on which device the image file resides,
and to treat this device as internal storage.

Change-Id: I0c3e1b51e948963b2fdf0fc711539d11631f0110

packaging/storaged.spec
src/block/block.c

index 2d3ad40..0b2a5c8 100644 (file)
@@ -4,7 +4,7 @@
 
 Name:       storaged
 Summary:    Storaged
-Version:    1.0.0
+Version:    1.0.1
 Release:    1
 Group:      System/Management
 License:    Apache-2.0
index 9456604..5e51bab 100644 (file)
@@ -61,6 +61,7 @@
 #include "apps.h"
 #include "storaged_common.h"
 
+#define LOOP_PATH                    "/dev/loop[0-9]*"
 #define MMC_PATH                     "*/mmcblk[0-9]*"
 #define MMC_PARTITION_PATH           "mmcblk[0-9]p[0-9]*"
 /* Emulator send devlink for sdcard as \*\/sdcard\/\* */
@@ -2468,6 +2469,61 @@ out:
        dm_task_destroy(dmt);
 }
 
+static char *loopdev_get_backing_file(int loop_id)
+{
+       char sysfile[96] = "";
+       (void)snprintf(sysfile, sizeof(sysfile), "/sys/class/block/loop%d/loop/backing_file", loop_id);
+
+       int fd = open(sysfile, O_RDONLY);
+       if (fd < 0) {
+               _W("Unable to read information about backing file for loop device %d: %m", loop_id);
+               return NULL;
+       }
+
+       char line[PATH_MAX];
+       int r = read(fd, line, sizeof line);
+       if (r < 0) {
+               _W("Unable to read from %s: %m", sysfile);
+               close(fd);
+               return NULL;
+       }
+       close(fd); // theoretically we could have one close after read (and not in if), but it would overwrite 'errno'
+
+       char *p = malloc(r + 1);
+       if (!p)
+               return NULL;
+
+       memcpy(p, line, r);
+       p[r] = '\0';
+
+       _D("Got backing file for loop device %d: %s", loop_id, p);
+
+       return p;
+}
+
+static char* trunc_one_pathlevel(char *path)
+{
+       int len = strlen(path);
+       if (len == 1) {
+               path[0] = '\0';
+               return NULL;
+       }
+
+       for (char *p = path; len > 0; len--) {
+               if (p[len] != '/')
+                       continue;
+               p[len] = '\0';
+               return path;
+       }
+
+       if (strlen(path) > 0) {
+               path[1] = '\0';
+               return path;
+       }
+
+       return NULL;
+}
+
 static int get_internal_storage_number(void)
 {
        struct libmnt_table *t = NULL;
@@ -2490,7 +2546,6 @@ static int get_internal_storage_number(void)
        for ( dev_i = 0; dev_i < DEV_INTERNAL_COUNT; dev_i++) {
                fs = mnt_table_find_target(t, dev_internal_list[dev_i], MNT_ITER_BACKWARD);
 
-
                if (!fs) {
                        mnt_free_table(t);
                        return -EPERM;
@@ -2502,6 +2557,31 @@ static int get_internal_storage_number(void)
                        return -EPERM;
                }
 
+               /* Any of filesystems we look for could be on loop device.  We have to check this case first
+                * as the loop file can be on any of the storage we check for below.
+                */
+               if (!fnmatch(LOOP_PATH, temp, 0)) {
+                       int num = atoi(temp + sizeof("/dev/loop") - 1 /* -1 for extra zero in string literal */);
+                       _D("Found %s on loop device %s (loop id %d)", dev_internal_list[dev_i], temp, num);
+
+                        char *backingfile_path = loopdev_get_backing_file(num);
+                       /* We have path to file from which image was mounted, but to find from which device it originates
+                        * we have assume it might be mounted in any of directories the path points to, ie.
+                        * with backing file in /var/images/tizen/foo.img, we have to check if /var/images/tizen, /var/images, /var, /
+                        * are the mountpoints which contain the image.
+                        */
+                       for (char *p = NULL; (p = trunc_one_pathlevel(backingfile_path)) != NULL;) {
+                               fs = mnt_table_find_target(t, p, MNT_ITER_BACKWARD);
+                               if (!fs)
+                                       continue;
+                               const char *origtemp = temp;
+                               temp = mnt_fs_get_srcpath(fs);
+                               _I("%s is found under mountpoint %s on device %s (internal storage candidate)\n", origtemp, p, temp);
+                               break;
+                       }
+                       free(backingfile_path);
+               }
+
                name = strrchr(temp, '/');
                if (!name) {
                        mnt_free_table(t);