]> git.ipfire.org Git - thirdparty/systemd.git/blame - extras/ata_id/ata_id.c
delete all Makefiles and move udev source to udev/
[thirdparty/systemd.git] / extras / ata_id / ata_id.c
CommitLineData
670e4705
KS
1/*
2 * ata_id - reads product/serial number from ATA drives
3 *
4 * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5 *
2321ba6f
KS
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.
670e4705
KS
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>
1aa1e248 20#include <string.h>
670e4705 21#include <errno.h>
4fa3d99d 22#include <getopt.h>
670e4705
KS
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
1aa1e248 29#include "../../udev.h"
670e4705
KS
30
31#ifdef USE_LOG
32void 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
70721db6 56static void set_str(char *to, const char *from, size_t count)
670e4705 57{
70721db6 58 size_t i, j, len;
670e4705 59
aaff09a3 60 /* strip trailing whitespace */
670e4705 61 len = strnlen(from, count);
c907c823 62 while (len && isspace(from[len-1]))
670e4705
KS
63 len--;
64
aaff09a3 65 /* strip leading whitespace */
670e4705
KS
66 i = 0;
67 while (isspace(from[i]) && (i < len))
68 i++;
69
70 j = 0;
71 while (i < len) {
aaff09a3
KS
72 /* substitute multiple whitespace */
73 if (isspace(from[i])) {
74 while (isspace(from[i]))
75 i++;
670e4705 76 to[j++] = '_';
670e4705 77 }
aaff09a3
KS
78 /* skip chars */
79 if (from[i] == '/') {
80 i++;
81 continue;
82 }
83 to[j++] = from[i++];
670e4705
KS
84 }
85 to[j] = '\0';
86}
87
88int 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;
670e4705
KS
95 int export = 0;
96 int fd;
97 int rc = 0;
4fa3d99d
KS
98 static const struct option options[] = {
99 { "export", 0, NULL, 'x' },
100 { "help", 0, NULL, 'h' },
101 {}
102 };
670e4705 103
5f84d726
KS
104 logging_init("ata_id");
105
4fa3d99d
KS
106 while (1) {
107 int option;
670e4705 108
4fa3d99d
KS
109 option = getopt_long(argc, argv, "xh", options, NULL);
110 if (option == -1)
111 break;
112
113 switch (option) {
114 case 'x':
670e4705 115 export = 1;
4fa3d99d
KS
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 }
670e4705 125 }
4fa3d99d
KS
126
127 node = argv[optind];
128 if (node == NULL) {
c70560fe 129 err("no node specified\n");
670e4705
KS
130 rc = 1;
131 goto exit;
132 }
133
3515c0ad 134 fd = open(node, O_RDONLY|O_NONBLOCK);
670e4705 135 if (fd < 0) {
c70560fe 136 err("unable to open '%s'\n", node);
670e4705
KS
137 rc = 1;
138 goto exit;
139 }
140
141 if (ioctl(fd, HDIO_GET_IDENTITY, &id)) {
cfdea0f6 142 if (errno == ENOTTY) {
c70560fe 143 info("HDIO_GET_IDENTITY unsupported for '%s'\n", node);
cfdea0f6
MS
144 rc = 2;
145 } else {
c70560fe 146 err("HDIO_GET_IDENTITY failed for '%s'\n", node);
cfdea0f6
MS
147 rc = 3;
148 }
670e4705
KS
149 goto close;
150 }
151
70721db6
KS
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);
670e4705
KS
155
156 if (export) {
aaff09a3
KS
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 }
670e4705
KS
179 printf("ID_MODEL=%s\n", model);
180 printf("ID_SERIAL=%s\n", serial);
181 printf("ID_REVISION=%s\n", revision);
46f01c6d 182 printf("ID_BUS=ata\n");
e03bce63
KS
183 } else {
184 if (serial[0] != '\0')
185 printf("%s_%s\n", model, serial);
186 else
187 printf("%s\n", model);
188 }
670e4705
KS
189
190close:
191 close(fd);
192exit:
193 logging_close();
194 return rc;
195}