2 * Copyright (C) 2014 Daniel Golle <daniel@makrotopia.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2.1
6 * as published by the Free Software Foundation
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
19 #include "libfstools.h"
22 /* fit for UBI_MAX_VOLUME_NAME and sysfs path lengths */
25 /* could use libubi-tiny instead, but already had the code directly reading
27 const char *const ubi_dir_name
= "/sys/devices/virtual/ubi";
34 static struct driver ubi_driver
;
37 read_uint_from_file(char *dirname
, char *filename
, unsigned int *i
)
43 snprintf(fname
, sizeof(fname
), "%s/%s", dirname
, filename
);
45 f
= fopen(fname
, "r");
49 if (fscanf(f
, "%u", i
) == 1)
57 *read_string_from_file(char *dirname
, char *filename
)
64 snprintf(fname
, sizeof(fname
), "%s/%s", dirname
, filename
);
66 f
= fopen(fname
, "r");
70 if (fgets(buf
, sizeof(buf
), f
) == NULL
)
75 /* make sure the string is \0 terminated */
76 buf
[sizeof(buf
) - 1] = '\0';
78 /* remove trailing whitespace */
80 while (i
> 0 && buf
[i
] <= ' ')
87 test_open(char *filename
)
91 f
= fopen(filename
, "r");
99 static int ubi_volume_init(struct volume
*v
)
101 char voldir
[BUFLEN
], voldev
[BUFLEN
], *volname
;
103 unsigned int volsize
;
105 p
= (struct ubi_priv
*)v
->priv
;
107 snprintf(voldir
, sizeof(voldir
), "%s/ubi%u/ubi%u_%u",
108 ubi_dir_name
, p
->ubi_num
, p
->ubi_num
, p
->ubi_volid
);
110 snprintf(voldev
, sizeof(voldev
), "/dev/ubi%u_%u",
111 p
->ubi_num
, p
->ubi_volid
);
113 volname
= read_string_from_file(voldir
, "name");
117 if (read_uint_from_file(voldir
, "data_bytes", &volsize
))
123 v
->blk
= strdup(voldev
);
128 static int ubi_volume_match(struct volume
*v
, char *name
, int ubi_num
, int volid
)
130 char voldir
[BUFLEN
], volblkdev
[BUFLEN
], *volname
;
133 snprintf(voldir
, sizeof(voldir
), "%s/ubi%u/ubi%u_%u",
134 ubi_dir_name
, ubi_num
, ubi_num
, volid
);
136 snprintf(volblkdev
, sizeof(volblkdev
), "/dev/ubiblock%u_%u",
139 /* skip if ubiblock device exists */
140 if (test_open(volblkdev
))
143 /* todo: skip existing gluebi device for legacy support */
145 volname
= read_string_from_file(voldir
, "name");
147 fprintf(stderr
, "Couldn't read %s/name\n", voldir
);
151 if (strncmp(name
, volname
, strlen(volname
) + 1))
154 p
= calloc(1, sizeof(struct ubi_priv
));
159 v
->drv
= &ubi_driver
;
160 p
->ubi_num
= ubi_num
;
161 p
->ubi_volid
= volid
;
163 return ubi_volume_init(v
);
166 static int ubi_part_match(struct volume
*v
, char *name
, unsigned int ubi_num
)
169 struct dirent
*ubi_dirent
;
174 snprintf(devdir
, sizeof(devdir
), "%s/ubi%u",
175 ubi_dir_name
, ubi_num
);
177 ubi_dir
= opendir(devdir
);
181 while ((ubi_dirent
= readdir(ubi_dir
)) != NULL
) {
182 if (strncmp(ubi_dirent
->d_name
, "ubi", 3))
185 if (sscanf(ubi_dirent
->d_name
, "ubi%*u_%u", &volid
) != 1)
188 if (!ubi_volume_match(v
, name
, ubi_num
, volid
)) {
198 static int ubi_volume_find(struct volume
*v
, char *name
)
201 struct dirent
*ubi_dirent
;
202 unsigned int ubi_num
;
205 if (find_filesystem("ubifs"))
208 ubi_dir
= opendir(ubi_dir_name
);
209 /* check for os ubi support */
213 /* probe ubi devices and volumes */
214 while ((ubi_dirent
= readdir(ubi_dir
)) != NULL
) {
215 if (ubi_dirent
->d_name
[0] == '.')
218 sscanf(ubi_dirent
->d_name
, "ubi%u", &ubi_num
);
219 if (!ubi_part_match(v
, name
, ubi_num
)) {
228 static int ubi_volume_identify(struct volume
*v
)
230 /* Todo: use libblkid-tiny on the ubi chardev */
234 static struct driver ubi_driver
= {
236 .find
= ubi_volume_find
,
237 .init
= ubi_volume_init
,
238 .identify
= ubi_volume_identify
,