aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwiktor w brodlo <wiktor@brodlo.net>2011-06-15 16:59:54 +0000
committerwiktor w brodlo <wiktor@brodlo.net>2011-06-15 16:59:54 +0000
commit2590d96369d0217e31dc2812690dde61dac417b5 (patch)
tree82276f787b08a28548e342c7921486f1acefab9f /isys/devices.c
parentfirst commit (diff)
downloadanaconda-2590d96369d0217e31dc2812690dde61dac417b5.tar.gz
anaconda-2590d96369d0217e31dc2812690dde61dac417b5.tar.bz2
anaconda-2590d96369d0217e31dc2812690dde61dac417b5.zip
Initial import from Sabayon (ver 0.9.9.56)
Diffstat (limited to 'isys/devices.c')
-rw-r--r--isys/devices.c217
1 files changed, 217 insertions, 0 deletions
diff --git a/isys/devices.c b/isys/devices.c
new file mode 100644
index 0000000..98c8769
--- /dev/null
+++ b/isys/devices.c
@@ -0,0 +1,217 @@
+/*
+ * 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 <limits.h>
+
+#include "devices.h"
+
+/* for 'disks', to filter out weird stuff */
+#define MINIMUM_INTERESTING_SIZE 32*1024 /* 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;
+
+ 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, 63) <= 0) {
+ close(fd);
+ continue;
+ }
+
+ close(fd);
+ errno = 0;
+ caps = strtol(buf, NULL, 16);
+
+ if ((errno == ERANGE && (caps == LONG_MIN || caps == LONG_MAX)) ||
+ (errno != 0 && caps == 0)) {
+ return NULL;
+ }
+
+ 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, 63) <= 0) {
+ close(fd);
+ continue;
+ }
+
+ close(fd);
+ errno = 0;
+ size = strtol(buf, NULL, 10);
+
+ if ((errno == ERANGE && (size == LONG_MIN ||
+ size == LONG_MAX)) ||
+ (errno != 0 && size == 0)) {
+ return NULL;
+ }
+
+ if (size < MINIMUM_INTERESTING_SIZE)
+ continue;
+ }
+
+ new = calloc(1, sizeof(struct device));
+ new->device = strdup(ent->d_name);
+ /* FIXME */
+ if (asprintf(&new->description, "Storage device %s",
+ new->device) == -1) {
+ fprintf(stderr, "%s: %d: %s\n", __func__, __LINE__,
+ strerror(errno));
+ fflush(stderr);
+ abort();
+ }
+ 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, 63) <= 0) {
+ close(fd);
+ continue;
+ }
+
+ close(fd);
+ errno = 0;
+ type = strtol(buf, NULL, 10);
+
+ if ((errno == ERANGE && (type == LONG_MIN || type == LONG_MAX)) ||
+ (errno != 0 && type == 0)) {
+ return NULL;
+ }
+
+ if (type != 1)
+ continue;
+
+ new = calloc(1, sizeof(struct device));
+ new->device = strdup(ent->d_name);
+ /* FIXME */
+ snprintf(path, 64, "/sys/class/net/%s/address", ent->d_name);
+ fd = open(path, O_RDONLY);
+ if (fd != -1) {
+ memset(buf, '\0', 64);
+ if (read(fd, buf, 63) > 0) {
+ int i;
+ for (i = (strlen(buf)-1); isspace(buf[i]); i--)
+ buf[i] = '\0';
+ new->priv.hwaddr = strdup(buf);
+ }
+ }
+
+ if (new->priv.hwaddr) {
+ if (asprintf(&new->description, "Ethernet device %s - %s",
+ new->device, new->priv.hwaddr) == -1) {
+ fprintf(stderr, "%s: %d: %s\n", __func__, __LINE__,
+ strerror(errno));
+ fflush(stderr);
+ abort();
+ }
+ } else {
+ if (asprintf(&new->description, "Ethernet device %s",
+ new->device) == -1) {
+ fprintf(stderr, "%s: %d: %s\n", __func__, __LINE__,
+ strerror(errno));
+ fflush(stderr);
+ abort();
+ }
+ }
+
+ ret = realloc(ret, (numdevices+2) * sizeof(struct device));
+ ret[numdevices] = new;
+ ret[numdevices+1] = NULL;
+ numdevices++;
+ }
+ }
+netdone:
+ return ret;
+}
+