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