chiark / gitweb /
[PATCH] udev_volume_id: rename probe_ibm into probe_dasd
[elogind.git] / extras / volume_id / udev_volume_id.c
1 /*
2  * udev_volume_id - udev callout to read filesystem label and uuid
3  *
4  * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5  *
6  *      sample udev rule for creation of a symlink with the filsystem uuid:
7  *      KERNEL="sd*", PROGRAM="/sbin/udev_volume_id -u", SYMLINK="%c"
8  *
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.
12  * 
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.
17  * 
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.
21  *
22  */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <sys/ioctl.h>
30
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"
36
37 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
38
39 #ifdef LOG
40 void log_message(int level, const char *format, ...)
41 {
42         va_list args;
43
44         va_start(args, format);
45         vsyslog(level, format, args);
46         va_end(args);
47 }
48 #endif
49
50 static struct volume_id *open_classdev(struct sysfs_class_device *class_dev)
51 {
52         struct volume_id *vid;
53         struct sysfs_attribute *attr;
54         int major, minor;
55
56         attr = sysfs_get_classdev_attr(class_dev, "dev");
57
58         if (attr == NULL) {
59                 printf("error reading 'dev' attribute\n");
60                 return NULL;
61         }
62
63         if (sscanf(attr->value, "%u:%u", &major, &minor) != 2) {
64                 printf("error getting major/minor number\n");
65                 return NULL;
66         }
67
68         vid = volume_id_open_dev_t(makedev(major, minor));
69         if (vid == NULL) {
70                 printf("error open volume\n");
71                 return NULL;
72         }
73
74         return vid;
75 }
76
77 int main(int argc, char *argv[])
78 {
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"
84                             "\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;
91         char *devpath;
92         char probe_main_device = 0;
93         char print = 'a';
94         static char name[VOLUME_ID_LABEL_SIZE];
95         int len, i, j;
96         unsigned long long size;
97         int rc = 1;
98
99         logging_init("udev_volume_id");
100
101         while (1) {
102                 int option;
103
104                 option = getopt(argc, argv, short_options);
105                 if (option == -1)
106                         break;
107
108                 switch (option) {
109                 case 't':
110                         print = 't';
111                         continue;
112                 case 'l':
113                         print = 'l';
114                         continue;
115                 case 'u':
116                         print = 'u';
117                         continue;
118                 case 'd':
119                         probe_main_device = 1;
120                         continue;
121                 case 'h':
122                 case '?':
123                 default:
124                         printf(help);
125                         exit(1);
126                 }
127         }
128
129         devpath = getenv("DEVPATH");
130         if (devpath == NULL) {
131                 printf("error DEVPATH empty\n");
132                 goto exit;
133         }
134
135         if (sysfs_get_mnt_path(sysfs_mnt_path, SYSFS_PATH_MAX) != 0) {
136                 printf("error getting sysfs mount path\n");
137                 goto exit;
138         }
139
140         strfieldcpy(dev_path, sysfs_mnt_path);
141         strfieldcat(dev_path, devpath);
142
143         class_dev = sysfs_open_class_device_path(dev_path);
144         if (class_dev == NULL) {
145                 printf("error getting class device\n");
146                 goto exit;
147         }
148
149         if (probe_main_device == 0) {
150                 /* open block device */
151                 vid = open_classdev(class_dev);
152                 if (vid == NULL)
153                         goto exit;
154
155                 if (ioctl(vid->fd, BLKGETSIZE64, &size) != 0)
156                         size = 0;
157
158                 if (volume_id_probe_all(vid, 0, size) == 0)
159                         goto print;
160         } else {
161                 /* if we are on a partition, open main block device instead */
162                 class_dev_parent = sysfs_get_classdev_parent(class_dev);
163                 if (class_dev_parent != NULL)
164                         vid = open_classdev(class_dev_parent);
165                 else
166                         vid = open_classdev(class_dev);
167                 if (vid == NULL)
168                         goto exit;
169
170                 if (volume_id_probe_dasd_partition(vid) == 0)
171                         goto print;
172         }
173
174         printf("unknown volume type\n");
175         goto exit;
176
177
178 print:
179         len = strnlen(vid->label, VOLUME_ID_LABEL_SIZE);
180
181         /* remove trailing spaces */
182         while (len > 0 && isspace(vid->label[len-1]))
183                 len--;
184         name[len] = '\0';
185
186         /* substitute chars */
187         i = 0;
188         j = 0;
189         while (j < len) {
190                 switch(vid->label[j]) {
191                 case '/' :
192                         break;
193                 case ' ' :
194                         name[i++] = '_';
195                         break;
196                 default :
197                         name[i++] = vid->label[j];
198                 }
199                 j++;
200         }
201         name[i] = '\0';
202
203         switch (print) {
204         case 't':
205                 printf("%s\n", vid->type);
206                 break;
207         case 'l':
208                 if (name[0] == '\0' || vid->usage_id != VOLUME_ID_FILESYSTEM) {
209                         rc = 2;
210                         goto exit;
211                 }
212                 printf("%s\n", name);
213                 break;
214         case 'u':
215                 if (vid->uuid[0] == '\0' || vid->usage_id != VOLUME_ID_FILESYSTEM) {
216                         rc = 2;
217                         goto exit;
218                 }
219                 printf("%s\n", vid->uuid);
220                 break;
221         case 'a':
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);
228         }
229         rc = 0;
230
231 exit:
232         if (class_dev != NULL)
233                 sysfs_close_class_device(class_dev);
234         if (vid != NULL)
235                 volume_id_close(vid);
236
237         logging_close();
238
239         exit(rc);
240 }