support UBI blocks (volumes)
[project/fstools.git] / libblkid-tiny / libblkid-tiny.c
1 #include <stdio.h>
2 #include <sys/utsname.h>
3
4 #include "superblocks.h"
5 #include "linux_version.h"
6
7 #if 0
8 #define DEBUG(fmt, ...) printf(fmt, __VA_ARGS__)
9 #else
10 #define DEBUG(fmt, ...)
11 #endif
12
13 int blkid_debug_mask = 0;
14
15 static unsigned char *probe_buffer;
16 static unsigned int probe_buffer_size = 0;
17
18 int get_linux_version (void)
19 {
20         static int kver = -1;
21         struct utsname uts;
22         int major = 0;
23         int minor = 0;
24         int teeny = 0;
25         int n;
26
27         if (kver != -1)
28                 return kver;
29         if (uname (&uts))
30                 return kver = 0;
31
32         n = sscanf(uts.release, "%d.%d.%d", &major, &minor, &teeny);
33         if (n < 1 || n > 3)
34                 return kver = 0;
35
36         return kver = KERNEL_VERSION(major, minor, teeny);
37 }
38
39 int blkid_probe_is_tiny(blkid_probe pr)
40 {
41         /* never true ? */
42         return 0;
43 }
44
45 int blkid_probe_set_value(blkid_probe pr, const char *name,
46                 unsigned char *data, size_t len)
47 {
48         /* empty stub */
49         return 0;
50 }
51
52 int blkid_probe_set_version(blkid_probe pr, const char *version)
53 {
54         int len = strlen(version);
55         if (len > (sizeof(pr->version) - 1)) {
56                 fprintf(stderr, "version buffer too small %d\n", len);
57                 return -1;
58         }
59
60         strncpy(pr->version, version, sizeof(pr->version));
61
62         return 0;
63 }
64
65 int blkid_probe_sprintf_version(blkid_probe pr, const char *fmt, ...)
66 {
67         va_list ap;
68         int n;
69
70         va_start(ap, fmt);
71         n = vsnprintf(pr->version, sizeof(pr->version), fmt, ap);
72         va_end(ap);
73
74         if (n >= sizeof(pr->version))
75                 fprintf(stderr, "version buffer too small %d\n", n);
76
77         return 0;
78 }
79
80 unsigned char *blkid_probe_get_buffer(blkid_probe pr,
81                                 blkid_loff_t off, blkid_loff_t len)
82 {
83         int ret;
84         unsigned char *buf;
85
86         if (len > probe_buffer_size) {
87                 buf = realloc(probe_buffer, len);
88
89                 if (!buf) {
90                         fprintf(stderr, "failed to allocate %d byte buffer\n",
91                                 (int)len);
92
93                         return NULL;
94                 }
95
96                 probe_buffer = buf;
97                 probe_buffer_size = len;
98         }
99
100         memset(probe_buffer, 0, probe_buffer_size);
101
102         lseek(pr->fd, off, SEEK_SET);
103         ret = read(pr->fd, probe_buffer, len);
104
105         if (ret != len)
106                 fprintf(stderr, "faile to read blkid\n");
107
108         return probe_buffer;
109 }
110
111 int blkid_probe_set_label(blkid_probe pr, unsigned char *label, size_t len)
112 {
113         if (len > (sizeof(pr->label) - 1)) {
114                 fprintf(stderr, "label buffer too small %d > %d\n",
115                         (int) len, (int) sizeof(pr->label) - 1);
116                 return -1;
117         }
118         memcpy(pr->label, label, len + 1);
119
120         return 0;
121 }
122
123 int blkid_probe_set_uuid_as(blkid_probe pr, unsigned char *uuid, const char *name)
124 {
125         short unsigned int*u = (short unsigned int*) uuid;
126
127         if (u[0])
128                 sprintf(pr->uuid,
129                         "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
130                         be16_to_cpu(u[0]), be16_to_cpu(u[1]), be16_to_cpu(u[2]), be16_to_cpu(u[3]),
131                         be16_to_cpu(u[4]), be16_to_cpu(u[5]), be16_to_cpu(u[6]), be16_to_cpu(u[7]));
132         if (name)
133                 strncpy(pr->name, name, sizeof(pr->name));
134
135         return 0;
136 }
137
138 int blkid_probe_set_uuid(blkid_probe pr, unsigned char *uuid)
139 {
140         return blkid_probe_set_uuid_as(pr, uuid, NULL);
141 }
142
143 int blkid_probe_sprintf_uuid(blkid_probe pr, unsigned char *uuid,
144                              size_t len, const char *fmt, ...)
145 {
146         va_list ap;
147
148         va_start(ap, fmt);
149         vsnprintf(pr->uuid, sizeof(pr->uuid), fmt, ap);
150         va_end(ap);
151
152         return 0;
153 }
154
155 static const struct blkid_idinfo *idinfos[] =
156 {
157         &vfat_idinfo,
158         &swsuspend_idinfo,
159         &swap_idinfo,
160         &ext4dev_idinfo,
161         &ext4_idinfo,
162         &ext3_idinfo,
163         &ext2_idinfo,
164         &jbd_idinfo,
165         &squashfs_idinfo,
166         &ubifs_idinfo,
167         &jffs2_idinfo,
168         &hfsplus_idinfo,
169         &hfs_idinfo,
170 };
171
172 int probe_block(char *block, struct blkid_struct_probe *pr)
173 {
174         struct stat s;
175         int i;
176
177         if (stat(block, &s) || (!S_ISBLK(s.st_mode) && !S_ISREG(s.st_mode) && !strncmp(block, "ubi", 3)))
178                 return -1;
179
180         pr->err = -1;
181         pr->fd = open(block, O_RDONLY);
182         if (!pr->fd)
183                 return -1;
184
185         for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
186                 /* loop over all magic handlers */
187                 const struct blkid_idmag *mag;
188
189                 /* loop over all probe handlers */
190                 DEBUG("scanning %s\n", idinfos[i]->name);
191
192                 mag = &idinfos[i]->magics[0];
193
194                 while (mag->magic) {
195                         int off = (mag->kboff * 1024) + mag->sboff;
196                         char magic[32] = { 0 };
197
198                         lseek(pr->fd, off, SEEK_SET);
199                         read(pr->fd, magic, mag->len);
200
201                         DEBUG("magic: %s %s %d\n", mag->magic, magic, mag->len);
202                         if (!memcmp(mag->magic, magic, mag->len))
203                                 break;
204                         mag++;
205                 }
206
207                 if (mag && mag->magic) {
208                         DEBUG("probing %s\n", idinfos[i]->name);
209                         pr->err = idinfos[i]->probefunc(pr, mag);
210                         pr->id = idinfos[i];
211                         strcpy(pr->dev, block);
212                         if (!pr->err)
213                                 break;
214                 }
215         }
216
217         close(pr->fd);
218
219         return 0;
220 }