1 // SPDX-License-Identifier: GPL-2.0-or-later 2 3 #include "common.h" 4 5 #define BUFLEN 64 6 7 struct devpath { 8 char prefix[5]; 9 char device[11]; 10 }; 11 12 struct partname_volume { 13 struct volume v; 14 union { 15 char devpathstr[16]; 16 struct devpath devpath; 17 } dev; 18 19 union { 20 char devpathstr[16]; 21 struct devpath devpath; 22 } parent_dev; 23 }; 24 25 static struct driver partname_driver; 26 27 static int partname_volume_identify(struct volume *v) 28 { 29 struct partname_volume *p = container_of(v, struct partname_volume, v); 30 int ret = FS_NONE; 31 FILE *f; 32 33 f = fopen(p->dev.devpathstr, "r"); 34 if (!f) 35 return ret; 36 37 ret = block_file_identify(f, 0); 38 39 fclose(f); 40 41 return ret; 42 } 43 44 static int partname_volume_init(struct volume *v) 45 { 46 struct partname_volume *p = container_of(v, struct partname_volume, v); 47 char voldir[BUFLEN]; 48 unsigned int volsize; 49 50 snprintf(voldir, sizeof(voldir), "%s/%s", block_dir_name, p->dev.devpath.device); 51 52 if (read_uint_from_file(voldir, "size", &volsize)) 53 return -1; 54 55 v->type = BLOCKDEV; 56 v->size = volsize << 9; /* size is returned in sectors of 512 bytes */ 57 v->blk = p->dev.devpathstr; 58 59 return block_volume_format(v, 0, p->parent_dev.devpathstr); 60 } 61 62 static char *rootdevname(char *devpath) { 63 int l; 64 65 l = strlen(devpath) - 1; 66 67 /* strip partition suffix from root=/dev/... string */ 68 while (l > 0 && (devpath[l] >= '' && devpath[l] <= '9')) 69 --l; 70 71 if (devpath[l] != 'p') 72 ++l; 73 74 devpath[l] = '\0'; 75 76 return basename(devpath); 77 } 78 79 static struct volume *partname_volume_find(char *name) 80 { 81 struct partname_volume *p; 82 char ueventgstr[BUFLEN]; 83 char namebuf[BUFLEN]; 84 char rootparam[BUFLEN]; 85 char *rootdev = NULL, *devname, *tmp; 86 int j; 87 bool found = false; 88 bool allow_fallback = false; 89 bool has_root = false; 90 glob_t gl; 91 92 if (get_var_from_file("/proc/cmdline", "fstools_ignore_partname", rootparam, sizeof(rootparam))) { 93 if (!strcmp("1", rootparam)) 94 return NULL; 95 } 96 97 /* 98 * Some device may contains a GPT partition named rootfs_data that may not be suitable. 99 * To save from regression with old implementation that doesn't use fstools_ignore_partname to 100 * explicitly say that that partname scan should be ignored, make explicit that scanning each 101 * partition should be done by providing fstools_partname_fallback_scan=1 and skip partname scan 102 * in every other case. 103 */ 104 if (get_var_from_file("/proc/cmdline", "fstools_partname_fallback_scan", rootparam, sizeof(rootparam))) { 105 if (!strcmp("1", rootparam)) 106 allow_fallback = true; 107 } 108 109 if (get_var_from_file("/proc/cmdline", "root", rootparam, sizeof(rootparam))) 110 has_root = true; 111 112 if (has_root && rootparam[0] == '/') { 113 rootdev = rootdevname(rootparam); 114 /* find partition on same device as rootfs */ 115 snprintf(ueventgstr, sizeof(ueventgstr), "%s/%s/*/uevent", block_dir_name, rootdev); 116 } else { 117 /* For compatibility, devices with root= params must explicitly opt into this fallback. */ 118 if (has_root && !allow_fallback) 119 return NULL; 120 121 /* no useful 'root=' kernel cmdline parameter, find on any block device */ 122 snprintf(ueventgstr, sizeof(ueventgstr), "%s/*/uevent", block_dir_name); 123 } 124 125 if (!glob(ueventgstr, GLOB_NOESCAPE, NULL, &gl)) 126 for (j = 0; j < gl.gl_pathc; j++) { 127 if (!get_var_from_file(gl.gl_pathv[j], "PARTNAME", namebuf, sizeof(namebuf))) 128 continue; 129 if (!strncmp(namebuf, name, sizeof(namebuf))) { 130 found = 1; 131 break; 132 } 133 } 134 135 if (!found) 136 return NULL; 137 138 devname = gl.gl_pathv[j]; 139 tmp = strrchr(devname, '/'); 140 if (!tmp) 141 return NULL; 142 143 *tmp = '\0'; 144 devname = strrchr(devname, '/') + 1; 145 146 p = calloc(1, sizeof(*p)); 147 memcpy(p->dev.devpath.prefix, "/dev/", sizeof(p->dev.devpath.prefix)); 148 strncpy(p->dev.devpath.device, devname, sizeof(p->dev.devpath.device) - 1); 149 p->dev.devpath.device[sizeof(p->dev.devpath.device)-1] = '\0'; 150 151 memcpy(p->parent_dev.devpath.prefix, "/dev/", sizeof(p->parent_dev.devpath.prefix)); 152 if (rootdev) 153 strncpy(p->parent_dev.devpath.device, rootdev, sizeof(p->parent_dev.devpath.device) - 1); 154 else 155 strncpy(p->parent_dev.devpath.device, rootdevname(devname), sizeof(p->parent_dev.devpath.device) - 1); 156 157 p->parent_dev.devpath.device[sizeof(p->parent_dev.devpath.device)-1] = '\0'; 158 159 p->v.drv = &partname_driver; 160 p->v.blk = p->dev.devpathstr; 161 p->v.name = name; 162 163 return &p->v; 164 } 165 166 static struct driver partname_driver = { 167 .name = "partname", 168 .priority = 25, 169 .find = partname_volume_find, 170 .init = partname_volume_init, 171 .identify = partname_volume_identify, 172 }; 173 174 DRIVER(partname_driver); 175
This page was automatically generated by LXR 0.3.1. • OpenWrt