4560125879c6b29b982c4af7d3937d3be1e305f6
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 /* from procd/utils.c -> should go to libubox */
65 static char* get_cmdline_val(const char* name
, char* out
, int len
)
67 char line
[1024], *c
, *sptr
;
68 int fd
= open("/proc/cmdline", O_RDONLY
);
69 ssize_t r
= read(fd
, line
, sizeof(line
) - 1);
77 for (c
= strtok_r(line
, " \t\n", &sptr
); c
;
78 c
= strtok_r(NULL
, " \t\n", &sptr
)) {
79 char *sep
= strchr(c
, '=');
83 ssize_t klen
= sep
- c
;
84 if (strncmp(name
, c
, klen
) || name
[klen
] != 0)
87 strncpy(out
, &sep
[1], len
);
95 static char *rootdevname(char *devpath
) {
98 l
= strlen(devpath
) - 1;
100 /* strip partition suffix from root=/dev/... string */
101 while (l
> 0 && (devpath
[l
] >= '0' && devpath
[l
] <= '9'))
104 if (devpath
[l
] != 'p')
109 return basename(devpath
);
112 static struct volume
*partname_volume_find(char *name
)
114 struct partname_volume
*p
;
115 char volnamegstr
[BUFLEN
];
116 char namebuf
[BUFLEN
];
117 char rootparam
[BUFLEN
];
118 char *rootdev
= NULL
, *devname
, *tmp
;
123 if (get_cmdline_val("root", rootparam
, sizeof(rootparam
))) {
124 rootdev
= rootdevname(rootparam
);
125 /* find partition on same device as rootfs */
126 snprintf(volnamegstr
, sizeof(volnamegstr
), "%s/%s/*/name", block_dir_name
, rootdev
);
128 /* no 'root=' kernel cmdline parameter, find on any block device */
129 snprintf(volnamegstr
, sizeof(volnamegstr
), "%s/*/name", block_dir_name
);
132 if (!glob(volnamegstr
, GLOB_NOESCAPE
, NULL
, &gl
))
133 for (j
= 0; j
< gl
.gl_pathc
; j
++) {
134 if (!read_string_from_file("", gl
.gl_pathv
[j
], namebuf
, sizeof(namebuf
)))
136 if (!strncmp(namebuf
, name
, sizeof(namebuf
))) {
145 devname
= gl
.gl_pathv
[j
];
146 tmp
= strrchr(devname
, '/');
148 devname
= strrchr(devname
, '/') + 1;
150 p
= calloc(1, sizeof(*p
));
151 memcpy(p
->dev
.devpath
.prefix
, "/dev/", sizeof(p
->dev
.devpath
.prefix
));
152 strncpy(p
->dev
.devpath
.device
, devname
, sizeof(p
->dev
.devpath
.device
) - 1);
153 p
->dev
.devpath
.device
[sizeof(p
->dev
.devpath
.device
)-1] = '\0';
155 memcpy(p
->parent_dev
.devpath
.prefix
, "/dev/", sizeof(p
->parent_dev
.devpath
.prefix
));
157 strncpy(p
->parent_dev
.devpath
.device
, rootdev
, sizeof(p
->parent_dev
.devpath
.device
) - 1);
159 strncpy(p
->parent_dev
.devpath
.device
, rootdevname(devname
), sizeof(p
->parent_dev
.devpath
.device
) - 1);
161 p
->parent_dev
.devpath
.device
[sizeof(p
->parent_dev
.devpath
.device
)-1] = '\0';
163 p
->v
.drv
= &partname_driver
;
164 p
->v
.blk
= p
->dev
.devpathstr
;
170 static struct driver partname_driver
= {
172 .find
= partname_volume_find
,
173 .init
= partname_volume_init
,
174 .identify
= partname_volume_identify
,
177 DRIVER(partname_driver
);