1 // SPDX-License-Identifier: GPL-2.0-or-later
7 const char *const block_dir_name
= "/sys/class/block";
9 struct partname_volume
{
12 char parent_devname
[16];
15 static struct driver partname_driver
;
17 static int partname_volume_identify(struct volume
*v
)
22 f
= fopen(v
->blk
, "r");
26 ret
= block_file_identify(f
, 0);
33 static int partname_volume_init(struct volume
*v
)
35 struct partname_volume
*p
= container_of(v
, struct partname_volume
, v
);
41 snprintf(voldir
, sizeof(voldir
), "%s/%s", block_dir_name
, p
->devname
);
43 if (read_uint_from_file(voldir
, "size", &volsize
))
46 snprintf(voldev
, sizeof(voldev
), "/dev/%s", p
->devname
);
47 snprintf(pdev
, sizeof(pdev
), "/dev/%s", p
->parent_devname
);
50 v
->size
= volsize
<< 9; /* size is returned in sectors of 512 bytes */
51 v
->blk
= strdup(voldev
);
53 return block_volume_format(v
, 0, pdev
);
56 /* from procd/utils.c -> should go to libubox */
57 static char* get_cmdline_val(const char* name
, char* out
, int len
)
59 char line
[1024], *c
, *sptr
;
60 int fd
= open("/proc/cmdline", O_RDONLY
);
61 ssize_t r
= read(fd
, line
, sizeof(line
) - 1);
69 for (c
= strtok_r(line
, " \t\n", &sptr
); c
;
70 c
= strtok_r(NULL
, " \t\n", &sptr
)) {
71 char *sep
= strchr(c
, '=');
75 ssize_t klen
= sep
- c
;
76 if (strncmp(name
, c
, klen
) || name
[klen
] != 0)
79 strncpy(out
, &sep
[1], len
);
87 static char *rootdevname(char *devpath
) {
90 l
= strlen(devpath
) - 1;
92 /* strip partition suffix from root=/dev/... string */
93 while (l
> 0 && (devpath
[l
] >= '0' && devpath
[l
] <= '9'))
96 if (devpath
[l
] != 'p')
101 return basename(devpath
);
104 static struct volume
*partname_volume_find(char *name
)
106 struct partname_volume
*p
;
107 char volnamegstr
[BUFLEN
];
108 char namebuf
[BUFLEN
];
109 char rootparam
[BUFLEN
];
110 char *rootdev
= NULL
, *devname
, *tmp
;
115 if (get_cmdline_val("root", rootparam
, sizeof(rootparam
))) {
116 rootdev
= rootdevname(rootparam
);
117 /* find partition on same device as rootfs */
118 snprintf(volnamegstr
, sizeof(volnamegstr
), "%s/%s/*/name", block_dir_name
, rootdev
);
120 /* no 'root=' kernel cmdline parameter, find on any block device */
121 snprintf(volnamegstr
, sizeof(volnamegstr
), "%s/*/name", block_dir_name
);
124 if (!glob(volnamegstr
, GLOB_NOESCAPE
, NULL
, &gl
))
125 for (j
= 0; j
< gl
.gl_pathc
; j
++) {
126 if (!read_string_from_file("", gl
.gl_pathv
[j
], namebuf
, sizeof(namebuf
)))
128 if (!strncmp(namebuf
, name
, sizeof(namebuf
))) {
137 devname
= gl
.gl_pathv
[j
];
138 tmp
= strrchr(devname
, '/');
140 devname
= strrchr(devname
, '/') + 1;
142 p
= calloc(1, sizeof(*p
));
143 strncpy(p
->devname
, devname
, sizeof(p
->devname
));
145 strncpy(p
->parent_devname
, rootdev
, sizeof(p
->devname
));
147 strncpy(p
->parent_devname
, rootdevname(devname
), sizeof(p
->devname
));
149 p
->devname
[sizeof(p
->devname
)-1] = '\0';
150 p
->v
.drv
= &partname_driver
;
151 p
->v
.name
= strdup(namebuf
);
156 static struct driver partname_driver
= {
158 .find
= partname_volume_find
,
159 .init
= partname_volume_init
,
160 .identify
= partname_volume_identify
,
163 DRIVER(partname_driver
);