• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/fstools/libfstools/ubi.c

  1 /*
  2  * Copyright (C) 2014 Daniel Golle <daniel@makrotopia.org>
  3  *
  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
  7  *
  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.
 12  */
 13 
 14 #include "common.h"
 15 
 16 /* fit for UBI_MAX_VOLUME_NAME and sysfs path lengths */
 17 #define BUFLEN          128
 18 
 19 /* could use libubi-tiny instead, but already had the code directly reading
 20  * from sysfs */
 21 const char *const ubi_dir_name = "/sys/devices/virtual/ubi";
 22 
 23 struct ubi_volume {
 24         struct volume v;
 25         int             ubi_num;
 26         int             ubi_volid;
 27 };
 28 
 29 static struct driver ubi_driver;
 30 
 31 static unsigned int
 32 test_open(char *filename)
 33 {
 34         FILE *f;
 35 
 36         f = fopen(filename, "r");
 37         if (!f)
 38                 return 0;
 39 
 40         fclose(f);
 41         return 1;
 42 }
 43 
 44 static int ubi_volume_init(struct volume *v)
 45 {
 46         struct ubi_volume *p = container_of(v, struct ubi_volume, v);
 47         char voldir[BUFLEN], voldev[BUFLEN], volname[BUFLEN];
 48         unsigned int volsize;
 49 
 50         snprintf(voldir, sizeof(voldir), "%s/ubi%u/ubi%u_%u",
 51                 ubi_dir_name, p->ubi_num, p->ubi_num, p->ubi_volid);
 52 
 53         snprintf(voldev, sizeof(voldev), "/dev/ubi%u_%u",
 54                 p->ubi_num, p->ubi_volid);
 55 
 56         if (!read_string_from_file(voldir, "name", volname, sizeof(volname)))
 57                 return -1;
 58 
 59         if (read_uint_from_file(voldir, "data_bytes", &volsize))
 60                 return -1;
 61 
 62         v->name = volname;
 63         v->type = UBIVOLUME;
 64         v->size = volsize;
 65         v->blk = strdup(voldev);
 66 
 67         return 0;
 68 }
 69 
 70 static struct volume *ubi_volume_match(char *name, int ubi_num, int volid)
 71 {
 72         char voldir[BUFLEN], volblkdev[BUFLEN], volname[BUFLEN];
 73         struct ubi_volume *p;
 74 
 75         snprintf(voldir, sizeof(voldir), "%s/ubi%u/ubi%u_%u",
 76                 ubi_dir_name, ubi_num, ubi_num, volid);
 77 
 78         snprintf(volblkdev, sizeof(volblkdev), "/dev/ubiblock%u_%u",
 79                 ubi_num, volid);
 80 
 81         /* skip if ubiblock device exists */
 82         if (test_open(volblkdev))
 83                 return NULL;
 84 
 85         /* todo: skip existing gluebi device for legacy support */
 86 
 87         if (!read_string_from_file(voldir, "name", volname, sizeof(volname))) {
 88                 ULOG_ERR("Couldn't read %s/name\n", voldir);
 89                 return NULL;
 90         }
 91 
 92         if (strcmp(name, volname))
 93                 return NULL;
 94 
 95         p = calloc(1, sizeof(struct ubi_volume));
 96         if (!p)
 97                 return NULL;
 98 
 99         p->v.drv = &ubi_driver;
100         p->ubi_num = ubi_num;
101         p->ubi_volid = volid;
102 
103         return &p->v;
104 }
105 
106 static struct volume *ubi_part_match(char *name, unsigned int ubi_num)
107 {
108         DIR *ubi_dir;
109         struct dirent *ubi_dirent;
110         unsigned int volid;
111         char devdir[BUFLEN];
112         struct volume *ret = NULL;
113 
114         snprintf(devdir, sizeof(devdir), "%s/ubi%u",
115                 ubi_dir_name, ubi_num);
116 
117         ubi_dir = opendir(devdir);
118         if (!ubi_dir)
119                 return ret;
120 
121         while ((ubi_dirent = readdir(ubi_dir)) != NULL) {
122                 if (strncmp(ubi_dirent->d_name, "ubi", 3))
123                         continue;
124 
125                 if (sscanf(ubi_dirent->d_name, "ubi%*u_%u", &volid) != 1)
126                         continue;
127 
128                 ret = ubi_volume_match(name, ubi_num, volid);
129                 if (ret)
130                         break;
131         }
132         closedir(ubi_dir);
133 
134         return ret;
135 }
136 
137 static struct volume *ubi_volume_find(char *name)
138 {
139         struct volume *ret = NULL;
140         DIR *ubi_dir;
141         struct dirent *ubi_dirent;
142         unsigned int ubi_num;
143 
144         if (find_filesystem("ubifs"))
145                 return ret;
146 
147         ubi_dir = opendir(ubi_dir_name);
148         /* check for os ubi support */
149         if (!ubi_dir)
150                 return ret;
151 
152         /* probe ubi devices and volumes */
153         while ((ubi_dirent = readdir(ubi_dir)) != NULL) {
154                 if (ubi_dirent->d_name[0] == '.')
155                         continue;
156 
157                 sscanf(ubi_dirent->d_name, "ubi%u", &ubi_num);
158                 ret = ubi_part_match(name, ubi_num);
159                 if (ret)
160                         break;
161         }
162         closedir(ubi_dir);
163         return ret;
164 }
165 
166 static int ubi_volume_identify(struct volume *v)
167 {
168         /* Todo: use libblkid-tiny on the ubi chardev */
169         return FS_UBIFS;
170 }
171 
172 static struct driver ubi_driver = {
173         .name = "ubi",
174         .find = ubi_volume_find,
175         .init = ubi_volume_init,
176         .identify = ubi_volume_identify,
177 };
178 
179 DRIVER(ubi_driver);
180 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt