1 // SPDX-License-Identifier: GPL-2.0-or-later
7 const char *const block_dir_name
= "/sys/class/block";
14 struct partname_volume
{
18 struct devpath devpath
;
23 struct devpath devpath
;
27 static struct driver partname_driver
;
29 static int partname_volume_identify(struct volume
*v
)
31 struct partname_volume
*p
= container_of(v
, struct partname_volume
, v
);
35 f
= fopen(p
->dev
.devpathstr
, "r");
39 ret
= block_file_identify(f
, 0);
46 static int partname_volume_init(struct volume
*v
)
48 struct partname_volume
*p
= container_of(v
, struct partname_volume
, v
);
52 snprintf(voldir
, sizeof(voldir
), "%s/%s", block_dir_name
, p
->dev
.devpath
.device
);
54 if (read_uint_from_file(voldir
, "size", &volsize
))
58 v
->size
= volsize
<< 9; /* size is returned in sectors of 512 bytes */
59 v
->blk
= p
->dev
.devpathstr
;
61 return block_volume_format(v
, 0, p
->parent_dev
.devpathstr
);
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
)
67 char line
[1024], *c
, *sptr
;
68 int fd
= open(filename
, O_RDONLY
);
72 ssize_t r
= read(fd
, line
, sizeof(line
) - 1);
80 for (c
= strtok_r(line
, " \t\n", &sptr
); c
;
81 c
= strtok_r(NULL
, " \t\n", &sptr
)) {
82 char *sep
= strchr(c
, '=');
86 ssize_t klen
= sep
- c
;
87 if (strncmp(name
, c
, klen
) || name
[klen
] != 0)
90 strncpy(out
, &sep
[1], len
);
98 static char *rootdevname(char *devpath
) {
101 l
= strlen(devpath
) - 1;
103 /* strip partition suffix from root=/dev/... string */
104 while (l
> 0 && (devpath
[l
] >= '0' && devpath
[l
] <= '9'))
107 if (devpath
[l
] != 'p')
112 return basename(devpath
);
115 static struct volume
*partname_volume_find(char *name
)
117 struct partname_volume
*p
;
118 char ueventgstr
[BUFLEN
];
119 char namebuf
[BUFLEN
];
120 char rootparam
[BUFLEN
];
121 char *rootdev
= NULL
, *devname
, *tmp
;
126 if (get_var_from_file("/proc/cmdline", "fstools_ignore_partname", rootparam
, sizeof(rootparam
))) {
127 if (!strcmp("1", rootparam
))
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
);
136 /* no 'root=' kernel cmdline parameter, find on any block device */
137 snprintf(ueventgstr
, sizeof(ueventgstr
), "%s/*/uevent", block_dir_name
);
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
)))
144 if (!strncmp(namebuf
, name
, sizeof(namebuf
))) {
153 devname
= gl
.gl_pathv
[j
];
154 tmp
= strrchr(devname
, '/');
156 devname
= strrchr(devname
, '/') + 1;
158 p
= calloc(1, sizeof(*p
));
159 memcpy(p
->dev
.devpath
.prefix
, "/dev/", sizeof(p
->dev
.devpath
.prefix
));
160 strncpy(p
->dev
.devpath
.device
, devname
, sizeof(p
->dev
.devpath
.device
) - 1);
161 p
->dev
.devpath
.device
[sizeof(p
->dev
.devpath
.device
)-1] = '\0';
163 memcpy(p
->parent_dev
.devpath
.prefix
, "/dev/", sizeof(p
->parent_dev
.devpath
.prefix
));
165 strncpy(p
->parent_dev
.devpath
.device
, rootdev
, sizeof(p
->parent_dev
.devpath
.device
) - 1);
167 strncpy(p
->parent_dev
.devpath
.device
, rootdevname(devname
), sizeof(p
->parent_dev
.devpath
.device
) - 1);
169 p
->parent_dev
.devpath
.device
[sizeof(p
->parent_dev
.devpath
.device
)-1] = '\0';
171 p
->v
.drv
= &partname_driver
;
172 p
->v
.blk
= p
->dev
.devpathstr
;
178 static struct driver partname_driver
= {
180 .find
= partname_volume_find
,
181 .init
= partname_volume_init
,
182 .identify
= partname_volume_identify
,
185 DRIVER(partname_driver
);