1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker * read.c - read the blkid cache from disk, to avoid scanning all devices
3*6a54128fSAndroid Build Coastguard Worker *
4*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 2001, 2003 Theodore Y. Ts'o
5*6a54128fSAndroid Build Coastguard Worker * Copyright (C) 2001 Andreas Dilger
6*6a54128fSAndroid Build Coastguard Worker *
7*6a54128fSAndroid Build Coastguard Worker * %Begin-Header%
8*6a54128fSAndroid Build Coastguard Worker * This file may be redistributed under the terms of the
9*6a54128fSAndroid Build Coastguard Worker * GNU Lesser General Public License.
10*6a54128fSAndroid Build Coastguard Worker * %End-Header%
11*6a54128fSAndroid Build Coastguard Worker */
12*6a54128fSAndroid Build Coastguard Worker
13*6a54128fSAndroid Build Coastguard Worker #define _XOPEN_SOURCE 600 /* for inclusion of strtoull */
14*6a54128fSAndroid Build Coastguard Worker
15*6a54128fSAndroid Build Coastguard Worker #include "config.h"
16*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
17*6a54128fSAndroid Build Coastguard Worker #include <ctype.h>
18*6a54128fSAndroid Build Coastguard Worker #include <string.h>
19*6a54128fSAndroid Build Coastguard Worker #include <time.h>
20*6a54128fSAndroid Build Coastguard Worker #include <sys/types.h>
21*6a54128fSAndroid Build Coastguard Worker #include <sys/stat.h>
22*6a54128fSAndroid Build Coastguard Worker #include <fcntl.h>
23*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
24*6a54128fSAndroid Build Coastguard Worker #if HAVE_ERRNO_H
25*6a54128fSAndroid Build Coastguard Worker #include <errno.h>
26*6a54128fSAndroid Build Coastguard Worker #endif
27*6a54128fSAndroid Build Coastguard Worker
28*6a54128fSAndroid Build Coastguard Worker #include "blkidP.h"
29*6a54128fSAndroid Build Coastguard Worker #include "uuid/uuid.h"
30*6a54128fSAndroid Build Coastguard Worker
31*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_STRTOULL
32*6a54128fSAndroid Build Coastguard Worker #define STRTOULL strtoull /* defined in stdlib.h if you try hard enough */
33*6a54128fSAndroid Build Coastguard Worker #else
34*6a54128fSAndroid Build Coastguard Worker /* FIXME: need to support real strtoull here */
35*6a54128fSAndroid Build Coastguard Worker #define STRTOULL strtoul
36*6a54128fSAndroid Build Coastguard Worker #endif
37*6a54128fSAndroid Build Coastguard Worker
38*6a54128fSAndroid Build Coastguard Worker #if HAVE_STDLIB_H
39*6a54128fSAndroid Build Coastguard Worker #include <stdlib.h>
40*6a54128fSAndroid Build Coastguard Worker #endif
41*6a54128fSAndroid Build Coastguard Worker
42*6a54128fSAndroid Build Coastguard Worker #ifdef TEST_PROGRAM
43*6a54128fSAndroid Build Coastguard Worker #define blkid_debug_dump_dev(dev) (debug_dump_dev(dev))
44*6a54128fSAndroid Build Coastguard Worker static void debug_dump_dev(blkid_dev dev);
45*6a54128fSAndroid Build Coastguard Worker #endif
46*6a54128fSAndroid Build Coastguard Worker
47*6a54128fSAndroid Build Coastguard Worker /*
48*6a54128fSAndroid Build Coastguard Worker * File format:
49*6a54128fSAndroid Build Coastguard Worker *
50*6a54128fSAndroid Build Coastguard Worker * <device [<NAME="value"> ...]>device_name</device>
51*6a54128fSAndroid Build Coastguard Worker *
52*6a54128fSAndroid Build Coastguard Worker * The following tags are required for each entry:
53*6a54128fSAndroid Build Coastguard Worker * <ID="id"> unique (within this file) ID number of this device
54*6a54128fSAndroid Build Coastguard Worker * <TIME="time"> (ascii time_t) time this entry was last read from disk
55*6a54128fSAndroid Build Coastguard Worker * <TYPE="type"> (detected) type of filesystem/data for this partition
56*6a54128fSAndroid Build Coastguard Worker *
57*6a54128fSAndroid Build Coastguard Worker * The following tags may be present, depending on the device contents
58*6a54128fSAndroid Build Coastguard Worker * <LABEL="label"> (user supplied) label (volume name, etc)
59*6a54128fSAndroid Build Coastguard Worker * <UUID="uuid"> (generated) universally unique identifier (serial no)
60*6a54128fSAndroid Build Coastguard Worker */
61*6a54128fSAndroid Build Coastguard Worker
skip_over_blank(char * cp)62*6a54128fSAndroid Build Coastguard Worker static char *skip_over_blank(char *cp)
63*6a54128fSAndroid Build Coastguard Worker {
64*6a54128fSAndroid Build Coastguard Worker while (*cp && isspace(*cp))
65*6a54128fSAndroid Build Coastguard Worker cp++;
66*6a54128fSAndroid Build Coastguard Worker return cp;
67*6a54128fSAndroid Build Coastguard Worker }
68*6a54128fSAndroid Build Coastguard Worker
skip_over_word(char * cp)69*6a54128fSAndroid Build Coastguard Worker static char *skip_over_word(char *cp)
70*6a54128fSAndroid Build Coastguard Worker {
71*6a54128fSAndroid Build Coastguard Worker char ch;
72*6a54128fSAndroid Build Coastguard Worker
73*6a54128fSAndroid Build Coastguard Worker while ((ch = *cp)) {
74*6a54128fSAndroid Build Coastguard Worker /* If we see a backslash, skip the next character */
75*6a54128fSAndroid Build Coastguard Worker if (ch == '\\') {
76*6a54128fSAndroid Build Coastguard Worker cp++;
77*6a54128fSAndroid Build Coastguard Worker if (*cp == '\0')
78*6a54128fSAndroid Build Coastguard Worker break;
79*6a54128fSAndroid Build Coastguard Worker cp++;
80*6a54128fSAndroid Build Coastguard Worker continue;
81*6a54128fSAndroid Build Coastguard Worker }
82*6a54128fSAndroid Build Coastguard Worker if (isspace(ch) || ch == '<' || ch == '>')
83*6a54128fSAndroid Build Coastguard Worker break;
84*6a54128fSAndroid Build Coastguard Worker cp++;
85*6a54128fSAndroid Build Coastguard Worker }
86*6a54128fSAndroid Build Coastguard Worker return cp;
87*6a54128fSAndroid Build Coastguard Worker }
88*6a54128fSAndroid Build Coastguard Worker
strip_line(char * line)89*6a54128fSAndroid Build Coastguard Worker static char *strip_line(char *line)
90*6a54128fSAndroid Build Coastguard Worker {
91*6a54128fSAndroid Build Coastguard Worker char *p;
92*6a54128fSAndroid Build Coastguard Worker
93*6a54128fSAndroid Build Coastguard Worker line = skip_over_blank(line);
94*6a54128fSAndroid Build Coastguard Worker
95*6a54128fSAndroid Build Coastguard Worker p = line + strlen(line) - 1;
96*6a54128fSAndroid Build Coastguard Worker
97*6a54128fSAndroid Build Coastguard Worker while (*line) {
98*6a54128fSAndroid Build Coastguard Worker if (isspace(*p))
99*6a54128fSAndroid Build Coastguard Worker *p-- = '\0';
100*6a54128fSAndroid Build Coastguard Worker else
101*6a54128fSAndroid Build Coastguard Worker break;
102*6a54128fSAndroid Build Coastguard Worker }
103*6a54128fSAndroid Build Coastguard Worker
104*6a54128fSAndroid Build Coastguard Worker return line;
105*6a54128fSAndroid Build Coastguard Worker }
106*6a54128fSAndroid Build Coastguard Worker
107*6a54128fSAndroid Build Coastguard Worker #if 0
108*6a54128fSAndroid Build Coastguard Worker static char *parse_word(char **buf)
109*6a54128fSAndroid Build Coastguard Worker {
110*6a54128fSAndroid Build Coastguard Worker char *word, *next;
111*6a54128fSAndroid Build Coastguard Worker
112*6a54128fSAndroid Build Coastguard Worker word = *buf;
113*6a54128fSAndroid Build Coastguard Worker if (*word == '\0')
114*6a54128fSAndroid Build Coastguard Worker return NULL;
115*6a54128fSAndroid Build Coastguard Worker
116*6a54128fSAndroid Build Coastguard Worker word = skip_over_blank(word);
117*6a54128fSAndroid Build Coastguard Worker next = skip_over_word(word);
118*6a54128fSAndroid Build Coastguard Worker if (*next) {
119*6a54128fSAndroid Build Coastguard Worker char *end = next - 1;
120*6a54128fSAndroid Build Coastguard Worker if (*end == '"' || *end == '\'')
121*6a54128fSAndroid Build Coastguard Worker *end = '\0';
122*6a54128fSAndroid Build Coastguard Worker *next++ = '\0';
123*6a54128fSAndroid Build Coastguard Worker }
124*6a54128fSAndroid Build Coastguard Worker *buf = next;
125*6a54128fSAndroid Build Coastguard Worker
126*6a54128fSAndroid Build Coastguard Worker if (*word == '"' || *word == '\'')
127*6a54128fSAndroid Build Coastguard Worker word++;
128*6a54128fSAndroid Build Coastguard Worker return word;
129*6a54128fSAndroid Build Coastguard Worker }
130*6a54128fSAndroid Build Coastguard Worker #endif
131*6a54128fSAndroid Build Coastguard Worker
132*6a54128fSAndroid Build Coastguard Worker /*
133*6a54128fSAndroid Build Coastguard Worker * Start parsing a new line from the cache.
134*6a54128fSAndroid Build Coastguard Worker *
135*6a54128fSAndroid Build Coastguard Worker * line starts with "<device" return 1 -> continue parsing line
136*6a54128fSAndroid Build Coastguard Worker * line starts with "<foo", empty, or # return 0 -> skip line
137*6a54128fSAndroid Build Coastguard Worker * line starts with other, return -BLKID_ERR_CACHE -> error
138*6a54128fSAndroid Build Coastguard Worker */
parse_start(char ** cp)139*6a54128fSAndroid Build Coastguard Worker static int parse_start(char **cp)
140*6a54128fSAndroid Build Coastguard Worker {
141*6a54128fSAndroid Build Coastguard Worker char *p;
142*6a54128fSAndroid Build Coastguard Worker
143*6a54128fSAndroid Build Coastguard Worker p = strip_line(*cp);
144*6a54128fSAndroid Build Coastguard Worker
145*6a54128fSAndroid Build Coastguard Worker /* Skip comment or blank lines. We can't just NUL the first '#' char,
146*6a54128fSAndroid Build Coastguard Worker * in case it is inside quotes, or escaped.
147*6a54128fSAndroid Build Coastguard Worker */
148*6a54128fSAndroid Build Coastguard Worker if (*p == '\0' || *p == '#')
149*6a54128fSAndroid Build Coastguard Worker return 0;
150*6a54128fSAndroid Build Coastguard Worker
151*6a54128fSAndroid Build Coastguard Worker if (!strncmp(p, "<device", 7)) {
152*6a54128fSAndroid Build Coastguard Worker DBG(DEBUG_READ, printf("found device header: %8s\n", p));
153*6a54128fSAndroid Build Coastguard Worker p += 7;
154*6a54128fSAndroid Build Coastguard Worker
155*6a54128fSAndroid Build Coastguard Worker *cp = p;
156*6a54128fSAndroid Build Coastguard Worker return 1;
157*6a54128fSAndroid Build Coastguard Worker }
158*6a54128fSAndroid Build Coastguard Worker
159*6a54128fSAndroid Build Coastguard Worker if (*p == '<')
160*6a54128fSAndroid Build Coastguard Worker return 0;
161*6a54128fSAndroid Build Coastguard Worker
162*6a54128fSAndroid Build Coastguard Worker return -BLKID_ERR_CACHE;
163*6a54128fSAndroid Build Coastguard Worker }
164*6a54128fSAndroid Build Coastguard Worker
165*6a54128fSAndroid Build Coastguard Worker /* Consume the remaining XML on the line (cosmetic only) */
parse_end(char ** cp)166*6a54128fSAndroid Build Coastguard Worker static int parse_end(char **cp)
167*6a54128fSAndroid Build Coastguard Worker {
168*6a54128fSAndroid Build Coastguard Worker *cp = skip_over_blank(*cp);
169*6a54128fSAndroid Build Coastguard Worker
170*6a54128fSAndroid Build Coastguard Worker if (!strncmp(*cp, "</device>", 9)) {
171*6a54128fSAndroid Build Coastguard Worker DBG(DEBUG_READ, printf("found device trailer %9s\n", *cp));
172*6a54128fSAndroid Build Coastguard Worker *cp += 9;
173*6a54128fSAndroid Build Coastguard Worker return 0;
174*6a54128fSAndroid Build Coastguard Worker }
175*6a54128fSAndroid Build Coastguard Worker
176*6a54128fSAndroid Build Coastguard Worker return -BLKID_ERR_CACHE;
177*6a54128fSAndroid Build Coastguard Worker }
178*6a54128fSAndroid Build Coastguard Worker
179*6a54128fSAndroid Build Coastguard Worker /*
180*6a54128fSAndroid Build Coastguard Worker * Allocate a new device struct with device name filled in. Will handle
181*6a54128fSAndroid Build Coastguard Worker * finding the device on lines of the form:
182*6a54128fSAndroid Build Coastguard Worker * <device foo=bar>devname</device>
183*6a54128fSAndroid Build Coastguard Worker * <device>devname<foo>bar</foo></device>
184*6a54128fSAndroid Build Coastguard Worker */
parse_dev(blkid_cache cache,blkid_dev * dev,char ** cp)185*6a54128fSAndroid Build Coastguard Worker static int parse_dev(blkid_cache cache, blkid_dev *dev, char **cp)
186*6a54128fSAndroid Build Coastguard Worker {
187*6a54128fSAndroid Build Coastguard Worker char *start, *tmp, *end, *name;
188*6a54128fSAndroid Build Coastguard Worker int ret;
189*6a54128fSAndroid Build Coastguard Worker
190*6a54128fSAndroid Build Coastguard Worker if ((ret = parse_start(cp)) <= 0)
191*6a54128fSAndroid Build Coastguard Worker return ret;
192*6a54128fSAndroid Build Coastguard Worker
193*6a54128fSAndroid Build Coastguard Worker start = tmp = strchr(*cp, '>');
194*6a54128fSAndroid Build Coastguard Worker if (!start) {
195*6a54128fSAndroid Build Coastguard Worker DBG(DEBUG_READ,
196*6a54128fSAndroid Build Coastguard Worker printf("blkid: short line parsing dev: %s\n", *cp));
197*6a54128fSAndroid Build Coastguard Worker return -BLKID_ERR_CACHE;
198*6a54128fSAndroid Build Coastguard Worker }
199*6a54128fSAndroid Build Coastguard Worker start = skip_over_blank(start + 1);
200*6a54128fSAndroid Build Coastguard Worker end = skip_over_word(start);
201*6a54128fSAndroid Build Coastguard Worker
202*6a54128fSAndroid Build Coastguard Worker DBG(DEBUG_READ, printf("device should be %.*s\n",
203*6a54128fSAndroid Build Coastguard Worker (int)(end - start), start));
204*6a54128fSAndroid Build Coastguard Worker
205*6a54128fSAndroid Build Coastguard Worker if (**cp == '>')
206*6a54128fSAndroid Build Coastguard Worker *cp = end;
207*6a54128fSAndroid Build Coastguard Worker else
208*6a54128fSAndroid Build Coastguard Worker (*cp)++;
209*6a54128fSAndroid Build Coastguard Worker
210*6a54128fSAndroid Build Coastguard Worker *tmp = '\0';
211*6a54128fSAndroid Build Coastguard Worker
212*6a54128fSAndroid Build Coastguard Worker if (!(tmp = strrchr(end, '<')) || parse_end(&tmp) < 0) {
213*6a54128fSAndroid Build Coastguard Worker DBG(DEBUG_READ,
214*6a54128fSAndroid Build Coastguard Worker printf("blkid: missing </device> ending: %s\n", end));
215*6a54128fSAndroid Build Coastguard Worker } else if (tmp)
216*6a54128fSAndroid Build Coastguard Worker *tmp = '\0';
217*6a54128fSAndroid Build Coastguard Worker
218*6a54128fSAndroid Build Coastguard Worker if (end - start <= 1) {
219*6a54128fSAndroid Build Coastguard Worker DBG(DEBUG_READ, printf("blkid: empty device name: %s\n", *cp));
220*6a54128fSAndroid Build Coastguard Worker return -BLKID_ERR_CACHE;
221*6a54128fSAndroid Build Coastguard Worker }
222*6a54128fSAndroid Build Coastguard Worker
223*6a54128fSAndroid Build Coastguard Worker name = blkid_strndup(start, end-start);
224*6a54128fSAndroid Build Coastguard Worker if (name == NULL)
225*6a54128fSAndroid Build Coastguard Worker return -BLKID_ERR_MEM;
226*6a54128fSAndroid Build Coastguard Worker
227*6a54128fSAndroid Build Coastguard Worker DBG(DEBUG_READ, printf("found dev %s\n", name));
228*6a54128fSAndroid Build Coastguard Worker
229*6a54128fSAndroid Build Coastguard Worker if (!(*dev = blkid_get_dev(cache, name, BLKID_DEV_CREATE))) {
230*6a54128fSAndroid Build Coastguard Worker free(name);
231*6a54128fSAndroid Build Coastguard Worker return -BLKID_ERR_MEM;
232*6a54128fSAndroid Build Coastguard Worker }
233*6a54128fSAndroid Build Coastguard Worker
234*6a54128fSAndroid Build Coastguard Worker free(name);
235*6a54128fSAndroid Build Coastguard Worker return 1;
236*6a54128fSAndroid Build Coastguard Worker }
237*6a54128fSAndroid Build Coastguard Worker
238*6a54128fSAndroid Build Coastguard Worker /*
239*6a54128fSAndroid Build Coastguard Worker * Extract a tag of the form NAME="value" from the line.
240*6a54128fSAndroid Build Coastguard Worker */
parse_token(char ** name,char ** value,char ** cp)241*6a54128fSAndroid Build Coastguard Worker static int parse_token(char **name, char **value, char **cp)
242*6a54128fSAndroid Build Coastguard Worker {
243*6a54128fSAndroid Build Coastguard Worker char *end;
244*6a54128fSAndroid Build Coastguard Worker
245*6a54128fSAndroid Build Coastguard Worker if (!name || !value || !cp)
246*6a54128fSAndroid Build Coastguard Worker return -BLKID_ERR_PARAM;
247*6a54128fSAndroid Build Coastguard Worker
248*6a54128fSAndroid Build Coastguard Worker if (!(*value = strchr(*cp, '=')))
249*6a54128fSAndroid Build Coastguard Worker return 0;
250*6a54128fSAndroid Build Coastguard Worker
251*6a54128fSAndroid Build Coastguard Worker **value = '\0';
252*6a54128fSAndroid Build Coastguard Worker *name = strip_line(*cp);
253*6a54128fSAndroid Build Coastguard Worker *value = skip_over_blank(*value + 1);
254*6a54128fSAndroid Build Coastguard Worker
255*6a54128fSAndroid Build Coastguard Worker if (**value == '"') {
256*6a54128fSAndroid Build Coastguard Worker end = strchr(*value + 1, '"');
257*6a54128fSAndroid Build Coastguard Worker if (!end) {
258*6a54128fSAndroid Build Coastguard Worker DBG(DEBUG_READ,
259*6a54128fSAndroid Build Coastguard Worker printf("unbalanced quotes at: %s\n", *value));
260*6a54128fSAndroid Build Coastguard Worker *cp = *value;
261*6a54128fSAndroid Build Coastguard Worker return -BLKID_ERR_CACHE;
262*6a54128fSAndroid Build Coastguard Worker }
263*6a54128fSAndroid Build Coastguard Worker (*value)++;
264*6a54128fSAndroid Build Coastguard Worker *end = '\0';
265*6a54128fSAndroid Build Coastguard Worker end++;
266*6a54128fSAndroid Build Coastguard Worker } else {
267*6a54128fSAndroid Build Coastguard Worker end = skip_over_word(*value);
268*6a54128fSAndroid Build Coastguard Worker if (*end) {
269*6a54128fSAndroid Build Coastguard Worker *end = '\0';
270*6a54128fSAndroid Build Coastguard Worker end++;
271*6a54128fSAndroid Build Coastguard Worker }
272*6a54128fSAndroid Build Coastguard Worker }
273*6a54128fSAndroid Build Coastguard Worker *cp = end;
274*6a54128fSAndroid Build Coastguard Worker
275*6a54128fSAndroid Build Coastguard Worker return 1;
276*6a54128fSAndroid Build Coastguard Worker }
277*6a54128fSAndroid Build Coastguard Worker
278*6a54128fSAndroid Build Coastguard Worker /*
279*6a54128fSAndroid Build Coastguard Worker * Extract a tag of the form <NAME>value</NAME> from the line.
280*6a54128fSAndroid Build Coastguard Worker */
281*6a54128fSAndroid Build Coastguard Worker /*
282*6a54128fSAndroid Build Coastguard Worker static int parse_xml(char **name, char **value, char **cp)
283*6a54128fSAndroid Build Coastguard Worker {
284*6a54128fSAndroid Build Coastguard Worker char *end;
285*6a54128fSAndroid Build Coastguard Worker
286*6a54128fSAndroid Build Coastguard Worker if (!name || !value || !cp)
287*6a54128fSAndroid Build Coastguard Worker return -BLKID_ERR_PARAM;
288*6a54128fSAndroid Build Coastguard Worker
289*6a54128fSAndroid Build Coastguard Worker *name = strip_line(*cp);
290*6a54128fSAndroid Build Coastguard Worker
291*6a54128fSAndroid Build Coastguard Worker if ((*name)[0] != '<' || (*name)[1] == '/')
292*6a54128fSAndroid Build Coastguard Worker return 0;
293*6a54128fSAndroid Build Coastguard Worker
294*6a54128fSAndroid Build Coastguard Worker FIXME: finish this.
295*6a54128fSAndroid Build Coastguard Worker }
296*6a54128fSAndroid Build Coastguard Worker */
297*6a54128fSAndroid Build Coastguard Worker
298*6a54128fSAndroid Build Coastguard Worker /*
299*6a54128fSAndroid Build Coastguard Worker * Extract a tag from the line.
300*6a54128fSAndroid Build Coastguard Worker *
301*6a54128fSAndroid Build Coastguard Worker * Return 1 if a valid tag was found.
302*6a54128fSAndroid Build Coastguard Worker * Return 0 if no tag found.
303*6a54128fSAndroid Build Coastguard Worker * Return -ve error code.
304*6a54128fSAndroid Build Coastguard Worker */
parse_tag(blkid_cache cache,blkid_dev dev,char ** cp)305*6a54128fSAndroid Build Coastguard Worker static int parse_tag(blkid_cache cache, blkid_dev dev, char **cp)
306*6a54128fSAndroid Build Coastguard Worker {
307*6a54128fSAndroid Build Coastguard Worker char *name;
308*6a54128fSAndroid Build Coastguard Worker char *value;
309*6a54128fSAndroid Build Coastguard Worker int ret;
310*6a54128fSAndroid Build Coastguard Worker
311*6a54128fSAndroid Build Coastguard Worker if (!cache || !dev)
312*6a54128fSAndroid Build Coastguard Worker return -BLKID_ERR_PARAM;
313*6a54128fSAndroid Build Coastguard Worker
314*6a54128fSAndroid Build Coastguard Worker if ((ret = parse_token(&name, &value, cp)) <= 0 /* &&
315*6a54128fSAndroid Build Coastguard Worker (ret = parse_xml(&name, &value, cp)) <= 0 */)
316*6a54128fSAndroid Build Coastguard Worker return ret;
317*6a54128fSAndroid Build Coastguard Worker
318*6a54128fSAndroid Build Coastguard Worker /* Some tags are stored directly in the device struct */
319*6a54128fSAndroid Build Coastguard Worker if (!strcmp(name, "DEVNO"))
320*6a54128fSAndroid Build Coastguard Worker dev->bid_devno = STRTOULL(value, 0, 0);
321*6a54128fSAndroid Build Coastguard Worker else if (!strcmp(name, "PRI"))
322*6a54128fSAndroid Build Coastguard Worker dev->bid_pri = strtol(value, 0, 0);
323*6a54128fSAndroid Build Coastguard Worker else if (!strcmp(name, "TIME"))
324*6a54128fSAndroid Build Coastguard Worker dev->bid_time = STRTOULL(value, 0, 0);
325*6a54128fSAndroid Build Coastguard Worker else
326*6a54128fSAndroid Build Coastguard Worker ret = blkid_set_tag(dev, name, value, strlen(value));
327*6a54128fSAndroid Build Coastguard Worker
328*6a54128fSAndroid Build Coastguard Worker DBG(DEBUG_READ, printf(" tag: %s=\"%s\"\n", name, value));
329*6a54128fSAndroid Build Coastguard Worker
330*6a54128fSAndroid Build Coastguard Worker return ret < 0 ? ret : 1;
331*6a54128fSAndroid Build Coastguard Worker }
332*6a54128fSAndroid Build Coastguard Worker
333*6a54128fSAndroid Build Coastguard Worker /*
334*6a54128fSAndroid Build Coastguard Worker * Parse a single line of data, and return a newly allocated dev struct.
335*6a54128fSAndroid Build Coastguard Worker * Add the new device to the cache struct, if one was read.
336*6a54128fSAndroid Build Coastguard Worker *
337*6a54128fSAndroid Build Coastguard Worker * Lines are of the form <device [TAG="value" ...]>/dev/foo</device>
338*6a54128fSAndroid Build Coastguard Worker *
339*6a54128fSAndroid Build Coastguard Worker * Returns -ve value on error.
340*6a54128fSAndroid Build Coastguard Worker * Returns 0 otherwise.
341*6a54128fSAndroid Build Coastguard Worker * If a valid device was read, *dev_p is non-NULL, otherwise it is NULL
342*6a54128fSAndroid Build Coastguard Worker * (e.g. comment lines, unknown XML content, etc).
343*6a54128fSAndroid Build Coastguard Worker */
blkid_parse_line(blkid_cache cache,blkid_dev * dev_p,char * cp)344*6a54128fSAndroid Build Coastguard Worker static int blkid_parse_line(blkid_cache cache, blkid_dev *dev_p, char *cp)
345*6a54128fSAndroid Build Coastguard Worker {
346*6a54128fSAndroid Build Coastguard Worker blkid_dev dev;
347*6a54128fSAndroid Build Coastguard Worker int ret;
348*6a54128fSAndroid Build Coastguard Worker
349*6a54128fSAndroid Build Coastguard Worker if (!cache || !dev_p)
350*6a54128fSAndroid Build Coastguard Worker return -BLKID_ERR_PARAM;
351*6a54128fSAndroid Build Coastguard Worker
352*6a54128fSAndroid Build Coastguard Worker *dev_p = NULL;
353*6a54128fSAndroid Build Coastguard Worker
354*6a54128fSAndroid Build Coastguard Worker DBG(DEBUG_READ, printf("line: %s\n", cp));
355*6a54128fSAndroid Build Coastguard Worker
356*6a54128fSAndroid Build Coastguard Worker if ((ret = parse_dev(cache, dev_p, &cp)) <= 0)
357*6a54128fSAndroid Build Coastguard Worker return ret;
358*6a54128fSAndroid Build Coastguard Worker
359*6a54128fSAndroid Build Coastguard Worker dev = *dev_p;
360*6a54128fSAndroid Build Coastguard Worker
361*6a54128fSAndroid Build Coastguard Worker while ((ret = parse_tag(cache, dev, &cp)) > 0) {
362*6a54128fSAndroid Build Coastguard Worker ;
363*6a54128fSAndroid Build Coastguard Worker }
364*6a54128fSAndroid Build Coastguard Worker
365*6a54128fSAndroid Build Coastguard Worker if (dev->bid_type == NULL) {
366*6a54128fSAndroid Build Coastguard Worker DBG(DEBUG_READ,
367*6a54128fSAndroid Build Coastguard Worker printf("blkid: device %s has no TYPE\n",dev->bid_name));
368*6a54128fSAndroid Build Coastguard Worker blkid_free_dev(dev);
369*6a54128fSAndroid Build Coastguard Worker }
370*6a54128fSAndroid Build Coastguard Worker
371*6a54128fSAndroid Build Coastguard Worker DBG(DEBUG_READ, blkid_debug_dump_dev(dev));
372*6a54128fSAndroid Build Coastguard Worker
373*6a54128fSAndroid Build Coastguard Worker return ret;
374*6a54128fSAndroid Build Coastguard Worker }
375*6a54128fSAndroid Build Coastguard Worker
376*6a54128fSAndroid Build Coastguard Worker /*
377*6a54128fSAndroid Build Coastguard Worker * Parse the specified filename, and return the data in the supplied or
378*6a54128fSAndroid Build Coastguard Worker * a newly allocated cache struct. If the file doesn't exist, return a
379*6a54128fSAndroid Build Coastguard Worker * new empty cache struct.
380*6a54128fSAndroid Build Coastguard Worker */
blkid_read_cache(blkid_cache cache)381*6a54128fSAndroid Build Coastguard Worker void blkid_read_cache(blkid_cache cache)
382*6a54128fSAndroid Build Coastguard Worker {
383*6a54128fSAndroid Build Coastguard Worker FILE *file;
384*6a54128fSAndroid Build Coastguard Worker char buf[4096];
385*6a54128fSAndroid Build Coastguard Worker int fd, lineno = 0;
386*6a54128fSAndroid Build Coastguard Worker struct stat st;
387*6a54128fSAndroid Build Coastguard Worker
388*6a54128fSAndroid Build Coastguard Worker if (!cache)
389*6a54128fSAndroid Build Coastguard Worker return;
390*6a54128fSAndroid Build Coastguard Worker
391*6a54128fSAndroid Build Coastguard Worker /*
392*6a54128fSAndroid Build Coastguard Worker * If the file doesn't exist, then we just return an empty
393*6a54128fSAndroid Build Coastguard Worker * struct so that the cache can be populated.
394*6a54128fSAndroid Build Coastguard Worker */
395*6a54128fSAndroid Build Coastguard Worker if ((fd = open(cache->bic_filename, O_RDONLY)) < 0)
396*6a54128fSAndroid Build Coastguard Worker return;
397*6a54128fSAndroid Build Coastguard Worker if (fstat(fd, &st) < 0)
398*6a54128fSAndroid Build Coastguard Worker goto errout;
399*6a54128fSAndroid Build Coastguard Worker if ((st.st_mtime == cache->bic_ftime) ||
400*6a54128fSAndroid Build Coastguard Worker (cache->bic_flags & BLKID_BIC_FL_CHANGED)) {
401*6a54128fSAndroid Build Coastguard Worker DBG(DEBUG_CACHE, printf("skipping re-read of %s\n",
402*6a54128fSAndroid Build Coastguard Worker cache->bic_filename));
403*6a54128fSAndroid Build Coastguard Worker goto errout;
404*6a54128fSAndroid Build Coastguard Worker }
405*6a54128fSAndroid Build Coastguard Worker
406*6a54128fSAndroid Build Coastguard Worker DBG(DEBUG_CACHE, printf("reading cache file %s\n",
407*6a54128fSAndroid Build Coastguard Worker cache->bic_filename));
408*6a54128fSAndroid Build Coastguard Worker
409*6a54128fSAndroid Build Coastguard Worker file = fdopen(fd, "r");
410*6a54128fSAndroid Build Coastguard Worker if (!file)
411*6a54128fSAndroid Build Coastguard Worker goto errout;
412*6a54128fSAndroid Build Coastguard Worker
413*6a54128fSAndroid Build Coastguard Worker while (fgets(buf, sizeof(buf), file)) {
414*6a54128fSAndroid Build Coastguard Worker blkid_dev dev;
415*6a54128fSAndroid Build Coastguard Worker unsigned int end;
416*6a54128fSAndroid Build Coastguard Worker
417*6a54128fSAndroid Build Coastguard Worker lineno++;
418*6a54128fSAndroid Build Coastguard Worker if (buf[0] == 0)
419*6a54128fSAndroid Build Coastguard Worker continue;
420*6a54128fSAndroid Build Coastguard Worker end = strlen(buf) - 1;
421*6a54128fSAndroid Build Coastguard Worker /* Continue reading next line if it ends with a backslash */
422*6a54128fSAndroid Build Coastguard Worker while (buf[end] == '\\' && end < sizeof(buf) - 2 &&
423*6a54128fSAndroid Build Coastguard Worker fgets(buf + end, sizeof(buf) - end, file)) {
424*6a54128fSAndroid Build Coastguard Worker end = strlen(buf) - 1;
425*6a54128fSAndroid Build Coastguard Worker lineno++;
426*6a54128fSAndroid Build Coastguard Worker }
427*6a54128fSAndroid Build Coastguard Worker
428*6a54128fSAndroid Build Coastguard Worker if (blkid_parse_line(cache, &dev, buf) < 0) {
429*6a54128fSAndroid Build Coastguard Worker DBG(DEBUG_READ,
430*6a54128fSAndroid Build Coastguard Worker printf("blkid: bad format on line %d\n", lineno));
431*6a54128fSAndroid Build Coastguard Worker continue;
432*6a54128fSAndroid Build Coastguard Worker }
433*6a54128fSAndroid Build Coastguard Worker }
434*6a54128fSAndroid Build Coastguard Worker fclose(file);
435*6a54128fSAndroid Build Coastguard Worker
436*6a54128fSAndroid Build Coastguard Worker /*
437*6a54128fSAndroid Build Coastguard Worker * Initially we do not need to write out the cache file.
438*6a54128fSAndroid Build Coastguard Worker */
439*6a54128fSAndroid Build Coastguard Worker cache->bic_flags &= ~BLKID_BIC_FL_CHANGED;
440*6a54128fSAndroid Build Coastguard Worker cache->bic_ftime = st.st_mtime;
441*6a54128fSAndroid Build Coastguard Worker
442*6a54128fSAndroid Build Coastguard Worker return;
443*6a54128fSAndroid Build Coastguard Worker errout:
444*6a54128fSAndroid Build Coastguard Worker close(fd);
445*6a54128fSAndroid Build Coastguard Worker return;
446*6a54128fSAndroid Build Coastguard Worker }
447*6a54128fSAndroid Build Coastguard Worker
448*6a54128fSAndroid Build Coastguard Worker #ifdef TEST_PROGRAM
debug_dump_dev(blkid_dev dev)449*6a54128fSAndroid Build Coastguard Worker static void debug_dump_dev(blkid_dev dev)
450*6a54128fSAndroid Build Coastguard Worker {
451*6a54128fSAndroid Build Coastguard Worker struct list_head *p;
452*6a54128fSAndroid Build Coastguard Worker
453*6a54128fSAndroid Build Coastguard Worker if (!dev) {
454*6a54128fSAndroid Build Coastguard Worker printf(" dev: NULL\n");
455*6a54128fSAndroid Build Coastguard Worker return;
456*6a54128fSAndroid Build Coastguard Worker }
457*6a54128fSAndroid Build Coastguard Worker
458*6a54128fSAndroid Build Coastguard Worker printf(" dev: name = %s\n", dev->bid_name);
459*6a54128fSAndroid Build Coastguard Worker printf(" dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno);
460*6a54128fSAndroid Build Coastguard Worker printf(" dev: TIME=\"%lld\"\n", (long long)dev->bid_time);
461*6a54128fSAndroid Build Coastguard Worker printf(" dev: PRI=\"%d\"\n", dev->bid_pri);
462*6a54128fSAndroid Build Coastguard Worker printf(" dev: flags = 0x%08X\n", dev->bid_flags);
463*6a54128fSAndroid Build Coastguard Worker
464*6a54128fSAndroid Build Coastguard Worker list_for_each(p, &dev->bid_tags) {
465*6a54128fSAndroid Build Coastguard Worker blkid_tag tag = list_entry(p, struct blkid_struct_tag, bit_tags);
466*6a54128fSAndroid Build Coastguard Worker if (tag)
467*6a54128fSAndroid Build Coastguard Worker printf(" tag: %s=\"%s\"\n", tag->bit_name,
468*6a54128fSAndroid Build Coastguard Worker tag->bit_val);
469*6a54128fSAndroid Build Coastguard Worker else
470*6a54128fSAndroid Build Coastguard Worker printf(" tag: NULL\n");
471*6a54128fSAndroid Build Coastguard Worker }
472*6a54128fSAndroid Build Coastguard Worker printf("\n");
473*6a54128fSAndroid Build Coastguard Worker }
474*6a54128fSAndroid Build Coastguard Worker
main(int argc,char ** argv)475*6a54128fSAndroid Build Coastguard Worker int main(int argc, char**argv)
476*6a54128fSAndroid Build Coastguard Worker {
477*6a54128fSAndroid Build Coastguard Worker blkid_cache cache = NULL;
478*6a54128fSAndroid Build Coastguard Worker int ret;
479*6a54128fSAndroid Build Coastguard Worker
480*6a54128fSAndroid Build Coastguard Worker blkid_debug_mask = DEBUG_ALL;
481*6a54128fSAndroid Build Coastguard Worker if (argc > 2) {
482*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "Usage: %s [filename]\n"
483*6a54128fSAndroid Build Coastguard Worker "Test parsing of the cache (filename)\n", argv[0]);
484*6a54128fSAndroid Build Coastguard Worker exit(1);
485*6a54128fSAndroid Build Coastguard Worker }
486*6a54128fSAndroid Build Coastguard Worker if ((ret = blkid_get_cache(&cache, argv[1])) < 0)
487*6a54128fSAndroid Build Coastguard Worker fprintf(stderr, "error %d reading cache file %s\n", ret,
488*6a54128fSAndroid Build Coastguard Worker argv[1] ? argv[1] : BLKID_CACHE_FILE);
489*6a54128fSAndroid Build Coastguard Worker
490*6a54128fSAndroid Build Coastguard Worker blkid_put_cache(cache);
491*6a54128fSAndroid Build Coastguard Worker
492*6a54128fSAndroid Build Coastguard Worker return ret;
493*6a54128fSAndroid Build Coastguard Worker }
494*6a54128fSAndroid Build Coastguard Worker #endif
495