• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/fstools/libfstools/partname.c

  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