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

« back to all changes in this revision

Viewing changes to shlibs/blkid/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