chiark / gitweb /
run_directory: fix typo in "make install"
[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 library is free software; you can redistribute it and/or
7  *      modify it under the terms of the GNU Lesser General Public
8  *      License as published by the Free Software Foundation; either
9  *      version 2.1 of the License, or (at your option) any later version.
10  *
11  *      This library is distributed in the hope that it will be useful,
12  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  *      Lesser General Public License for more details.
15  *
16  *      You should have received a copy of the GNU Lesser General Public
17  *      License along with this library; if not, write to the Free Software
18  *      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20
21 #ifndef _GNU_SOURCE
22 #define _GNU_SOURCE 1
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <ctype.h>
30 #include <errno.h>
31 #include <sys/ioctl.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <linux/types.h>
35 #include <linux/hdreg.h>
36
37 #include "../../logging.h"
38 #include "../../udev_utils.h"
39
40 #ifdef USE_LOG
41 void log_message(int priority, const char *format, ...)
42 {
43         va_list args;
44         static int udev_log = -1;
45
46         if (udev_log == -1) {
47                 const char *value;
48
49                 value = getenv("UDEV_LOG");
50                 if (value)
51                         udev_log = log_priority(value);
52                 else
53                         udev_log = LOG_ERR;
54         }
55
56         if (priority > udev_log)
57                 return;
58
59         va_start(args, format);
60         vsyslog(priority, format, args);
61         va_end(args);
62 }
63 #endif
64
65 static void set_str(char *to, const char *from, size_t count)
66 {
67         size_t i, j, len;
68
69         /* strip trailing whitespace */
70         len = strnlen(from, count);
71         while (len && isspace(from[len-1]))
72                 len--;
73
74         /* strip leading whitespace */
75         i = 0;
76         while (isspace(from[i]) && (i < len))
77                 i++;
78
79         j = 0;
80         while (i < len) {
81                 /* substitute multiple whitespace */
82                 if (isspace(from[i])) {
83                         while (isspace(from[i]))
84                                 i++;
85                         to[j++] = '_';
86                 }
87                 /* skip chars */
88                 if (from[i] == '/') {
89                         i++;
90                         continue;
91                 }
92                 to[j++] = from[i++];
93         }
94         to[j] = '\0';
95 }
96
97 int main(int argc, char *argv[])
98 {
99         struct hd_driveid id;
100         char model[41];
101         char serial[21];
102         char revision[9];
103         const char *node = NULL;
104         int i;
105         int export = 0;
106         int fd;
107         int rc = 0;
108
109         logging_init("ata_id");
110
111         for (i = 1 ; i < argc; i++) {
112                 char *arg = argv[i];
113
114                 if (strcmp(arg, "--export") == 0) {
115                         export = 1;
116                 } else
117                         node = arg;
118         }
119         if (!node) {
120                 err("no node specified");
121                 rc = 1;
122                 goto exit;
123         }
124
125         fd = open(node, O_RDONLY);
126         if (fd < 0)
127                 if (errno == ENOMEDIUM)
128                         fd = open(node, O_RDONLY|O_NONBLOCK);
129         if (fd < 0) {
130                 err("unable to open '%s'", node);
131                 rc = 1;
132                 goto exit;
133         }
134
135         if (ioctl(fd, HDIO_GET_IDENTITY, &id)) {
136                 err("HDIO_GET_IDENTITY failed for '%s'", node);
137                 rc = 3;
138                 goto close;
139         }
140
141         set_str(model, (char *) id.model, 40);
142         set_str(serial, (char *) id.serial_no, 20);
143         set_str(revision, (char *) id.fw_rev, 8);
144
145         if (export) {
146                 if ((id.config >> 8) & 0x80) {
147                         /* This is an ATAPI device */
148                         switch ((id.config >> 8) & 0x1f) {
149                         case 0:
150                                 printf("ID_TYPE=cd\n");
151                                 break;
152                         case 1:
153                                 printf("ID_TYPE=tape\n");
154                                 break;
155                         case 5:
156                                 printf("ID_TYPE=cd\n");
157                                 break;
158                         case 7:
159                                 printf("ID_TYPE=optical\n");
160                                 break;
161                         default:
162                                 printf("ID_TYPE=generic\n");
163                                 break;
164                         }
165                 } else {
166                         printf("ID_TYPE=disk\n");
167                 }
168                 printf("ID_MODEL=%s\n", model);
169                 printf("ID_SERIAL=%s\n", serial);
170                 printf("ID_REVISION=%s\n", revision);
171                 printf("ID_BUS=ata\n");
172         } else {
173                 if (serial[0] != '\0')
174                         printf("%s_%s\n", model, serial);
175                 else
176                         printf("%s\n", model);
177         }
178
179 close:
180         close(fd);
181 exit:
182         logging_close();
183         return rc;
184 }