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

« back to all changes in this revision

Viewing changes to shlibs/blkid/src/evaluate.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
 
 * evaluate.c - very high-level API to evaluate LABELs or UUIDs
3
 
 *
4
 
 * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
5
 
 *
6
 
 * This file may be redistributed under the terms of the
7
 
 * GNU Lesser General Public License.
8
 
 */
9
 
#include <stdio.h>
10
 
#include <string.h>
11
 
#include <stdlib.h>
12
 
#include <unistd.h>
13
 
#include <fcntl.h>
14
 
#include <ctype.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 <stdint.h>
23
 
#include <stdarg.h>
24
 
 
25
 
#include "pathnames.h"
26
 
#include "canonicalize.h"
27
 
 
28
 
#include "blkidP.h"
29
 
 
30
 
/**
31
 
 * SECTION:evaluate
32
 
 * @title: Tags evaluation
33
 
 * @short_description: top-level API for LABEL and UUID evaluation.
34
 
 *
35
 
 * This API provides very simple and portable way how evaluate LABEL and UUID
36
 
 * tags.  The blkid_evaluate_tag() works on 2.4 and 2.6 systems and on systems
37
 
 * with or without udev. Currently, the libblkid library supports "udev" and
38
 
 * "scan" methods. The "udev" method uses udev /dev/disk/by-* symlinks and the
39
 
 * "scan" method scans all block devices from the /proc/partitions file. The
40
 
 * evaluation could be controlled by the /etc/blkid.conf config file. The
41
 
 * default is to try "udev" and then "scan" method.
42
 
 *
43
 
 * The blkid_evaluate_tag() also automatically informs udevd when an obsolete
44
 
 * /dev/disk/by-* symlink is detected.
45
 
 *
46
 
 * If you are not sure how translate LABEL or UUID to the device name use this
47
 
 * API.
48
 
 */
49
 
 
50
 
/* returns zero when the device has NAME=value (LABEL/UUID) */
51
 
static int verify_tag(const char *devname, const char *name, const char *value)
52
 
{
53
 
        blkid_probe pr;
54
 
        int fd = -1, rc = -1;
55
 
        size_t len;
56
 
        const char *data;
57
 
        int errsv = 0;
58
 
 
59
 
        pr = blkid_new_probe();
60
 
        if (!pr)
61
 
                return -1;
62
 
 
63
 
        blkid_probe_enable_superblocks(pr, TRUE);
64
 
        blkid_probe_set_superblocks_flags(pr,
65
 
                        BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID);
66
 
 
67
 
        fd = open(devname, O_RDONLY);
68
 
        if (fd < 0) {
69
 
                errsv = errno;
70
 
                goto done;
71
 
        }
72
 
        if (blkid_probe_set_device(pr, fd, 0, 0))
73
 
                goto done;
74
 
        rc = blkid_do_safeprobe(pr);
75
 
        if (rc)
76
 
                goto done;
77
 
        rc = blkid_probe_lookup_value(pr, name, &data, &len);
78
 
        if (!rc)
79
 
                rc = memcmp(value, data, len);
80
 
done:
81
 
        DBG(DEBUG_EVALUATE, printf("%s: %s verification %s\n",
82
 
                        devname, name, rc == 0 ? "PASS" : "FAILED"));
83
 
        if (fd >= 0)
84
 
                close(fd);
85
 
        blkid_free_probe(pr);
86
 
 
87
 
        /* for non-root users we use unverified udev links */
88
 
        return errsv == EACCES ? 0 : rc;
89
 
}
90
 
 
91
 
/**
92
 
 * blkid_send_uevent:
93
 
 * @devname: absolute path to the device
94
 
 *
95
 
 * Returns: -1 in case of failure, or 0 on success.
96
 
 */
97
 
int blkid_send_uevent(const char *devname, const char *action)
98
 
{
99
 
        char uevent[PATH_MAX];
100
 
        struct stat st;
101
 
        FILE *f;
102
 
        int rc = -1;
103
 
 
104
 
        DBG(DEBUG_EVALUATE, printf("%s: uevent '%s' requested\n", devname, action));
105
 
 
106
 
        if (!devname || !action)
107
 
                return -1;
108
 
        if (stat(devname, &st) || !S_ISBLK(st.st_mode))
109
 
                return -1;
110
 
 
111
 
        snprintf(uevent, sizeof(uevent), "/sys/dev/block/%d:%d/uevent",
112
 
                        major(st.st_rdev), minor(st.st_rdev));
113
 
 
114
 
        f = fopen(uevent, "w");
115
 
        if (f) {
116
 
                rc = 0;
117
 
                if (fputs(action, f) >= 0)
118
 
                        rc = 0;
119
 
                fclose(f);
120
 
        }
121
 
        DBG(DEBUG_EVALUATE, printf("%s: send uevent %s\n",
122
 
                        uevent, rc == 0 ? "SUCCES" : "FAILED"));
123
 
        return rc;
124
 
}
125
 
 
126
 
static char *evaluate_by_udev(const char *token, const char *value, int uevent)
127
 
