chiark / gitweb /
udev-acl: allow to skip ACL handling
[elogind.git] / extras / ata_id / ata_id.c
1 /*
2  * ata_id - reads product/serial number from ATA drives
3  *
4  * Copyright (C) 2005-2008 Kay Sievers <kay.sievers@vrfy.org>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #ifndef _GNU_SOURCE
21 #define _GNU_SOURCE 1
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <ctype.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <getopt.h>
32 #include <sys/ioctl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <linux/types.h>
36 #include <linux/hdreg.h>
37
38 #include "libudev.h"
39 #include "libudev-private.h"
40
41 static void log_fn(struct udev *udev, int priority,
42                    const char *file, int line, const char *fn,
43                    const char *format, va_list args)
44 {
45         vsyslog(priority, format, args);
46 }
47
48 int main(int argc, char *argv[])
49 {
50         struct udev *udev;
51         struct hd_driveid id;
52         char model[41];
53         char model_enc[256];
54         char serial[21];
55         char revision[9];
56         const char *node = NULL;
57         int export = 0;
58         int fd;
59         int rc = 0;
60         static const struct option options[] = {
61                 { "export", no_argument, NULL, 'x' },
62                 { "help", no_argument, NULL, 'h' },
63                 {}
64         };
65
66         udev = udev_new();
67         if (udev == NULL)
68                 goto exit;
69
70         udev_log_init("ata_id");
71         udev_set_log_fn(udev, log_fn);
72
73         while (1) {
74                 int option;
75
76                 option = getopt_long(argc, argv, "xh", options, NULL);
77                 if (option == -1)
78                         break;
79
80                 switch (option) {
81                 case 'x':
82                         export = 1;
83                         break;
84                 case 'h':
85                         printf("Usage: ata_id [--export] [--help] <device>\n"
86                                "  --export    print values as environment keys\n"
87                                "  --help      print this help text\n\n");
88                 default:
89                         rc = 1;
90                         goto exit;
91                 }
92         }
93
94         node = argv[optind];
95         if (node == NULL) {
96                 err(udev, "no node specified\n");
97                 rc = 1;
98                 goto exit;
99         }
100
101         fd = open(node, O_RDONLY|O_NONBLOCK);
102         if (fd < 0) {
103                 err(udev, "unable to open '%s'\n", node);
104                 rc = 1;
105                 goto exit;
106         }
107
108         if (ioctl(fd, HDIO_GET_IDENTITY, &id)) {
109                 if (errno == ENOTTY) {
110                         info(udev, "HDIO_GET_IDENTITY unsupported for '%s'\n", node);
111                         rc = 2;
112                 } else {
113                         err(udev, "HDIO_GET_IDENTITY failed for '%s'\n", node);
114                         rc = 3;
115                 }
116                 goto close;
117         }
118
119         memcpy (model, id.model, 40);
120         model[40] = '\0';
121         udev_util_encode_string(model, model_enc, sizeof(model_enc));
122         udev_util_replace_whitespace((char *) id.model, model, 40);
123         udev_util_replace_chars(model, NULL);
124         udev_util_replace_whitespace((char *) id.serial_no, serial, 20);
125         udev_util_replace_chars(serial, NULL);
126         udev_util_replace_whitespace((char *) id.fw_rev, revision, 8);
127         udev_util_replace_chars(revision, NULL);
128
129         if (export) {
130                 if ((id.config >> 8) & 0x80) {
131                         /* This is an ATAPI device */
132                         switch ((id.config >> 8) & 0x1f) {
133                         case 0:
134                                 printf("ID_TYPE=cd\n");
135                                 break;
136                         case 1:
137                                 printf("ID_TYPE=tape\n");
138                                 break;
139                         case 5:
140                                 printf("ID_TYPE=cd\n");
141                                 break;
142                         case 7:
143                                 printf("ID_TYPE=optical\n");
144                                 break;
145                         default:
146                                 printf("ID_TYPE=generic\n");
147                                 break;
148                         }
149                 } else {
150                         printf("ID_TYPE=disk\n");
151                 }
152                 printf("ID_BUS=ata\n");
153                 printf("ID_MODEL=%s\n", model);
154                 printf("ID_MODEL_ENC=%s\n", model_enc);
155                 printf("ID_REVISION=%s\n", revision);
156                 printf("ID_SERIAL=%s_%s\n", model, serial);
157                 printf("ID_SERIAL_SHORT=%s\n", serial);
158         } else {
159                 if (serial[0] != '\0')
160                         printf("%s_%s\n", model, serial);
161                 else
162                         printf("%s\n", model);
163         }
164
165 close:
166         close(fd);
167 exit:
168         udev_unref(udev);
169         udev_log_close();
170         return rc;
171 }