~ubuntu-branches/ubuntu/trusty/util-linux/trusty-proposed

« back to all changes in this revision

Viewing changes to libblkid/src/verify.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2011-11-03 15:38:23 UTC
  • mto: (4.5.5 sid) (1.6.4)
  • mto: This revision was merged to the branch mainline in revision 85.
  • Revision ID: package-import@ubuntu.com-20111103153823-10sx16jprzxlhkqf
ImportĀ upstreamĀ versionĀ 2.20.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/time.h>
 
15
#include <sys/types.h>
 
16
#ifdef HAVE_SYS_STAT_H
 
17
#include <sys/stat.h>
 
18
#endif
 
19
#ifdef HAVE_ERRNO_H
 
20
#include <errno.h>
 
21
#endif
 
22
#include "blkidP.h"
 
23
 
 
24
static void blkid_probe_to_tags(blkid_probe pr, blkid_dev dev)
 
25
{
 
26
        const char *data;
 
27
        const char *name;
 
28
        int nvals, n;
 
29
        size_t len;
 
30
 
 
31
        nvals = blkid_probe_numof_values(pr);
 
32
 
 
33
        for (n = 0; n < nvals; n++) {
 
34
                if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
 
35
                        blkid_set_tag(dev, name, data, len);
 
36
        }
 
37
}
 
38
 
 
39
/*
 
40
 * Verify that the data in dev is consistent with what is on the actual
 
41
 * block device (using the devname field only).  Normally this will be
 
42
 * called when finding items in the cache, but for long running processes
 
43
 * is also desirable to revalidate an item before use.
 
44
 *
 
45
 * If we are unable to revalidate the data, we return the old data and
 
46
 * do not set the BLKID_BID_FL_VERIFIED flag on it.
 
47
 */
 
48
blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
 
