• 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 const char *const block_dir_name = "/sys/class/block";
  8 
  9 struct devpath {
 10         char prefix[5];
 11         char device[11];
 12 };
 13 
 14 struct partname_volume {
 15         struct volume v;
 16         union {
 17                 char devpathstr[16];
 18                 struct devpath devpath;
 19         } dev;
 20 
 21         union {
 22                 char devpathstr[16];
 23                 struct devpath devpath;
 24         } parent_dev;
 25 };
 26 
 27 static struct driver partname_driver;
 28 
 29 static int partname_volume_identify(struct volume *v)
 30 {
 31         struct partname_volume *p = container_of(v, struct partname_volume, v);
 32         int ret = FS_NONE;
 33         FILE *f;
 34 
 35         f = fopen(p->dev.devpathstr, "r");
 36         if (!f)
 37                 return ret;
 38 
 39         ret = block_file_identify(f, 0);
 40 
 41         fclose(f);
 42 
 43         return ret;
 44 }
 45 
 46 static int partname_volume_init(struct volume *v)
 47 {
 48         struct partname_volume *p = container_of(v, struct partname_volume, v);
 49         char voldir[BUFLEN];
 50         unsigned int volsize;
 51 
 52         snprintf(voldir, sizeof(voldir), "%s/%s", block_dir_name, p->dev.devpath.device);
 53 
 54         if (read_uint_from_file(voldir, "size", &volsize))
 55                 return -1;
 56 
 57         v->type = BLOCKDEV;
 58         v->size = volsize << 9; /* size is returned in sectors of 512 bytes */
 59         v->blk = p->dev.devpathstr;
 60 
 61         return block_volume_format(v, 0, p->parent_dev.devpathstr);
 62 }
 63 
 64 /* adapted from procd/utils.c -> should go to libubox */
 65 static char* get_var_from_file(const char* filename, const char* name, char* out, int len)
 66 {
 67         char line[1024], *c, *sptr;
 68         int fd = open(filename, O_RDONLY);
 69         if (fd == -1)
 70                 return NULL;
 71 
 72         ssize_t r = read(fd, line, sizeof(line) - 1);
 73         close(fd);
 74 
 75         if (r <= 0)
 76                 return NULL;
 77 
 78         line[r] = 0;
 79 
 80         for (c = strtok_r(line, " \t\n", &sptr); c;
 81                         c = strtok_r(NULL, " \t\n", &sptr)) {
 82                 char *sep = strchr(c, '=');
 83                 if (sep == NULL)
 84                         continue;
 85 
 86                 ssize_t klen = sep - c;
 87                 if (strncmp(name, c, klen) || name[klen] != 0)
 88                         continue;
 89 
 90                 strncpy(out, &sep[1], len);
 91                 out[len-1] = '\0';
 92                 return out;
 93         }
 94 
 95         return NULL;
 96 }
 97 
 98 static char *rootdevname(char *devpath) {
 99         int l;
100 
101         l = strlen(devpath) - 1;
102 
103         /* strip partition suffix from root=/dev/... string */
104         while (l > 0 && (devpath[l] >= '' && devpath[l] <= '9'))
105                 --l;
106 
107         if (devpath[l] != 'p')
108                 ++l;
109 
110         devpath[l] = '\0';
111 
112         return basename(devpath);
113 }
114 
115 static struct volume *partname_volume_find(char *name)
116 {
117         struct partname_volume *p;
118         char ueventgstr[BUFLEN];
119         char namebuf[BUFLEN];
120         char rootparam[BUFLEN];
121         char *rootdev = NULL, *devname, *tmp;
122         int j;
123         bool found = false;
124         glob_t gl;
125 
126         if (get_var_from_file("/proc/cmdline", "fstools_ignore_partname", rootparam, sizeof(rootparam))) {
127                 if (!strcmp("1", rootparam))
128                         return NULL;
129         }
130 
131         if (get_var_from_file("/proc/cmdline", "root", rootparam, sizeof(rootparam))) {
132                 rootdev = rootdevname(rootparam);
133                 /* find partition on same device as rootfs */
134                 snprintf(ueventgstr, sizeof(ueventgstr), "%s/%s/*/uevent", block_dir_name, rootdev);
135         } else {
136                 /* no 'root=' kernel cmdline parameter, find on any block device */
137                 snprintf(ueventgstr, sizeof(ueventgstr), "%s/*/uevent", block_dir_name);
138         }
139 
140         if (!glob(ueventgstr, GLOB_NOESCAPE, NULL, &gl))
141                 for (j = 0; j < gl.gl_pathc; j++) {
142                         if (!get_var_from_file(gl.gl_pathv[j], "PARTNAME", namebuf, sizeof(namebuf)))
143                                 continue;
144                         if (!strncmp(namebuf, name, sizeof(namebuf))) {
145                                 found = 1;
146                                 break;
147                         }
148                 }
149 
150         if (!found)
151                 return NULL;
152 
153         devname = gl.gl_pathv[j];
154         tmp = strrchr(devname, '/');
155         if (!tmp)
156                 return NULL;
157 
158         *tmp = '\0';
159         devname = strrchr(devname, '/') + 1;
160 
161         p = calloc(1, sizeof(*p));
162         memcpy(p->dev.devpath.prefix, "/dev/", sizeof(p->dev.devpath.prefix));
163         strncpy(p->dev.devpath.device, devname, sizeof(p->dev.devpath.device) - 1);
164         p->dev.devpath.device[sizeof(p->dev.devpath.device)-1] = '\0';
165 
166         memcpy(p->parent_dev.devpath.prefix, "/dev/", sizeof(p->parent_dev.devpath.prefix));
167         if (rootdev)
168                 strncpy(p->parent_dev.devpath.device, rootdev, sizeof(p->parent_dev.devpath.device) - 1);
169         else
170                 strncpy(p->parent_dev.devpath.device, rootdevname(devname), sizeof(p->parent_dev.devpath.device) - 1);
171 
172         p->parent_dev.devpath.device[sizeof(p->parent_dev.devpath.device)-1] = '\0';
173 
174         p->v.drv = &partname_driver;
175         p->v.blk = p->dev.devpathstr;
176         p->v.name = name;
177 
178         return &p->v;
179 }
180 
181 static struct driver partname_driver = {
182         .name = "partname",
183         .find = partname_volume_find,
184         .init = partname_volume_init,
185         .identify = partname_volume_identify,
186 };
187 
188 DRIVER(partname_driver);
189 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt