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 "../../libsysfs/sysfs/libsysfs.h"
30 #include "../../udev_lib.h"
31 #include "../../logging.h"
32 #include "volume_id.h"
33 #include "dasdlabel.h"
36 unsigned char logname[LOGNAME_SIZE];
37 void log_message(int level, const char *format, ...)
41 va_start(args, format);
42 vsyslog(level, format, args);
47 static struct volume_id *open_classdev(struct sysfs_class_device *class_dev)
49 struct volume_id *vid;
50 struct sysfs_attribute *attr;
53 attr = sysfs_get_classdev_attr(class_dev, "dev");
56 printf("error reading 'dev' attribute\n");
60 if (sscanf(attr->value, "%u:%u", &major, &minor) != 2) {
61 printf("error getting major/minor number\n");
65 vid = volume_id_open_dev_t(makedev(major, minor));
67 printf("error open volume\n");
74 int main(int argc, char *argv[])
76 const char help[] = "usage: udev_volume_id [-t|-l|-u|-d]\n"
77 " -t filesystem type\n"
78 " -l filesystem label\n"
79 " -u filesystem uuid\n"
80 " -d disk label from main device\n"
82 static const char short_options[] = "htlud";
84 char sysfs_path[SYSFS_PATH_MAX];
85 char dev_path[SYSFS_PATH_MAX];
86 struct sysfs_class_device *class_dev = NULL;
87 struct sysfs_class_device *class_dev_parent = NULL;
88 struct volume_id *vid = NULL;
93 static char name[VOLUME_ID_LABEL_SIZE];
98 option = getopt(argc, argv, short_options);
123 devpath = getenv("DEVPATH");
124 if (devpath == NULL) {
125 printf("error DEVPATH empty\n");
129 if (sysfs_get_mnt_path(sysfs_path, SYSFS_PATH_MAX) != 0) {
130 printf("error getting sysfs mount path\n");
134 strfieldcpy(dev_path, sysfs_path);
135 strfieldcat(dev_path, devpath);
137 class_dev = sysfs_open_class_device_path(dev_path);
138 if (class_dev == NULL) {
139 printf("error getting class device\n");
145 /* open block device */
146 vid = open_classdev(class_dev);
149 if (volume_id_probe(vid, ALL) == 0)
153 /* if we are on a partition, close it and open main block device */
154 class_dev_parent = sysfs_get_classdev_parent(class_dev);
155 if (class_dev_parent != NULL) {
156 volume_id_close(vid);
157 vid = open_classdev(class_dev_parent);
159 vid = open_classdev(class_dev_parent);
163 if (probe_ibm_partition(vid->fd, dasd_label) == 0) {
164 vid->fs_name = "dasd";
165 strncpy(vid->label_string, dasd_label, 6);
166 vid->label_string[6] = '\0';
172 printf("unknown volume type\n");
177 len = strnlen(vid->label_string, VOLUME_ID_LABEL_SIZE);
179 /* remove trailing spaces */
180 while (len > 0 && isspace(vid->label_string[len-1]))
184 /* substitute chars */
188 switch(vid->label_string[j]) {
195 name[i++] = vid->label_string[j];
203 printf("%s\n", vid->fs_name);
206 if (name[0] == '\0') {
210 printf("%s\n", name);
213 if (vid->uuid_string[0] == '\0') {
217 printf("%s\n", vid->uuid_string);
220 printf("T:%s\n", vid->fs_name);
221 printf("L:%s\n", vid->label_string);
222 printf("N:%s\n", name);
223 printf("U:%s\n", vid->uuid_string);
228 if (class_dev != NULL)
229 sysfs_close_class_device(class_dev);
231 volume_id_close(vid);