49
{
 
50
        struct stat st;
 
51
        time_t diff, now;
 
52
        char *fltr[2];
 
53
        int fd;
 
54
 
 
55
        if (!dev)
 
56
                return NULL;
 
57
 
 
58
        now = time(0);
 
59
        diff = now - dev->bid_time;
 
60
 
 
61
        if (stat(dev->bid_name, &st) < 0) {
 
62
                DBG(DEBUG_PROBE,
 
63
                    printf("blkid_verify: error %s (%d) while "
 
64
                           "trying to stat %s\n", strerror(errno), errno,
 
65
                           dev->bid_name));
 
66
        open_err:
 
67
                if ((errno == EPERM) || (errno == EACCES) || (errno == ENOENT)) {
 
68
                        /* We don't have read permission, just return cache data. */
 
69
                        DBG(DEBUG_PROBE, printf("returning unverified data for %s\n",
 
70
                                                dev->bid_name));
 
71
                        return dev;
 
72
                }
 
73
                blkid_free_dev(dev);
 
74
                return NULL;
 
75
        }
 
76
 
 
77
        if (now >= dev->bid_time &&
 
78
#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
 
79
            (st.st_mtime < dev->bid_time ||
 
80
                (st.st_mtime == dev->bid_time &&
 
81
                 st.st_mtim.tv_nsec / 1000 <= dev->bid_utime)) &&
 
82
#else
 
83
            st.st_mtime <= dev->bid_time &&
 
84
#endif
 
85
            (diff < BLKID_PROBE_MIN ||
 
86
                (dev->bid_flags & BLKID_BID_FL_VERIFIED &&
 
87
                 diff < BLKID_PROBE_INTERVAL)))
 
88
                return dev;
 
89
 
 
90
#ifndef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
 
91
        DBG(DEBUG_PROBE,
 
92
            printf("need to revalidate %s (cache time %lu, stat time %lu,\n\t"
 
93
                   "time since last check %lu)\n",
 
94
                   dev->bid_name, (unsigned long)dev->bid_time,
 
95
                   (unsigned long)st.st_mtime, (unsigned long)diff));
 
96
#else
 
97
        DBG(DEBUG_PROBE,
 
98
            printf("need to revalidate %s (cache time %lu.%lu, stat time %lu.%lu,\n\t"
 
99
                   "time since last check %lu)\n",
 
100
                   dev->bid_name,
 
101
                   (unsigned long)dev->bid_time, (unsigned long)dev->bid_utime,
 
102
                   (unsigned long)st.st_mtime, (unsigned long)st.st_mtim.tv_nsec / 1000,
 
103
                   (unsigned long)diff));
 
104
#endif
 
105
 
 
106
        if (!cache->probe) {
 
107
                cache->probe = blkid_new_probe();
 
108
                if (!cache->probe) {
 
109
                        blkid_free_dev(dev);
 
110
                        return NULL;
 
111
                }
 
112
        }
 
113
 
 
114
        fd = open(dev->bid_name, O_RDONLY);
 
115
        if (fd < 0) {
 
116
                DBG(DEBUG_PROBE, printf("blkid_verify: error %s (%d) while "
 
117
                                        "opening %s\n", strerror(errno), errno,
 
118
                                        dev->bid_name));
 
119
                goto open_err;
 
120
        }
 
121
 
 
122
        if (blkid_probe_set_device(cache->probe, fd, 0, 0)) {
 
123
                /* failed to read the device */
 
124
                close(fd);
 
125
                blkid_free_dev(dev);
 
126
                return NULL;
 
127
        }
 
128
 
 
129
        blkid_probe_enable_superblocks(cache->probe, TRUE);
 
130
 
 
131
        blkid_probe_set_superblocks_flags(cache->probe,
 
132
                BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID |
 
133
                BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE);
 
134
 
 
135
        /*
 
136
         * If we already know the type, then try that first.
 
137
         */
 
138
        if (dev->bid_type) {
 
139
                blkid_tag_iterate iter;
 
140
                const char *type, *value;
 
141
 
 
142
                fltr[0] = dev->bid_type;
 
143
                fltr[1] = NULL;
 
144
 
 
145
                blkid_probe_filter_superblocks_type(cache->probe,
 
146
                                BLKID_FLTR_ONLYIN, fltr);
 
147
 
 
148
                if (!blkid_do_probe(cache->probe))
 
149
                        goto found_type;
 
150
                blkid_probe_invert_superblocks_filter(cache->probe);
 
151
 
 
152
                /*
 
153
                 * Zap the device filesystem information and try again
 
154
                 */
 
155
                DBG(DEBUG_PROBE,
 
156
                    printf("previous fs type %s not valid, "
 
157
                           "trying full probe\n", dev->bid_type));
 
158
                iter = blkid_tag_iterate_begin(dev);
 
159
                while (blkid_tag_next(iter, &type, &value) == 0)
 
160
                        blkid_set_tag(dev, type, 0, 0);
 
161
                blkid_tag_iterate_end(iter);
 
162
        }
 
163
 
 
164
        /*
 
165
         * Probe for all types.
 
166
         */
 
167
        if (blkid_do_safeprobe(cache->probe)) {
 
168
                /* found nothing or error */
 
169
                blkid_free_dev(dev);
 
170
                dev = NULL;
 
171
        }
 
172
 
 
173
found_type:
 
174
        if (dev) {
 
175
#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
 
176
                struct timeval tv;
 
177
                if (!gettimeofday(&tv, NULL)) {
 
178
                        dev->bid_time = tv.tv_sec;
 
179
                        dev->bid_utime = tv.tv_usec;
 
180
                } else
 
181
#endif
 
182
                        dev->bid_time = time(0);
 
183
 
 
184
                dev->bid_devno = st.st_rdev;
 
185
                dev->bid_flags |= BLKID_BID_FL_VERIFIED;
 
186
                cache->bic_flags |= BLKID_BIC_FL_CHANGED;
 
187
 
 
188
                blkid_probe_to_tags(cache->probe, dev);
 
189
 
 
190
                DBG(DEBUG_PROBE, printf("%s: devno 0x%04llx, type %s\n",
 
191
                           dev->bid_name, (long long)st.st_rdev, dev->bid_type));
 
192
        }
 
193
 
 
194
        blkid_reset_probe(cache->probe);
 
195
        blkid_probe_reset_superblocks_filter(cache->probe);
 
196
        close(fd);
 
197
        return dev;
 
198
}
 
199
 
 
200
#ifdef TEST_PROGRAM
 
201
int main(int argc, char **argv)
 
202
{
 
203
        blkid_dev dev;
 
204
        blkid_cache cache;
 
205
        int ret;
 
206
 
 
207
        if (argc != 2) {
 
208
                fprintf(stderr, "Usage: %s device\n"
 
209
                        "Probe a single device to determine type\n", argv[0]);
 
210
                exit(1);
 
211
        }
 
212
        if ((ret = blkid_get_cache(&cache, "/dev/null")) != 0) {
 
213
                fprintf(stderr, "%s: error creating cache (%d)\n",
 
214
                        argv[0], ret);
 
215
                exit(1);
 
216
        }
 
217
        dev = blkid_get_dev(cache, argv[1], BLKID_DEV_NORMAL);
 
218
        if (!dev) {
 
219
                printf("%s: %s has an unsupported type\n", argv[0], argv[1]);
 
220
                return (1);
 
221
        }
 
222
        printf("TYPE='%s'\n", dev->bid_type ? dev->bid_type : "(null)");
 
223
        if (dev->bid_label)
 
224
                printf("LABEL='%s'\n", dev->bid_label);
 
225
        if (dev->bid_uuid)
 
226
                printf("UUID='%s'\n", dev->bid_uuid);
 
227
 
 
228
        blkid_free_dev(dev);
 
229
        return (0);
 
230
}
 
231
#endif