Upload Tizen:Base source
[framework/base/util-linux-ng.git] / shlibs / blkid / src / verify.c
1 /*
2  * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
3  *
4  * This file may be redistributed under the terms of the
5  * GNU Lesser General Public License.
6  */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include <time.h>
14 #include <sys/types.h>
15 #ifdef HAVE_SYS_STAT_H
16 #include <sys/stat.h>
17 #endif
18 #ifdef HAVE_ERRNO_H
19 #include <errno.h>
20 #endif
21 #include "blkidP.h"
22
23 static void blkid_probe_to_tags(blkid_probe pr, blkid_dev dev)
24 {
25         const char *data;
26         const char *name;
27         int nvals, n;
28         size_t len;
29
30         nvals = blkid_probe_numof_values(pr);
31
32         for (n = 0; n < nvals; n++) {
33                 if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
34                         blkid_set_tag(dev, name, data, len);
35         }
36 }
37
38 /*
39  * Verify that the data in dev is consistent with what is on the actual
40  * block device (using the devname field only).  Normally this will be
41  * called when finding items in the cache, but for long running processes
42  * is also desirable to revalidate an item before use.
43  *
44  * If we are unable to revalidate the data, we return the old data and
45  * do not set the BLKID_BID_FL_VERIFIED flag on it.
46  */
47 blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
48 {
49         struct stat st;
50         time_t diff, now;
51         char *fltr[2];
52         int fd;
53
54         if (!dev)
55                 return NULL;
56
57         now = time(0);
58         diff = now - dev->bid_time;
59
60         if (stat(dev->bid_name, &st) < 0) {
61                 DBG(DEBUG_PROBE,
62                     printf("blkid_verify: error %s (%d) while "
63                            "trying to stat %s\n", strerror(errno), errno,
64                            dev->bid_name));
65         open_err:
66                 if ((errno == EPERM) || (errno == EACCES) || (errno == ENOENT)) {
67                         /* We don't have read permission, just return cache data. */
68                         DBG(DEBUG_PROBE, printf("returning unverified data for %s\n",
69                                                 dev->bid_name));
70                         return dev;
71                 }
72                 blkid_free_dev(dev);
73                 return NULL;
74         }
75
76         if ((now >= dev->bid_time) &&
77             (st.st_mtime <= dev->bid_time) &&
78             ((diff < BLKID_PROBE_MIN) ||
79              (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
80               diff < BLKID_PROBE_INTERVAL)))
81                 return dev;
82
83         DBG(DEBUG_PROBE,
84             printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t"
85                    "time since last check %lu)\n",
86                    dev->bid_name, (unsigned long)dev->bid_time,
87                    (unsigned long)st.st_mtime, (unsigned long)diff));
88
89
90         if (!cache->probe) {
91                 cache->probe = blkid_new_probe();
92                 if (!cache->probe) {
93                         blkid_free_dev(dev);
94                         return NULL;
95                 }
96         }
97
98         fd = open(dev->bid_name, O_RDONLY);
99         if (fd < 0) {
100                 DBG(DEBUG_PROBE, printf("blkid_verify: error %s (%d) while "
101                                         "opening %s\n", strerror(errno), errno,
102                                         dev->bid_name));
103                 goto open_err;
104         }
105
106         if (blkid_probe_set_device(cache->probe, fd, 0, 0)) {
107                 /* failed to read the device */
108                 close(fd);
109                 blkid_free_dev(dev);
110                 return NULL;
111         }
112
113         blkid_probe_set_request(cache->probe,
114                 BLKID_PROBREQ_LABEL | BLKID_PROBREQ_UUID |
115                 BLKID_PROBREQ_TYPE | BLKID_PROBREQ_SECTYPE);
116
117         /*
118          * If we already know the type, then try that first.
119          */
120         if (dev->bid_type) {
121                 blkid_tag_iterate iter;
122                 const char *type, *value;
123
124                 fltr[0] = dev->bid_type;
125                 fltr[1] = NULL;
126
127                 blkid_probe_filter_types(cache->probe,
128                                 BLKID_FLTR_ONLYIN, fltr);
129
130                 if (!blkid_do_probe(cache->probe))
131                         goto found_type;
132                 blkid_probe_invert_filter(cache->probe);
133
134                 /*
135                  * Zap the device filesystem information and try again
136                  */
137                 DBG(DEBUG_PROBE,
138                     printf("previous fs type %s not valid, "
139                            "trying full probe\n", dev->bid_type));
140                 iter = blkid_tag_iterate_begin(dev);
141                 while (blkid_tag_next(iter, &type, &value) == 0)
142                         blkid_set_tag(dev, type, 0, 0);
143                 blkid_tag_iterate_end(iter);
144         }
145
146         /*
147          * Probe for all types.
148          */
149         if (blkid_do_safeprobe(cache->probe)) {
150                 /* found nothing or error */
151                 blkid_free_dev(dev);
152                 dev = NULL;
153         }
154
155 found_type:
156         if (dev) {
157                 dev->bid_devno = st.st_rdev;
158                 dev->bid_time = time(0);
159                 dev->bid_flags |= BLKID_BID_FL_VERIFIED;
160                 cache->bic_flags |= BLKID_BIC_FL_CHANGED;
161
162                 blkid_probe_to_tags(cache->probe, dev);
163
164                 DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n",
165                            dev->bid_name, (long long)st.st_rdev, dev->bid_type));
166         }
167
168         blkid_reset_probe(cache->probe);
169         blkid_probe_reset_filter(cache->probe);
170         close(fd);
171         return dev;
172 }
173
174 #ifdef TEST_PROGRAM
175 int main(int argc, char **argv)
176 {
177         blkid_dev dev;
178         blkid_cache cache;
179         int ret;
180
181         if (argc != 2) {
182                 fprintf(stderr, "Usage: %s device\n"
183                         "Probe a single device to determine type\n", argv[0]);
184                 exit(1);
185         }
186         if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
187                 fprintf(stderr, "%s: error creating cache (%d)\n",
188                         argv[0], ret);
189                 exit(1);
190         }
191         dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL);
192         if (!dev) {
193                 printf("%s: %s has an unsupported type\n", argv[0], argv[1]);
194                 return (1);
195         }
196         printf("TYPE='%s'\n", dev->bid_type ? dev->bid_type : "(null)");
197         if (dev->bid_label)
198                 printf("LABEL='%s'\n", dev->bid_label);
199         if (dev->bid_uuid)
200                 printf("UUID='%s'\n", dev->bid_uuid);
201
202         blkid_free_dev(dev);
203         return (0);
204 }
205 #endif