libfstools: skip JFFS2 padding when BLOCKSIZE was given
[project/fstools.git] / libfstools / partname.c
index 773df8cacad3089a61e019c328b020026e500570..9f2347a02acec9bd7b1af4d421c7891b864e8ee0 100644 (file)
@@ -4,8 +4,6 @@
 
 #define BUFLEN 64
 
-const char *const block_dir_name = "/sys/class/block";
-
 struct devpath {
        char prefix[5];
        char device[11];
@@ -121,6 +119,8 @@ static struct volume *partname_volume_find(char *name)
        char *rootdev = NULL, *devname, *tmp;
        int j;
        bool found = false;
+       bool allow_fallback = false;
+       bool has_root = false;
        glob_t gl;
 
        if (get_var_from_file("/proc/cmdline", "fstools_ignore_partname", rootparam, sizeof(rootparam))) {
@@ -128,12 +128,31 @@ static struct volume *partname_volume_find(char *name)
                        return NULL;
        }
 
-       if (get_var_from_file("/proc/cmdline", "root", rootparam, sizeof(rootparam))) {
+       /*
+        * Some device may contains a GPT partition named rootfs_data that may not be suitable.
+        * To save from regression with old implementation that doesn't use fstools_ignore_partname to
+        * explicitly say that that partname scan should be ignored, make explicit that scanning each
+        * partition should be done by providing fstools_partname_fallback_scan=1 and skip partname scan
+        * in every other case.
+        */
+       if (get_var_from_file("/proc/cmdline", "fstools_partname_fallback_scan", rootparam, sizeof(rootparam))) {
+               if (!strcmp("1", rootparam))
+                       allow_fallback = true;
+       }
+
+       if (get_var_from_file("/proc/cmdline", "root", rootparam, sizeof(rootparam)))
+               has_root = true;
+
+       if (has_root && rootparam[0] == '/') {
                rootdev = rootdevname(rootparam);
                /* find partition on same device as rootfs */
                snprintf(ueventgstr, sizeof(ueventgstr), "%s/%s/*/uevent", block_dir_name, rootdev);
        } else {
-               /* no 'root=' kernel cmdline parameter, find on any block device */
+               /* For compatibility, devices with root= params must explicitly opt into this fallback. */
+               if (has_root && !allow_fallback)
+                       return NULL;
+
+               /* no useful 'root=' kernel cmdline parameter, find on any block device */
                snprintf(ueventgstr, sizeof(ueventgstr), "%s/*/uevent", block_dir_name);
        }
 
@@ -152,6 +171,9 @@ static struct volume *partname_volume_find(char *name)
 
        devname = gl.gl_pathv[j];
        tmp = strrchr(devname, '/');
+       if (!tmp)
+               return NULL;
+
        *tmp = '\0';
        devname = strrchr(devname, '/') + 1;
 
@@ -177,6 +199,7 @@ static struct volume *partname_volume_find(char *name)
 
 static struct driver partname_driver = {
        .name = "partname",
+       .priority = 25,
        .find = partname_volume_find,
        .init = partname_volume_init,
        .identify = partname_volume_identify,