chiark / gitweb /
ata_id: don't log error for libata devices on older kernels
[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 <sys/ioctl.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <linux/types.h>
26 #include <linux/hdreg.h>
27
28 #include "../../udev.h"
29
30 #ifdef USE_LOG
31 void log_message(int priority, const char *format, ...)
32 {
33         va_list args;
34         static int udev_log = -1;
35
36         if (udev_log == -1) {
37                 const char *value;
38
39                 value = getenv("UDEV_LOG");
40                 if (value)
41                         udev_log = log_priority(value);
42                 else
43                         udev_log = LOG_ERR;
44         }
45
46         if (priority > udev_log)
47                 return;
48
49         va_start(args, format);
50         vsyslog(priority, format, args);
51         va_end(args);
52 }
53 #endif
54
55 static void set_str(char *to, const char *from, size_t count)
56 {
57         size_t i, j, len;
58
59         /* strip trailing whitespace */
60         len = strnlen(from, count);
61         while (len && isspace(from[len-1]))
62                 len--;
63
64         /* strip leading whitespace */
65         i = 0;
66         while (isspace(from[i]) && (i < len))
67                 i++;
68
69         j = 0;
70         while (i < len) {
71                 /* substitute multiple whitespace */
72                 if (isspace(from[i])) {
73                         while (isspace(from[i]))
74                                 i++;
75                         to[j++] = '_';
76                 }
77                 /* skip chars */
78                 if (from[i] == '/') {
79                         i++;
80                         continue;
81                 }
82                 to[j++] = from[i++];
83         }
84         to[j] = '\0';
85 }
86
87 int main(int argc, char *argv[])
88 {
89         struct hd_driveid id;
90         char model[41];
91         char serial[21];
92         char revision[9];
93         const char *node = NULL;
94         int i;
95         int export = 0;
96         int fd;
97         int rc = 0;
98
99         logging_init("ata_id");
100
101         for (i = 1 ; i < argc; i++) {
102                 char *arg = argv[i];
103
104                 if (strcmp(arg, "--export") == 0) {
105                         export = 1;
106                 } else
107                         node = arg;
108         }
109         if (!node) {
110                 err("no node specified");
111                 rc = 1;
112                 goto exit;
113         }
114
115         fd = open(node, O_RDONLY|O_NONBLOCK);
116         if (fd < 0) {
117                 err("unable to open '%s'", node);
118                 rc = 1;
119                 goto exit;
120         }
121
122         if (ioctl(fd, HDIO_GET_IDENTITY, &id)) {
123                 if (errno == ENOTTY) {
124                         info("HDIO_GET_IDENTITY unsupported for '%s'", node);
125                         rc = 2;
126                 } else {
127                         err("HDIO_GET_IDENTITY failed for '%s'", node);
128                         rc = 3;
129                 }
130                 goto close;
131         }
132
133         set_str(model, (char *) id.model, 40);
134         set_str(serial, (char *) id.serial_no, 20);
135         set_str(revision, (char *) id.fw_rev, 8);
136
137         if (export) {
138                 if ((id.config >> 8) & 0x80) {
139                         /* This is an ATAPI device */
140                         switch ((id.config >> 8) & 0x1f) {
141                         case 0:
142                                 printf("ID_TYPE=cd\n");
143                                 break;
144                         case 1:
145                                 printf("ID_TYPE=tape\n");
146                                 break;
147                         case 5:
148                                 printf("ID_TYPE=cd\n");
149                                 break;
150                         case 7:
151                                 printf("ID_TYPE=optical\n");
152                                 break;
153                         default:
154                                 printf("ID_TYPE=generic\n");
155                                 break;
156                         }
157                 } else {
158                         printf("ID_TYPE=disk\n");
159                 }
160                 printf("ID_MODEL=%s\n", model);
161                 printf("ID_SERIAL=%s\n", serial);
162                 printf("ID_REVISION=%s\n", revision);
163                 printf("ID_BUS=ata\n");
164         } else {
165                 if (serial[0] != '\0')
166                         printf("%s_%s\n", model, serial);
167                 else
168                         printf("%s\n", model);
169         }
170
171 close:
172         close(fd);
173 exit:
174         logging_close();
175         return rc;
176 }