2 * udev_volume_id - udev callout to read filesystem label and uuid
4 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
6 * sample udev rule for creation of a symlink with the filsystem uuid:
7 * KERNEL="sd*", PROGRAM="/sbin/udev_volume_id -u", SYMLINK="%c"
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation version 2 of the License.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 675 Mass Ave, Cambridge, MA 02139, USA.
29 #include <sys/ioctl.h>
31 #include "../../libsysfs/sysfs/libsysfs.h"
32 #include "../../udev_utils.h"
33 #include "../../logging.h"
34 #include "volume_id/volume_id.h"
35 #include "volume_id/dasd/dasd.h"
37 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
40 void log_message(int level, const char *format, ...)
44 va_start(args, format);
45 vsyslog(level, format, args);
50 static struct volume_id *open_classdev(struct sysfs_class_device *class_dev)
52 struct volume_id *vid;
53 struct sysfs_attribute *attr;
56 attr = sysfs_get_classdev_attr(class_dev, "dev");
59 printf("error reading 'dev' attribute\n");
63 if (sscanf(attr->value, "%u:%u", &major, &minor) != 2) {
64 printf("error getting major/minor number\n");
68 vid = volume_id_open_dev_t(makedev(major, minor));
70 printf("error open volume\n");
77 int main(int argc, char *argv[])
79 const char help[] = "usage: udev_volume_id [-t|-l|-u|-d]\n"
80 " -t filesystem type\n"
81 " -l filesystem label\n"
82 " -u filesystem uuid\n"
83 " -d disk label from main device\n"
85 static const char short_options[] = "htlud";
86 char sysfs_mnt_path[SYSFS_PATH_MAX];
87 char dev_path[SYSFS_PATH_MAX];
88 struct sysfs_class_device *class_dev = NULL;
89 struct sysfs_class_device *class_dev_parent = NULL;
90 struct volume_id *vid = NULL;
92 char probe_disk_label = 0;
94 static char name[VOLUME_ID_LABEL_SIZE];
96 unsigned long long size;
99 logging_init("udev_volume_id");
104 option = getopt(argc, argv, short_options);
119 probe_disk_label = 1;
129 devpath = getenv("DEVPATH");
130 if (devpath == NULL) {
131 printf("error DEVPATH empty\n");
135 if (sysfs_get_mnt_path(sysfs_mnt_path, SYSFS_PATH_MAX) != 0) {
136 printf("error getting sysfs mount path\n");
140 strfieldcpy(dev_path, sysfs_mnt_path);
141 strfieldcat(dev_path, devpath);
143 class_dev = sysfs_open_class_device_path(dev_path);
144 if (class_dev == NULL) {
145 printf("error getting class device\n");
149 if (probe_disk_label == 0) {
150 vid = open_classdev(class_dev);
154 if (ioctl(vid->fd, BLKGETSIZE64, &size) != 0)
157 if (volume_id_probe_all(vid, 0, size) == 0)
160 /* if we are on a partition, open main block device instead */
161 class_dev_parent = sysfs_get_classdev_parent(class_dev);
162 if (class_dev_parent != NULL)
163 vid = open_classdev(class_dev_parent);
165 vid = open_classdev(class_dev);
169 if (volume_id_probe_dasd(vid) == 0)
173 printf("unknown volume type\n");
178 len = strnlen(vid->label, VOLUME_ID_LABEL_SIZE);
180 /* remove trailing spaces */
181 while (len > 0 && isspace(vid->label[len-1]))
185 /* substitute chars */
189 switch(vid->label[j]) {
196 name[i++] = vid->label[j];
204 printf("%s\n", vid->type);
207 if (name[0] == '\0' ||
208 (vid->usage_id != VOLUME_ID_FILESYSTEM && vid->usage_id != VOLUME_ID_DISKLABEL)) {
212 printf("%s\n", name);
215 if (vid->uuid[0] == '\0' || vid->usage_id != VOLUME_ID_FILESYSTEM) {
219 printf("%s\n", vid->uuid);
222 printf("F:%s\n", vid->usage);
223 printf("T:%s\n", vid->type);
224 printf("V:%s\n", vid->type_version);
225 printf("L:%s\n", vid->label);
226 printf("N:%s\n", name);
227 printf("U:%s\n", vid->uuid);
232 if (class_dev != NULL)
233 sysfs_close_class_device(class_dev);
235 volume_id_close(vid);