{
128
 
        char dev[PATH_MAX];
129
 
        char *path = NULL;
130
 
        size_t len;
131
 
        struct stat st;
132
 
 
133
 
        DBG(DEBUG_EVALUATE,
134
 
            printf("evaluating by udev %s=%s\n", token, value));
135
 
 
136
 
        if (!strcmp(token, "UUID"))
137
 
                strcpy(dev, _PATH_DEV_BYUUID "/");
138
 
        else if (!strcmp(token, "LABEL"))
139
 
                strcpy(dev, _PATH_DEV_BYLABEL "/");
140
 
        else {
141
 
                DBG(DEBUG_EVALUATE,
142
 
                    printf("unsupported token %s\n", token));
143
 
                return NULL;    /* unsupported tag */
144
 
        }
145
 
 
146
 
        len = strlen(dev);
147
 
        if (blkid_encode_string(value, &dev[len], sizeof(dev) - len) != 0)
148
 
                return NULL;
149
 
 
150
 
        DBG(DEBUG_EVALUATE,
151
 
            printf("expected udev link: %s\n", dev));
152
 
 
153
 
        if (stat(dev, &st))
154
 
                goto failed;    /* link or device does not exist */
155
 
 
156
 
        if (!S_ISBLK(st.st_mode))
157
 
                return NULL;
158
 
 
159
 
        path = canonicalize_path(dev);
160
 
        if (!path)
161
 
                return NULL;
162
 
 
163
 
        if (verify_tag(path, token, value))
164
 
                goto failed;
165
 
        return path;
166
 
 
167
 
failed:
168
 
        DBG(DEBUG_EVALUATE, printf("failed to evaluate by udev\n"));
169
 
 
170
 
        if (uevent && path)
171
 
                blkid_send_uevent(path, "change");
172
 
        free(path);
173
 
        return NULL;
174
 
}
175
 
 
176
 
static char *evaluate_by_scan(const char *token, const char *value,
177
 
                blkid_cache *cache, struct blkid_config *conf)
178
 
{
179
 
        blkid_cache c = cache ? *cache : NULL;
180
 
        char *res;
181
 
 
182
 
        DBG(DEBUG_EVALUATE,
183
 
            printf("evaluating by blkid scan %s=%s\n", token, value));
184
 
 
185
 
        if (!c) {
186
 
                char *cachefile = blkid_get_cache_filename(conf);
187
 
                blkid_get_cache(&c, cachefile);
188
 
                free(cachefile);
189
 
        }
190
 
        if (!c)
191
 
                return NULL;
192
 
 
193
 
        res = blkid_get_devname(c, token, value);
194
 
 
195
 
        if (cache)
196
 
                *cache = c;
197
 
        else
198
 
                blkid_put_cache(c);
199
 
 
200
 
        return res;
201
 
}
202
 
 
203
 
/**
204
 
 * blkid_evaluate_tag:
205
 
 * @token: token name (e.g "LABEL" or "UUID")
206
 
 * @value: token data
207
 
 * @cache: pointer to cache (or NULL when you don't want to re-use the cache)
208
 
 *
209
 
 * Returns: allocated string with a device name.
210
 
 */
211
 
char *blkid_evaluate_tag(const char *token, const char *value, blkid_cache *cache)
212
 
{
213
 
        struct blkid_config *conf = NULL;
214
 
        char *t = NULL, *v = NULL;
215
 
        char *ret = NULL;
216
 
        int i;
217
 
 
218
 
        if (!token)
219
 
                return NULL;
220
 
 
221
 
        if (!cache || !*cache)
222
 
                blkid_init_debug(0);
223
 
 
224
 
        DBG(DEBUG_EVALUATE,
225
 
            printf("evaluating  %s%s%s\n", token, value ? "=" : "",
226
 
                   value ? value : ""));
227
 
 
228
 
        if (!value) {
229
 
                if (!strchr(token, '=')) {
230
 
                        ret = blkid_strdup(token);
231
 
                        goto out;
232
 
                }
233
 
                blkid_parse_tag_string(token, &t, &v);
234
 
                if (!t || !v)
235
 
                        goto out;
236
 
                token = t;
237
 
                value = v;
238
 
        }
239
 
 
240
 
        conf = blkid_read_config(NULL);
241
 
        if (!conf)
242
 
                goto out;
243
 
 
244
 
        for (i = 0; i < conf->nevals; i++) {
245
 
                if (conf->eval[i] == BLKID_EVAL_UDEV)
246
 
                        ret = evaluate_by_udev(token, value, conf->uevent);
247
 
                else if (conf->eval[i] == BLKID_EVAL_SCAN)
248
 
                        ret = evaluate_by_scan(token, value, cache, conf);
249
 
                if (ret)
250
 
                        break;
251
 
        }
252
 
 
253
 
        DBG(DEBUG_EVALUATE,
254
 
            printf("%s=%s evaluated as %s\n", token, value, ret));
255
 
out:
256
 
        blkid_free_config(conf);
257
 
        free(t);
258
 
        free(v);
259
 
        return ret;
260
 
}
261
 
 
262
 
#ifdef TEST_PROGRAM
263
 
int main(int argc, char *argv[])
264
 
{
265
 
        blkid_cache cache = NULL;
266
 
        char *res;
267
 
 
268
 
        if (argc < 3) {
269
 
                fprintf(stderr, "usage: %s <token> <value>\n", argv[0]);
270
 
                return EXIT_FAILURE;
271
 
        }
272
 
 
273
 
        blkid_init_debug(0);
274
 
 
275
 
        res = blkid_evaluate_tag(argv[1], argv[2], &cache);
276
 
        if (res)
277
 
                printf("%s\n", res);
278
 
        if (cache)
279
 
                blkid_put_cache(cache);
280
 
 
281
 
        return res ? EXIT_SUCCESS : EXIT_FAILURE;
282
 
}
283
 
#endif