chiark / gitweb /
add ata_id to read serial numbers from ATA drives
[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 unsigned char *from, int count)
66 {
67         int i, j;
68         int len;
69
70         len = strnlen(from, count);
71         while (isspace(from[len-1]))
72                 len--;
73
74         i = 0;
75         while (isspace(from[i]) && (i < len))
76                 i++;
77
78         j = 0;
79         while (i < len) {
80                 switch(from[i]) {
81                 case '/':
82                 case ' ':
83                         to[j++] = '_';
84                 default:
85                         to[j++] = from[i];
86                 }
87                 i++;
88         }
89         to[j] = '\0';
90 }
91
92 int main(int argc, char *argv[])
93 {
94         struct hd_driveid id;
95         char model[41];
96         char serial[21];
97         char revision[9];
98         const char *node = NULL;
99         int i;
100         int export = 0;
101         int fd;
102         int rc = 0;
103
104         for (i = 1 ; i < argc; i++) {
105                 char *arg = argv[i];
106
107                 if (strcmp(arg, "--export") == 0) {
108                         export = 1;
109                 } else
110                         node = arg;
111         }
112         if (!node) {
113                 err("no node specified");
114                 rc = 1;
115                 goto exit;
116         }
117
118         fd = open(node, O_RDONLY);
119         if (fd < 0)
120                 if (errno == ENOMEDIUM)
121                         fd = open(node, O_RDONLY|O_NONBLOCK);
122         if (fd < 0) {
123                 err("unable to open '%s'", node);
124                 rc = 1;
125                 goto exit;
126         }
127
128         if (ioctl(fd, HDIO_GET_IDENTITY, &id)) {
129                 err("HDIO_GET_IDENTITY failed for '%s'", node);
130                 rc = 3;
131                 goto close;
132         }
133
134         set_str(model, id.model, 40);
135         set_str(serial, id.serial_no, 20);
136         set_str(revision, id.fw_rev, 8);
137
138         if (export) {
139                 printf("ID_MODEL=%s\n", model);
140                 printf("ID_SERIAL=%s\n", serial);
141                 printf("ID_REVISION=%s\n", revision);
142         } else
143                 printf("%s_%s\n", model, serial);
144
145 close:
146         close(fd);
147 exit:
148         logging_close();
149         return rc;
150 }