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_lib.h"
33 #include "../../logging.h"
34 #include "volume_id.h"
35 #include "dasdlabel.h"
37 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
40 unsigned char logname[LOGNAME_SIZE];
41 void log_message(int level, const char *format, ...)
45 va_start(args, format);
46 vsyslog(level, format, args);
51 static struct volume_id *open_classdev(struct sysfs_class_device *class_dev)
53 struct volume_id *vid;
54 struct sysfs_attribute *attr;
57 attr = sysfs_get_classdev_attr(class_dev, "dev");
60 printf("error reading 'dev' attribute\n");
64 if (sscanf(attr->value, "%u:%u", &major, &minor) != 2) {
65 printf("error getting major/minor number\n");
69 vid = volume_id_open_dev_t(makedev(major, minor));
71 printf("error open volume\n");
78 static char *usage_id_name(enum volume_id_usage usage)
81 case VOLUME_ID_UNUSED:
83 case VOLUME_ID_UNPROBED:
87 case VOLUME_ID_PARTITIONTABLE:
88 return "partitiontable";
89 case VOLUME_ID_FILESYSTEM:
94 return "unknown type_id";
98 int main(int argc, char *argv[])
100 const char help[] = "usage: udev_volume_id [-t|-l|-u|-d]\n"
101 " -t filesystem type\n"
102 " -l filesystem label\n"
103 " -u filesystem uuid\n"
104 " -d disk label from main device\n"
106 static const char short_options[] = "htlud";
107 char sysfs_path[SYSFS_PATH_MAX];
108 char dev_path[SYSFS_PATH_MAX];
109 struct sysfs_class_device *class_dev = NULL;
110 struct sysfs_class_device *class_dev_parent = NULL;
111 struct volume_id *vid = NULL;
116 static char name[VOLUME_ID_LABEL_SIZE];
118 unsigned long long size;
124 option = getopt(argc, argv, short_options);
149 devpath = getenv("DEVPATH");
150 if (devpath == NULL) {
151 printf("error DEVPATH empty\n");
155 if (sysfs_get_mnt_path(sysfs_path, SYSFS_PATH_MAX) != 0) {
156 printf("error getting sysfs mount path\n");
160 strfieldcpy(dev_path, sysfs_path);
161 strfieldcat(dev_path, devpath);
163 class_dev = sysfs_open_class_device_path(dev_path);
164 if (class_dev == NULL) {
165 printf("error getting class device\n");
171 /* open block device */
172 vid = open_classdev(class_dev);
176 if (ioctl(vid->fd, BLKGETSIZE64, &size) != 0)
179 if (volume_id_probe(vid, VOLUME_ID_ALL, 0, size) == 0)
183 /* if we are on a partition, open main block device instead */
184 class_dev_parent = sysfs_get_classdev_parent(class_dev);
185 if (class_dev_parent != NULL)
186 vid = open_classdev(class_dev_parent);
188 vid = open_classdev(class_dev_parent);
192 if (probe_ibm_partition(vid->fd, dasd_label) == 0) {
194 strncpy(vid->label, dasd_label, 6);
195 vid->label[6] = '\0';
201 printf("unknown volume type\n");
206 len = strnlen(vid->label, VOLUME_ID_LABEL_SIZE);
208 /* remove trailing spaces */
209 while (len > 0 && isspace(vid->label[len-1]))
213 /* substitute chars */
217 switch(vid->label[j]) {
224 name[i++] = vid->label[j];
232 printf("%s\n", vid->type);
235 if (name[0] == '\0' || vid->usage_id != VOLUME_ID_FILESYSTEM) {
239 printf("%s\n", name);
242 if (vid->uuid[0] == '\0' || vid->usage_id != VOLUME_ID_FILESYSTEM) {
246 printf("%s\n", vid->uuid);
249 printf("F:%s\n", usage_id_name(vid->usage_id));
250 printf("T:%s\n", vid->type);
251 printf("V:%s\n", vid->type_version);
252 printf("L:%s\n", vid->label);
253 printf("N:%s\n", name);
254 printf("U:%s\n", vid->uuid);
259 if (class_dev != NULL)
260 sysfs_close_class_device(class_dev);
262 volume_id_close(vid);