summaryrefslogtreecommitdiffstats
path: root/isys/devices.c
diff options
context:
space:
mode:
authorBill Nottingham <notting@redhat.com>2007-12-20 16:32:44 -0500
committerBill Nottingham <notting@redhat.com>2007-12-20 18:11:47 -0500
commit2e6cb0d664b17c98ad6d2a6a094d99b65415be11 (patch)
tree1f387cbb194e55f72c2cbef5cfb671b5a0321cb5 /isys/devices.c
parentdaf5c641ddfd2345aaacfe77958f4c25ecbf7d78 (diff)
downloadanaconda-2e6cb0d664b17c98ad6d2a6a094d99b65415be11.tar.gz
anaconda-2e6cb0d664b17c98ad6d2a6a094d99b65415be11.tar.xz
anaconda-2e6cb0d664b17c98ad6d2a6a094d99b65415be11.zip
Add some simple hardware probing code that uses sysfs.
This is in isys because the EDD code needs it. Otherwise it would just be in the loader.
Diffstat (limited to 'isys/devices.c')
-rw-r--r--isys/devices.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/isys/devices.c b/isys/devices.c
new file mode 100644
index 000000000..47b4a8263
--- /dev/null
+++ b/isys/devices.c
@@ -0,0 +1,165 @@
+/*
+ * devices.c - various hardware probing functionality
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * 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/>.
+ *
+ * Author(s): Bill Nottingham <notting@redhat.com>
+ */
+
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "devices.h"
+
+/* for 'disks', to filter out weird stuff */
+#define MINIMUM_INTERESTING_SIZE 32*1048576 /* 32MB */
+
+/* from genhd.h, kernel side */
+#define GENHD_FL_REMOVABLE 1
+#define GENHD_FL_DRIVERFS 2
+#define GENHD_FL_MEDIA_CHANGE_NOTIFY 4
+#define GENHD_FL_CD 8
+#define GENHD_FL_UP 16
+#define GENHD_FL_SUPPRESS_PARTITION_INFO 32
+#define GENHD_FL_FAIL 64
+
+
+struct device **getDevices(enum deviceType type) {
+ struct device **ret = NULL;
+ struct device *new;
+ int numdevices = 0;
+ int rc;
+
+ if (type & (DEVICE_DISK | DEVICE_CDROM)) {
+ DIR *dir;
+ struct dirent *ent;
+
+ dir = opendir("/sys/block");
+
+ if (!dir) goto storagedone;
+
+ while ((ent = readdir(dir))) {
+ char path[64];
+ char buf[64];
+ int fd, caps, devtype;
+
+ snprintf(path, 64, "/sys/block/%s/capability", ent->d_name);
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ continue;
+ if (read(fd, buf, 64) <= 0) {
+ close(fd);
+ continue;
+ }
+ close(fd);
+ caps = strtol(buf, NULL, 16);
+ if (caps & GENHD_FL_CD)
+ devtype = DEVICE_CDROM;
+ else
+ devtype = DEVICE_DISK;
+ if (!(devtype & type))
+ continue;
+
+ if (devtype == DEVICE_DISK && !(caps & GENHD_FL_REMOVABLE)) {
+ int size;
+
+ snprintf(path, 64, "/sys/block/%s/size", ent->d_name);
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ continue;
+ if (read(fd, buf, 64) <= 0) {
+ close(fd);
+ continue;
+ }
+ close(fd);
+ size = atoi(buf);
+ if (size < MINIMUM_INTERESTING_SIZE)
+ continue;
+ }
+
+ new = calloc(1, sizeof(struct device));
+ new->device = strdup(ent->d_name);
+ /* FIXME */
+ rc = asprintf(&new->description,"Storage device %s",new->device);
+ new->type = devtype;
+ if (caps & GENHD_FL_REMOVABLE) {
+ new->priv.removable = 1;
+ }
+ ret = realloc(ret, (numdevices+2) * sizeof(struct device));
+ ret[numdevices] = new;
+ ret[numdevices+1] = NULL;
+ numdevices++;
+ }
+ }
+storagedone:
+
+ if (type & DEVICE_NETWORK) {
+ DIR *dir;
+ struct dirent *ent;
+
+ dir = opendir("/sys/class/net");
+
+ if (!dir) goto netdone;
+
+ while ((ent = readdir(dir))) {
+ char path[64];
+ int fd, type;
+ char buf[64];
+
+ snprintf(path, 64, "/sys/class/net/%s/type", ent->d_name);
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ continue;
+ if (read(fd, buf, 64) <= 0) {
+ close(fd);
+ continue;
+ }
+ close(fd);
+ type = atoi(buf);
+ if (type != 1)
+ continue;
+
+ new = calloc(1, sizeof(struct device));
+ new->device = strdup(ent->d_name);
+ /* FIXME */
+ rc = asprintf(&new->description,"Ethernet device %s",new->device);
+ snprintf(path, 64, "/sys/class/net/%s/address", ent->d_name);
+ fd = open(path, O_RDONLY);
+ if (fd != -1) {
+ if (read(fd, buf, 64) > 0) {
+ int i;
+ for (i = (strlen(buf)-1); isspace(buf[i]); i--) buf[i] = '\0';
+ new->priv.hwaddr = strdup(buf);
+ }
+ }
+ ret = realloc(ret, (numdevices+2) * sizeof(struct device));
+ ret[numdevices] = new;
+ ret[numdevices+1] = NULL;
+ numdevices++;
+ }
+ }
+netdone:
+ return ret;
+}
+