2 * evaluate.c - very high-level API to evaluate LABELs or UUIDs
4 * This is simular to blkid_get_devname() from resolve.c, but this
5 * API supports udev /dev/disk/by-{label,uuid} links.
7 * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
9 * This file may be redistributed under the terms of the
10 * GNU Lesser General Public License.
19 #include <sys/types.h>
20 #ifdef HAVE_SYS_STAT_H
23 #ifdef HAVE_SYS_MKDEV_H
24 #include <sys/mkdev.h>
32 #include "pathnames.h"
33 #include "canonicalize.h"
38 /* returns zero when the device has NAME=value (LABEL/UUID) */
39 static int verify_tag(const char *devname, const char *name, const char *value)
47 pr = blkid_new_probe();
51 blkid_probe_set_request(pr, BLKID_PROBREQ_LABEL | BLKID_PROBREQ_UUID);
53 fd = open(devname, O_RDONLY);
58 if (blkid_probe_set_device(pr, fd, 0, 0))
60 rc = blkid_do_safeprobe(pr);
63 rc = blkid_probe_lookup_value(pr, name, &data, &len);
65 rc = memcmp(value, data, len);
67 DBG(DEBUG_EVALUATE, printf("%s: %s verification %s\n",
68 devname, name, rc == 0 ? "PASS" : "FAILED"));
73 /* for non-root users we use unverified udev links */
74 return errsv == EACCES ? 0 : rc;
79 * @devname: absolute path to the device
81 * Returns -1 in case of failure, or 0 on success.
83 int blkid_send_uevent(const char *devname, const char *action)
85 char uevent[PATH_MAX];
90 DBG(DEBUG_EVALUATE, printf("%s: uevent '%s' requested\n", devname, action));
92 if (!devname || !action)
94 if (stat(devname, &st) || !S_ISBLK(st.st_mode))
97 snprintf(uevent, sizeof(uevent), "/sys/dev/block/%d:%d/uevent",
98 major(st.st_rdev), minor(st.st_rdev));
100 f = fopen(uevent, "w");
103 if (fputs(action, f) >= 0)
107 DBG(DEBUG_EVALUATE, printf("%s: send uevent %s\n",
108 uevent, rc == 0 ? "SUCCES" : "FAILED"));
112 static char *evaluate_by_udev(const char *token, const char *value, int uevent)
120 printf("evaluating by udev %s=%s\n", token, value));
122 if (!strcmp(token, "UUID"))
123 strcpy(dev, _PATH_DEV_BYUUID "/");
124 else if (!strcmp(token, "LABEL"))
125 strcpy(dev, _PATH_DEV_BYLABEL "/");
128 printf("unsupported token %s\n", token));
129 return NULL; /* unsupported tag */
133 if (blkid_encode_string(value, &dev[len], sizeof(dev) - len) != 0)
137 printf("expected udev link: %s\n", dev));
140 goto failed; /* link or device does not exist */
142 if (!S_ISBLK(st.st_mode))
145 path = canonicalize_path(dev);
149 if (verify_tag(path, token, value))
154 DBG(DEBUG_EVALUATE, printf("failed to evaluate by udev\n"));
157 blkid_send_uevent(path, "change");
162 static char *evaluate_by_scan(const char *token, const char *value,
163 blkid_cache *cache, struct blkid_config *conf)
165 blkid_cache c = cache ? *cache : NULL;
169 printf("evaluating by blkid scan %s=%s\n", token, value));
172 char *cachefile = blkid_get_cache_filename(conf);
173 blkid_get_cache(&c, cachefile);
179 res = blkid_get_devname(c, token, value);
190 * blkid_evaluate_tag:
191 * @token: token name (e.g "LABEL" or "UUID")
193 * @cache: pointer to cache (or NULL when you don't want to re-use the cache)
195 * Returns allocated string with device name.
197 char *blkid_evaluate_tag(const char *token, const char *value, blkid_cache *cache)
199 struct blkid_config *conf = NULL;
200 char *t = NULL, *v = NULL;
207 if (!cache || !*cache)
211 printf("evaluating %s%s%s\n", token, value ? "=" : "",
212 value ? value : ""));
215 if (!strchr(token, '=')) {
216 ret = blkid_strdup(token);
219 blkid_parse_tag_string(token, &t, &v);
226 conf = blkid_read_config(NULL);
230 for (i = 0; i < conf->nevals; i++) {
231 if (conf->eval[i] == BLKID_EVAL_UDEV)
232 ret = evaluate_by_udev(token, value, conf->uevent);
233 else if (conf->eval[i] == BLKID_EVAL_SCAN)
234 ret = evaluate_by_scan(token, value, cache, conf);
240 printf("%s=%s evaluated as %s\n", token, value, ret));
242 blkid_free_config(conf);
249 int main(int argc, char *argv[])
251 blkid_cache cache = NULL;
255 fprintf(stderr, "usage: %s <token> <value>\n", argv[0]);
261 res = blkid_evaluate_tag(argv[1], argv[2], &cache);
265 blkid_put_cache(cache);
267 return res ? EXIT_SUCCESS : EXIT_FAILURE;