summaryrefslogtreecommitdiffstats
path: root/sys-utils/eject.c
diff options
context:
space:
mode:
authorKarel Zak2014-12-02 11:00:19 +0100
committerKarel Zak2014-12-02 11:00:19 +0100
commitbc265f7cfa1018df129336bd79bb6817d335be5f (patch)
treec3c373a5d79ed454d2e2e1b6df2944652df97ed3 /sys-utils/eject.c
parentlib/sysfs: add subsystem and hotplug detection (diff)
downloadkernel-qcow2-util-linux-bc265f7cfa1018df129336bd79bb6817d335be5f.tar.gz
kernel-qcow2-util-linux-bc265f7cfa1018df129336bd79bb6817d335be5f.tar.xz
kernel-qcow2-util-linux-bc265f7cfa1018df129336bd79bb6817d335be5f.zip
eject: use sysfs API to detect hotplug
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'sys-utils/eject.c')
-rw-r--r--sys-utils/eject.c106
1 files changed, 1 insertions, 105 deletions
diff --git a/sys-utils/eject.c b/sys-utils/eject.c
index 0dfd30166..a816b208f 100644
--- a/sys-utils/eject.c
+++ b/sys-utils/eject.c
@@ -71,17 +71,6 @@
*/
#define TRAY_WAS_ALREADY_OPEN_USECS 200000 /* about 0.2 seconds */
-/* eject(1) is able to eject only 'removable' devices (attribute in /sys)
- * _or_ devices connected by hotplug subsystem.
- */
-static const char * const hotplug_subsystems[] = {
- "usb",
- "ieee1394",
- "pcmcia",
- "mmc",
- "ccw"
-};
-
struct eject_control {
struct libmnt_table *mtab;
char *device; /* device or mount point to be ejected */
@@ -820,111 +809,18 @@ done:
return count;
}
-static int is_hotpluggable_subsystem(const char *name)
-{
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(hotplug_subsystems); i++)
- if (strcmp(name, hotplug_subsystems[i]) == 0)
- return 1;
-
- return 0;
-}
-
-#define SUBSYSTEM_LINKNAME "/subsystem"
-
-/*
- * For example:
- *
- * chain: /sys/dev/block/../../devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.2/ \
- * 1-1.2:1.0/host65/target65:0:0/65:0:0:0/block/sdb
- *
- * The function check if <chain>/subsystem symlink exists, if yes then returns
- * basename of the readlink result, and remove the last subdirectory from the
- * <chain> path.
- */
-static char *get_subsystem(char *chain, char *buf, size_t bufsz)
-{
- size_t len;
- char *p;
-
- if (!chain || !*chain)
- return NULL;
-
- len = strlen(chain);
- if (len + sizeof(SUBSYSTEM_LINKNAME) > PATH_MAX)
- return NULL;
-
- do {
- ssize_t sz;
-
- /* append "/subsystem" to the path */
- memcpy(chain + len, SUBSYSTEM_LINKNAME, sizeof(SUBSYSTEM_LINKNAME));
-
- /* try if subsystem symlink exists */
- sz = readlink(chain, buf, bufsz - 1);
-
- /* remove last subsystem from chain */
- chain[len] = '\0';
- p = strrchr(chain, '/');
- if (p) {
- *p = '\0';
- len = p - chain;
- }
-
- if (sz > 0) {
- /* we found symlink to subsystem, return basename */
- buf[sz] = '\0';
- return basename(buf);
- }
-
- } while (p);
-
- return NULL;
-}
-
static int is_hotpluggable(const struct eject_control *ctl)
{
struct sysfs_cxt cxt = UL_SYSFSCXT_EMPTY;
- char devchain[PATH_MAX];
- char subbuf[PATH_MAX];
dev_t devno;
int rc = 0;
- ssize_t sz;
- char *sub;
devno = sysfs_devname_to_devno(ctl->device, NULL);
if (sysfs_init(&cxt, devno, NULL) != 0)
return 0;
- /* check /sys/dev/block/<maj>:<min>/removable attribute */
- if (sysfs_read_int(&cxt, "removable", &rc) == 0 && rc == 1) {
- verbose(ctl, _("%s: is removable device"), ctl->device);
- goto done;
- }
-
- /* read /sys/dev/block/<maj>:<min> symlink */
- sz = sysfs_readlink(&cxt, NULL, devchain, sizeof(devchain));
- if (sz <= 0 || sz + sizeof(_PATH_SYS_DEVBLOCK "/") > sizeof(devchain))
- goto done;
-
- devchain[sz++] = '\0';
-
- /* create absolute patch from the link */
- memmove(devchain + sizeof(_PATH_SYS_DEVBLOCK "/") - 1, devchain, sz);
- memcpy(devchain, _PATH_SYS_DEVBLOCK "/",
- sizeof(_PATH_SYS_DEVBLOCK "/") - 1);
+ rc = sysfs_is_hotpluggable(&cxt);
- while ((sub = get_subsystem(devchain, subbuf, sizeof(subbuf)))) {
- rc = is_hotpluggable_subsystem(sub);
- if (rc) {
- verbose(ctl, _("%s: connected by hotplug subsystem: %s"),
- ctl->device, sub);
- break;
- }
- }
-
-done:
sysfs_deinit(&cxt);
return rc;
}