chiark / gitweb /
cciss device support
[elogind.git] / extras / ata_id / ata_id.c
1 /*
2  * ata_id - reads product/serial number from ATA drives
3  *
4  * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5  *
6  *      This program is free software; you can redistribute it and/or modify it
7  *      under the terms of the GNU General Public License as published by the
8  *      Free Software Foundation version 2 of the License.
9  */
10
11 #ifndef _GNU_SOURCE
12 #define _GNU_SOURCE 1
13 #endif
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <ctype.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <getopt.h>
23 #include <sys/ioctl.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <linux/types.h>
27 #include <linux/hdreg.h>
28
29 #include "../../udev.h"
30
31 #ifdef USE_LOG
32 void log_message(int priority, const char *format, ...)
33 {
34         va_list args;
35         static int udev_log = -1;
36
37         if (udev_log == -1) {
38                 const char *value;
39
40                 value = getenv("UDEV_LOG");
41                 if (value)
42                         udev_log = log_priority(value);
43                 else
44                         udev_log = LOG_ERR;
45         }
46
47         if (priority > udev_log)
48                 return;
49
50         va_start(args, format);
51         vsyslog(priority, format, args);
52         va_end(args);
53 }
54 #endif
55
56 static void set_str(char *to, const char *from, size_t count)
57 {
58         size_t i, j, len;
59
60         /* strip trailing whitespace */
61         len = strnlen(from, count);
62         while (len && isspace(from[len-1]))
63                 len--;
64
65         /* strip leading whitespace */
66         i = 0;
67         while (isspace(from[i]) && (i < len))
68                 i++;
69
70         j = 0;
71         while (i < len) {
72                 /* substitute multiple whitespace */
73                 if (isspace(from[i])) {
74                         while (isspace(from[i]))
75                                 i++;
76                         to[j++] = '_';
77                 }
78                 /* skip chars */
79                 if (from[i] == '/') {
80                         i++;
81                         continue;
82                 }
83                 to[j++] = from[i++];
84         }
85         to[j] = '\0';
86 }
87
88 int main(int argc, char *argv[])
89 {
90         struct hd_driveid id;
91         char model[41];
92         char serial[21];
93         char revision[9];
94         const char *node = NULL;
95         int export = 0;
96         int fd;
97         int rc = 0;
98         static const struct option options[] = {
99                 { "export", 0, NULL, 'x' },
100                 { "help", 0, NULL, 'h' },
101                 {}
102         };
103
104         logging_init("ata_id");
105
106         while (1) {
107                 int option;
108
109                 option = getopt_long(argc, argv, "xh", options, NULL);
110                 if (option == -1)
111                         break;
112
113                 switch (option) {
114                 case 'x':
115                         export = 1;
116                         break;
117                 case 'h':
118                         printf("Usage: ata_id [--export] [--help] <device>\n"
119                                "  --export    print values as environemt keys\n"
120                                "  --help      print this help text\n\n");
121                 default:
122                         rc = 1;
123                         goto exit;
124                 }
125         }
126
127         node = argv[optind];
128         if (node == NULL) {
129                 err("no node specified");
130                 rc = 1;
131                 goto exit;
132         }
133
134         fd = open(node, O_RDONLY|O_NONBLOCK);
135         if (fd < 0) {
136                 err("unable to open '%s'", node);
137                 rc = 1;
138                 goto exit;
139         }
140
141         if (ioctl(fd, HDIO_GET_IDENTITY, &id)) {
142                 if (errno == ENOTTY) {
143                         info("HDIO_GET_IDENTITY unsupported for '%s'", node);
144                         rc = 2;
145                 } else {
146                         err("HDIO_GET_IDENTITY failed for '%s'", node);
147                         rc = 3;
148                 }
149                 goto close;
150         }
151
152         set_str(model, (char *) id.model, 40);
153         set_str(serial, (char *) id.serial_no, 20);
154         set_str(revision, (char *) id.fw_rev, 8);
155
156         if (export) {
157                 if ((id.config >> 8) & 0x80) {
158                         /* This is an ATAPI device */
159                         switch ((id.config >> 8) & 0x1f) {
160                         case 0:
161                                 printf("ID_TYPE=cd\n");
162                                 break;
163                         case 1:
164                                 printf("ID_TYPE=tape\n");
165                                 break;
166                         case 5:
167                                 printf("ID_TYPE=cd\n");
168                                 break;
169                         case 7:
170                                 printf("ID_TYPE=optical\n");
171                                 break;
172                         default:
173                                 printf("ID_TYPE=generic\n");
174                                 break;
175                         }
176                 } else {
177                         printf("ID_TYPE=disk\n");
178                 }
179                 printf("ID_MODEL=%s\n", model);
180                 printf("ID_SERIAL=%s\n", serial);
181                 printf("ID_REVISION=%s\n", revision);
182                 printf("ID_BUS=ata\n");
183         } else {
184                 if (serial[0] != '\0')
185                         printf("%s_%s\n", model, serial);
186                 else
187                         printf("%s\n", model);
188         }
189
190 close:
191         close(fd);
192 exit:
193         logging_close();
194         return rc;
195 }