summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2009-05-07 00:50:51 +0200
committerLennart Poettering <lennart@poettering.net>2009-05-07 00:50:51 +0200
commit4f1a396f3cb70bd9df081167124ff06d1fb9bdb4 (patch)
treead26f600358b515c31bfdcf006bdb323e437c2ae
parent1d7de6de9120275320c04646f4bb5905802411dd (diff)
allow prefixing device strings with access methods
-rw-r--r--atasmart.c94
1 files changed, 77 insertions, 17 deletions
diff --git a/atasmart.c b/atasmart.c
index d7113ce..1edc0f8 100644
--- a/atasmart.c
+++ b/atasmart.c
@@ -69,8 +69,9 @@ typedef enum SkDiskType {
/* These three will not be autotested for */
SK_DISK_TYPE_SUNPLUS, /* SunPlus USB/ATA bridges */
SK_DISK_TYPE_JMICRON, /* JMicron USB/ATA bridges */
- SK_DISK_TYPE_BLOB,
- SK_DISK_TYPE_UNKNOWN,
+ SK_DISK_TYPE_BLOB, /* From a file */
+ SK_DISK_TYPE_NONE, /* No access method */
+ SK_DISK_TYPE_AUTO, /* We don't know yet */
_SK_DISK_TYPE_MAX,
_SK_DISK_TYPE_TEST_MAX = SK_DISK_TYPE_SUNPLUS /* only auto test until here */
} SkDiskType;
@@ -138,7 +139,7 @@ typedef enum SkSmartCommand {
SK_SMART_COMMAND_RETURN_STATUS = 0xDA
} SkSmartCommand;
-static const char *disk_type_to_string(SkDiskType type) {
+static const char *disk_type_to_human_string(SkDiskType type) {
/* %STRINGPOOLSTART% */
static const char* const map[_SK_DISK_TYPE_MAX] = {
@@ -148,7 +149,8 @@ static const char *disk_type_to_string(SkDiskType type) {
[SK_DISK_TYPE_SUNPLUS] = "Sunplus SCSI ATA Passthru",
[SK_DISK_TYPE_JMICRON] = "JMicron SCSI ATA Passthru",
[SK_DISK_TYPE_BLOB] = "Blob",
- [SK_DISK_TYPE_UNKNOWN] = "Unknown"
+ [SK_DISK_TYPE_AUTO] = "Automatic",
+ [SK_DISK_TYPE_NONE] = "None"
};
/* %STRINGPOOLSTOP% */
@@ -158,6 +160,55 @@ static const char *disk_type_to_string(SkDiskType type) {
return _P(map[type]);
}
+static const char *disk_type_to_prefix_string(SkDiskType type) {
+
+ /* %STRINGPOOLSTART% */
+ static const char* const map[_SK_DISK_TYPE_MAX] = {
+ [SK_DISK_TYPE_ATA_PASSTHROUGH_16] = "sat16",
+ [SK_DISK_TYPE_ATA_PASSTHROUGH_12] = "sat12",
+ [SK_DISK_TYPE_LINUX_IDE] = "linux-ide",
+ [SK_DISK_TYPE_SUNPLUS] = "sunplus",
+ [SK_DISK_TYPE_JMICRON] = "jmicron",
+ [SK_DISK_TYPE_NONE] = "none",
+ [SK_DISK_TYPE_AUTO] = "auto",
+ };
+ /* %STRINGPOOLSTOP% */
+
+ if (type >= _SK_DISK_TYPE_MAX)
+ return NULL;
+
+ return _P(map[type]);
+}
+
+static const char *disk_type_from_string(const char *s, SkDiskType *type) {
+ unsigned u;
+
+ assert(s);
+ assert(type);
+
+ for (u = 0; u < _SK_DISK_TYPE_MAX; u++) {
+ const char *t;
+ size_t l;
+
+ if (!(t = disk_type_to_prefix_string(u)))
+ continue;
+
+ l = strlen(t);
+
+ if (strncmp(s, t, l))
+ continue;
+
+ if (s[l] != ':')
+ continue;
+
+ *type = u;
+
+ return s + l + 1;
+ }
+
+ return NULL;
+}
+
static SkBool disk_smart_is_available(SkDisk *d) {
return d->identify_valid && !!(d->identify[164] & 1);
}
@@ -640,7 +691,8 @@ static int disk_command(SkDisk *d, SkAtaCommand command, SkDirection direction,
[SK_DISK_TYPE_SUNPLUS] = disk_sunplus_command,
[SK_DISK_TYPE_JMICRON] = disk_jmicron_command,
[SK_DISK_TYPE_BLOB] = NULL,
- [SK_DISK_TYPE_UNKNOWN] = NULL
+ [SK_DISK_TYPE_AUTO] = NULL,
+ [SK_DISK_TYPE_NONE] = NULL
};
assert(d);
@@ -2066,7 +2118,7 @@ int sk_disk_dump(SkDisk *d) {
printf("Device: %s\n"
"Type: %s\n",
d->name ? d->name : "n/a",
- disk_type_to_string(d->type));
+ disk_type_to_human_string(d->type));
ret = sk_disk_get_size(d, &size);
if (ret >= 0)
@@ -2267,7 +2319,7 @@ static int disk_find_type(SkDisk *d, dev_t devnum) {
else if (udev_device_get_parent_with_subsystem_devtype(dev, "scsi", NULL))
d->type = SK_DISK_TYPE_ATA_PASSTHROUGH_16;
else
- d->type = SK_DISK_TYPE_UNKNOWN;
+ d->type = SK_DISK_TYPE_AUTO;
r = 0;
@@ -2293,18 +2345,25 @@ int sk_disk_open(const char *name, SkDisk **_d) {
goto fail;
}
- if (!name) {
- d->fd = -1;
+ d->fd = -1;
+ d->size = (uint64_t) -1;
+
+ if (!name)
d->type = SK_DISK_TYPE_BLOB;
- d->size = (uint64_t) -1;
- } else {
+ else {
+ const char *dn;
+
+ d->type = SK_DISK_TYPE_AUTO;
- if (!(d->name = strdup(name))) {
+ if (!(dn = disk_type_from_string(name, &d->type)))
+ dn = name;
+
+ if (!(d->name = strdup(dn))) {
errno = ENOMEM;
goto fail;
}
- if ((d->fd = open(name,
+ if ((d->fd = open(d->name,
O_RDONLY|O_NOCTTY|O_NONBLOCK
#ifdef O_CLOEXEC
|O_CLOEXEC
@@ -2335,16 +2394,17 @@ int sk_disk_open(const char *name, SkDisk **_d) {
}
/* OK, it's a real block device with a size. Now let's find the suitable API */
- if ((ret = disk_find_type(d, st.st_rdev)) < 0)
- goto fail;
+ if (d->type == SK_DISK_TYPE_AUTO)
+ if ((ret = disk_find_type(d, st.st_rdev)) < 0)
+ goto fail;
- if (d->type == SK_DISK_TYPE_UNKNOWN) {
+ if (d->type == SK_DISK_TYPE_AUTO) {
/* We have no clue, so let's autotest for a working API */
for (d->type = 0; d->type < _SK_DISK_TYPE_TEST_MAX; d->type++)
if (disk_identify_device(d) >= 0)
break;
if (d->type >= _SK_DISK_TYPE_TEST_MAX)
- d->type = SK_DISK_TYPE_UNKNOWN;
+ d->type = SK_DISK_TYPE_NONE;
} else
disk_identify_device(d);