Systemd/extras/ata_id/ata_id.c
David Zeuthen ad88f9409a *_id: add model/vendor enc strings
So ID_MODEL and ID_VENDOR are pretty useful keys. However since we fix
them up (removing leading/trailing whitespace, converts spaces to
underscores) for use in device naming etc. we also force these fixups on
the desktop shell. And this looks pretty ugly.

The attached patch introduces the ID_MODEL_ENC and ID_VENDOR_ENC keys
that contains the encoded version of the raw strings obtained. It's
pretty similar in spirit to ID_FS_LABEL and its cousin ID_FS_LABEL_ENC.

With this patch a desktop shell can fix up these strings as it sees fit.
Note that some fixup is still needed though, for example

# /lib/udev/ata_id --export /dev/sda |grep ID_MODEL
ID_MODEL=INTEL_SSDSA2MH080G1GC
ID_MODEL_ENC=INTEL\x20SSDSA2MH080G1GC\x20\x20\x20\x20\x20\x20\x20\x20
\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20

Note the trailing and leading whitespace. Anyway with the attached patch
the desktop shell should be able to display "INTEL SSDSA2MH080G1GC"
rather than "INTEL_SSDSA2MH080G1GC" to the user.
2009-02-17 21:45:43 +01:00

170 lines
3.8 KiB
C

/*
* ata_id - reads product/serial number from ATA drives
*
* Copyright (C) 2005-2008 Kay Sievers <kay.sievers@vrfy.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/types.h>
#include <linux/hdreg.h>
#include "../../udev/udev.h"
static void log_fn(struct udev *udev, int priority,
const char *file, int line, const char *fn,
const char *format, va_list args)
{
vsyslog(priority, format, args);
}
int main(int argc, char *argv[])
{
struct udev *udev;
struct hd_driveid id;
char model[41];
char model_enc[256];
char serial[21];
char revision[9];
const char *node = NULL;
int export = 0;
int fd;
int rc = 0;
static const struct option options[] = {
{ "export", no_argument, NULL, 'x' },
{ "help", no_argument, NULL, 'h' },
{}
};
udev = udev_new();
if (udev == NULL)
goto exit;
logging_init("ata_id");
udev_set_log_fn(udev, log_fn);
while (1) {
int option;
option = getopt_long(argc, argv, "xh", options, NULL);
if (option == -1)
break;
switch (option) {
case 'x':
export = 1;
break;
case 'h':
printf("Usage: ata_id [--export] [--help] <device>\n"
" --export print values as environment keys\n"
" --help print this help text\n\n");
default:
rc = 1;
goto exit;
}
}
node = argv[optind];
if (node == NULL) {
err(udev, "no node specified\n");
rc = 1;
goto exit;
}
fd = open(node, O_RDONLY|O_NONBLOCK);
if (fd < 0) {
err(udev, "unable to open '%s'\n", node);
rc = 1;
goto exit;
}
if (ioctl(fd, HDIO_GET_IDENTITY, &id)) {
if (errno == ENOTTY) {
info(udev, "HDIO_GET_IDENTITY unsupported for '%s'\n", node);
rc = 2;
} else {
err(udev, "HDIO_GET_IDENTITY failed for '%s'\n", node);
rc = 3;
}
goto close;
}
memcpy (model, id.model, 40);
model[40] = '\0';
udev_util_encode_string(model, model_enc, sizeof(model_enc));
udev_util_replace_whitespace((char *) id.model, model, 40);
udev_util_replace_chars(model, NULL);
udev_util_replace_whitespace((char *) id.serial_no, serial, 20);
udev_util_replace_chars(serial, NULL);
udev_util_replace_whitespace((char *) id.fw_rev, revision, 8);
udev_util_replace_chars(revision, NULL);
if (export) {
if ((id.config >> 8) & 0x80) {
/* This is an ATAPI device */
switch ((id.config >> 8) & 0x1f) {
case 0:
printf("ID_TYPE=cd\n");
break;
case 1:
printf("ID_TYPE=tape\n");
break;
case 5:
printf("ID_TYPE=cd\n");
break;
case 7:
printf("ID_TYPE=optical\n");
break;
default:
printf("ID_TYPE=generic\n");
break;
}
} else {
printf("ID_TYPE=disk\n");
}
printf("ID_MODEL=%s\n", model);
printf("ID_MODEL_ENC=%s\n", model_enc);
printf("ID_SERIAL=%s\n", serial);
printf("ID_REVISION=%s\n", revision);
printf("ID_BUS=ata\n");
} else {
if (serial[0] != '\0')
printf("%s_%s\n", model, serial);
else
printf("%s\n", model);
}
close:
close(fd);
exit:
udev_unref(udev);
logging_close();
return rc;
}