2 * evaluate.c - very high-level API to evaluate LABELs or UUIDs
4 * Copyright (C) 2009 Karel Zak <kzak@redhat.com>
6 * This file may be redistributed under the terms of the
7 * GNU Lesser General Public License.
15 #include <sys/types.h>
16 #ifdef HAVE_SYS_STAT_H
25 #include "pathnames.h"
26 #include "canonicalize.h"
32 * @title: Tags and Spec evaluation
33 * @short_description: top-level API for LABEL and UUID evaluation.
35 * This API provides very simple and portable way how evaluate LABEL and UUID
36 * tags. The blkid_evaluate_tag() and blkid_evaluate_spec() work on 2.4 and
37 * 2.6 systems and on systems with or without udev. Currently, the libblkid
38 * library supports "udev" and "scan" methods. The "udev" method uses udev
39 * /dev/disk/by-* symlinks and the "scan" method scans all block devices from
40 * the /proc/partitions file. The evaluation could be controlled by the
41 * /etc/blkid.conf config file. The default is to try "udev" and then "scan"
44 * The blkid_evaluate_tag() also automatically informs udevd when an obsolete
45 * /dev/disk/by-* symlink is detected.
47 * If you are not sure how translate LABEL or UUID to the device name use this
51 #ifdef CONFIG_BLKID_VERIFY_UDEV
52 /* returns zero when the device has NAME=value (LABEL/UUID) */
53 static int verify_tag(const char *devname
, const char *name
, const char *value
)
61 pr
= blkid_new_probe();
65 blkid_probe_enable_superblocks(pr
, TRUE
);
66 blkid_probe_set_superblocks_flags(pr
,
67 BLKID_SUBLKS_LABEL
| BLKID_SUBLKS_UUID
);
69 blkid_probe_enable_partitions(pr
, TRUE
);
70 blkid_probe_set_partitions_flags(pr
, BLKID_PARTS_ENTRY_DETAILS
);
72 fd
= open(devname
, O_RDONLY
|O_CLOEXEC
);
77 if (blkid_probe_set_device(pr
, fd
, 0, 0))
79 rc
= blkid_do_safeprobe(pr
);
82 rc
= blkid_probe_lookup_value(pr
, name
, &data
, &len
);
84 rc
= memcmp(value
, data
, len
);
86 DBG(DEBUG_EVALUATE
, printf("%s: %s verification %s\n",
87 devname
, name
, rc
== 0 ? "PASS" : "FAILED"));
92 /* for non-root users we use unverified udev links */
93 return errsv
== EACCES
? 0 : rc
;
95 #endif /* CONFIG_BLKID_VERIFY_UDEV*/
99 * @devname: absolute path to the device
100 * @action: event string
102 * Returns: -1 in case of failure, or 0 on success.
104 int blkid_send_uevent(const char *devname
, const char *action
)
106 char uevent
[PATH_MAX
];
111 DBG(DEBUG_EVALUATE
, printf("%s: uevent '%s' requested\n", devname
, action
));
113 if (!devname
|| !action
)
115 if (stat(devname
, &st
) || !S_ISBLK(st
.st_mode
))
118 snprintf(uevent
, sizeof(uevent
), "/sys/dev/block/%d:%d/uevent",
119 major(st
.st_rdev
), minor(st
.st_rdev
));
121 f
= fopen(uevent
, "w");
124 if (fputs(action
, f
) >= 0)
128 DBG(DEBUG_EVALUATE
, printf("%s: send uevent %s\n",
129 uevent
, rc
== 0 ? "SUCCES" : "FAILED"));
133 static char *evaluate_by_udev(const char *token
, const char *value
, int uevent
)
141 printf("evaluating by udev %s=%s\n", token
, value
));
143 if (!strcmp(token
, "UUID"))
144 strcpy(dev
, _PATH_DEV_BYUUID
"/");
145 else if (!strcmp(token
, "LABEL"))
146 strcpy(dev
, _PATH_DEV_BYLABEL
"/");
147 else if (!strcmp(token
, "PARTLABEL"))
148 strcpy(dev
, _PATH_DEV_BYPARTLABEL
"/");
149 else if (!strcmp(token
, "PARTUUID"))
150 strcpy(dev
, _PATH_DEV_BYPARTUUID
"/");
153 printf("unsupported token %s\n", token
));
154 return NULL
; /* unsupported tag */
158 if (blkid_encode_string(value
, &dev
[len
], sizeof(dev
) - len
) != 0)
162 printf("expected udev link: %s\n", dev
));
165 goto failed
; /* link or device does not exist */
167 if (!S_ISBLK(st
.st_mode
))
170 path
= canonicalize_path(dev
);
174 #ifdef CONFIG_BLKID_VERIFY_UDEV
175 if (verify_tag(path
, token
, value
))
181 DBG(DEBUG_EVALUATE
, printf("failed to evaluate by udev\n"));
184 blkid_send_uevent(path
, "change");
189 static char *evaluate_by_scan(const char *token
, const char *value
,
190 blkid_cache
*cache
, struct blkid_config
*conf
)
192 blkid_cache c
= cache
? *cache
: NULL
;
196 printf("evaluating by blkid scan %s=%s\n", token
, value
));
199 char *cachefile
= blkid_get_cache_filename(conf
);
200 blkid_get_cache(&c
, cachefile
);
206 res
= blkid_get_devname(c
, token
, value
);
217 * blkid_evaluate_tag:
218 * @token: token name (e.g "LABEL" or "UUID") or unparsed tag (e.g. "LABEL=foo")
219 * @value: token data (e.g. "foo")
220 * @cache: pointer to cache (or NULL when you don't want to re-use the cache)
222 * Returns: allocated string with a device name.
224 char *blkid_evaluate_tag(const char *token
, const char *value
, blkid_cache
*cache
)
226 struct blkid_config
*conf
= NULL
;
227 char *t
= NULL
, *v
= NULL
;
234 if (!cache
|| !*cache
)
238 printf("evaluating %s%s%s\n", token
, value
? "=" : "",
239 value
? value
: ""));
242 if (!strchr(token
, '=')) {
246 blkid_parse_tag_string(token
, &t
, &v
);
253 conf
= blkid_read_config(NULL
);
257 for (i
= 0; i
< conf
->nevals
; i
++) {
258 if (conf
->eval
[i
] == BLKID_EVAL_UDEV
)
259 ret
= evaluate_by_udev(token
, value
, conf
->uevent
);
260 else if (conf
->eval
[i
] == BLKID_EVAL_SCAN
)
261 ret
= evaluate_by_scan(token
, value
, cache
, conf
);
267 printf("%s=%s evaluated as %s\n", token
, value
, ret
));
269 blkid_free_config(conf
);
276 * blkid_evaluate_spec:
277 * @spec: unparsed tag (e.g. "LABEL=foo") or path (e.g. /dev/dm-0)
278 * @cache: pointer to cache (or NULL when you don't want to re-use the cache)
280 * All returned paths are canonicalized, device-mapper paths are converted
281 * to the /dev/mapper/name format.
283 * Returns: allocated string with a device name.
285 char *blkid_evaluate_spec(const char *spec
, blkid_cache
*cache
)
287 char *t
= NULL
, *v
= NULL
, *res
;
292 if (strchr(spec
, '=') &&
293 blkid_parse_tag_string(spec
, &t
, &v
) != 0) /* parse error */
297 res
= blkid_evaluate_tag(t
, v
, cache
);
299 res
= canonicalize_path(spec
);
308 int main(int argc
, char *argv
[])
310 blkid_cache cache
= NULL
;
314 fprintf(stderr
, "usage: %s <tag> | <spec>\n", argv
[0]);
320 res
= blkid_evaluate_spec(argv
[1], &cache
);
324 blkid_put_cache(cache
);
326 return res
? EXIT_SUCCESS
: EXIT_FAILURE
;