chiark / gitweb /
[PATCH] fix udev_volume_id build error.
[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.h"
35 #include "dasdlabel.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 static char *usage_id_name(enum volume_id_usage usage)
78 {
79         switch(usage) {
80         case VOLUME_ID_UNUSED:
81                 return "unused";
82         case VOLUME_ID_UNPROBED:
83                 return "unprobed";
84         case VOLUME_ID_OTHER:
85                 return "other";
86         case VOLUME_ID_PARTITIONTABLE:
87                 return "partitiontable";
88         case VOLUME_ID_FILESYSTEM:
89                 return "filesystem";
90         case VOLUME_ID_RAID:
91                 return "raid";
92         default:
93                 return "unknown type_id";
94         }
95 }
96
97 int main(int argc, char *argv[])
98 {
99         const char help[] = "usage: udev_volume_id [-t|-l|-u|-d]\n"
100                             "       -t filesystem type\n"
101                             "       -l filesystem label\n"
102                             "       -u filesystem uuid\n"
103                             "       -d disk label from main device\n"
104                             "\n";
105         static const char short_options[] = "htlud";
106         char sysfs_mnt_path[SYSFS_PATH_MAX];
107         char dev_path[SYSFS_PATH_MAX];
108         struct sysfs_class_device *class_dev = NULL;
109         struct sysfs_class_device *class_dev_parent = NULL;
110         struct volume_id *vid = NULL;
111         char *devpath;
112         char probe = 'p';
113         char print = 'a';
114         char dasd_label[7];
115         static char name[VOLUME_ID_LABEL_SIZE];
116         int len, i, j;
117         unsigned long long size;
118         int rc = 1;
119
120         logging_init("udev_volume_id");
121
122         while (1) {
123                 int option;
124
125                 option = getopt(argc, argv, short_options);
126                 if (option == -1)
127                         break;
128
129                 switch (option) {
130                 case 't':
131                         print = 't';
132                         continue;
133                 case 'l':
134                         print = 'l';
135                         continue;
136                 case 'u':
137                         print = 'u';
138                         continue;
139                 case 'd':
140                         probe = 'd';
141                         continue;
142                 case 'h':
143                 case '?':
144                 default:
145                         printf(help);
146                         exit(1);
147                 }
148         }
149
150         devpath = getenv("DEVPATH");
151         if (devpath == NULL) {
152                 printf("error DEVPATH empty\n");
153                 goto exit;
154         }
155
156         if (sysfs_get_mnt_path(sysfs_mnt_path, SYSFS_PATH_MAX) != 0) {
157                 printf("error getting sysfs mount path\n");
158                 goto exit;
159         }
160
161         strfieldcpy(dev_path, sysfs_mnt_path);
162         strfieldcat(dev_path, devpath);
163
164         class_dev = sysfs_open_class_device_path(dev_path);
165         if (class_dev == NULL) {
166                 printf("error getting class device\n");
167                 goto exit;
168         }
169
170         switch(probe) {
171         case 'p' :
172                 /* open block device */
173                 vid = open_classdev(class_dev);
174                 if (vid == NULL)
175                         goto exit;
176
177                 if (ioctl(vid->fd, BLKGETSIZE64, &size) != 0)
178                         size = 0;
179
180                 if (volume_id_probe(vid, VOLUME_ID_ALL, 0, size) == 0)
181                         goto print;
182                 break;
183         case 'd' :
184                 /* if we are on a partition, open main block device instead */
185                 class_dev_parent = sysfs_get_classdev_parent(class_dev);
186                 if (class_dev_parent != NULL)
187                         vid = open_classdev(class_dev_parent);
188                 else
189                         vid = open_classdev(class_dev_parent);
190                 if (vid == NULL)
191                         goto exit;
192
193                 if (probe_ibm_partition(vid->fd, dasd_label) == 0) {
194                         vid->type = "dasd";
195                         strncpy(vid->label, dasd_label, 6);
196                         vid->label[6] = '\0';
197                         goto print;
198                 }
199                 break;
200         }
201
202         printf("unknown volume type\n");
203         goto exit;
204
205
206 print:
207         len = strnlen(vid->label, VOLUME_ID_LABEL_SIZE);
208
209         /* remove trailing spaces */
210         while (len > 0 && isspace(vid->label[len-1]))
211                 len--;
212         name[len] = '\0';
213
214         /* substitute chars */
215         i = 0;
216         j = 0;
217         while (j < len) {
218                 switch(vid->label[j]) {
219                 case '/' :
220                         break;
221                 case ' ' :
222                         name[i++] = '_';
223                         break;
224                 default :
225                         name[i++] = vid->label[j];
226                 }
227                 j++;
228         }
229         name[i] = '\0';
230
231         switch (print) {
232         case 't':
233                 printf("%s\n", vid->type);
234                 break;
235         case 'l':
236                 if (name[0] == '\0' || vid->usage_id != VOLUME_ID_FILESYSTEM) {
237                         rc = 2;
238                         goto exit;
239                 }
240                 printf("%s\n", name);
241                 break;
242         case 'u':
243                 if (vid->uuid[0] == '\0' || vid->usage_id != VOLUME_ID_FILESYSTEM) {
244                         rc = 2;
245                         goto exit;
246                 }
247                 printf("%s\n", vid->uuid);
248                 break;
249         case 'a':
250                 printf("F:%s\n", usage_id_name(vid->usage_id));
251                 printf("T:%s\n", vid->type);
252                 printf("V:%s\n", vid->type_version);
253                 printf("L:%s\n", vid->label);
254                 printf("N:%s\n", name);
255                 printf("U:%s\n", vid->uuid);
256         }
257         rc = 0;
258
259 exit:
260         if (class_dev != NULL)
261                 sysfs_close_class_device(class_dev);
262         if (vid != NULL)
263                 volume_id_close(vid);
264
265         logging_close();
266
267         exit(rc);
268 }