summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--isys/cpio.c34
-rw-r--r--isys/cpio.h59
-rw-r--r--isys/devnodes.c131
-rw-r--r--isys/moduleinfo.c168
-rw-r--r--isys/otherinsmod.c129
5 files changed, 521 insertions, 0 deletions
diff --git a/isys/cpio.c b/isys/cpio.c
new file mode 100644
index 000000000..06e41502f
--- /dev/null
+++ b/isys/cpio.c
@@ -0,0 +1,34 @@
+#include <fcntl.h>
+#include <newt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <zlib.h>
+
+#include "cpio.h"
+
+int installCpioFile(FD_t fd, char * cpioName, char * outName, int inWin) {
+ struct cpioFileMapping map;
+ int rc;
+ char * failedFile;
+ CFD_t cfdbuf, *cfd = &cfdbuf;
+
+ if (outName) {
+ map.archivePath = cpioName;
+ map.fsPath = outName;
+ map.mapFlags = CPIO_MAP_PATH;
+ }
+
+ cfd->cpioIoType = cpioIoTypeGzFd;
+ cfd->cpioGzFd = gzdFdopen(fdDup(fdFileno(fd)), "r");
+
+ rc = cpioInstallArchive(cfd, outName ? &map : NULL, 1, NULL, NULL,
+ &failedFile);
+ gzdClose(cfd->cpioGzFd);
+
+ if (rc || access(outName, R_OK)) {
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/isys/cpio.h b/isys/cpio.h
new file mode 100644
index 000000000..44301aee9
--- /dev/null
+++ b/isys/cpio.h
@@ -0,0 +1,59 @@
+#ifndef H_CPIO
+#define H_CPIO
+
+#include <zlib.h>
+#define HAVE_ZLIB_H 1
+#include <rpm/rpmio.h>
+
+#define CPIO_MAP_PATH (1 << 0)
+#define CPIO_MAP_MODE (1 << 1)
+#define CPIO_MAP_UID (1 << 2)
+#define CPIO_MAP_GID (1 << 3)
+#define CPIO_FOLLOW_SYMLINKS (1 << 4) /* only for building */
+
+struct cpioFileMapping {
+ char * archivePath;
+ char * fsPath;
+ mode_t finalMode;
+ uid_t finalUid;
+ gid_t finalGid;
+ int mapFlags;
+};
+
+/* on cpio building, only "file" is filled in */
+struct cpioCallbackInfo {
+ char * file;
+ long fileSize; /* total file size */
+ long fileComplete; /* amount of file unpacked */
+ long bytesProcessed; /* bytes in archive read */
+};
+
+typedef struct CFD {
+ union {
+ FD_t _cfdu_fd;
+#define cpioFd _cfdu._cfdu_fd
+ FILE * _cfdu_fp;
+#define cpioFp _cfdu._cfdu_fp
+ FD_t _cfdu_gzfd;
+#define cpioGzFd _cfdu._cfdu_gzfd
+ } _cfdu;
+ int cpioPos;
+ enum cpioIoType {
+ cpioIoTypeDebug,
+ cpioIoTypeFd,
+ cpioIoTypeFp,
+ cpioIoTypeGzFd,
+ } cpioIoType;
+} CFD_t;
+
+typedef void (*cpioCallback)(struct cpioCallbackInfo * filespec, void * data);
+
+/* librpm provides these */
+int cpioInstallArchive(CFD_t *cfd, struct cpioFileMapping * mappings,
+ int numMappings, cpioCallback cb, void * cbData,
+ char ** failedFile);
+const char *cpioStrerror(int rc);
+
+int installCpioFile(FD_t fd, char * cpioName, char * outName, int inWin);
+
+#endif
diff --git a/isys/devnodes.c b/isys/devnodes.c
new file mode 100644
index 000000000..97ab2c3c9
--- /dev/null
+++ b/isys/devnodes.c
@@ -0,0 +1,131 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <unistd.h>
+
+struct devnum {
+ char * name;
+ short major, minor;
+ int isChar;
+};
+
+static struct devnum devices[] = {
+ { "aztcd", 29, 0, 0 },
+ { "bpcd", 41, 0, 0 },
+ { "cdu31a", 15, 0, 0 },
+ { "cdu535", 24, 0, 0 },
+ { "cm206cd", 32, 0, 0 },
+ { "fd0", 2, 0, 0 },
+ { "fd1", 2, 1, 0 },
+ { "gscd", 16, 0, 0 },
+ { "lp0", 6, 0, 1 },
+ { "lp1", 6, 1, 1 },
+ { "lp2", 6, 2, 1 },
+ { "mcd", 23, 0, 0 },
+ { "mcdx", 20, 0, 0 },
+ { "nst0", 9, 128, 1 },
+ { "optcd", 17, 0, 0 },
+ { "sbpcd", 25, 0, 0 },
+ { "scd0", 11, 0, 0 },
+ { "scd1", 11, 1, 0 },
+ { "sjcd", 18, 0, 0 },
+};
+
+int numDevices = sizeof(devices) / sizeof(struct devnum);
+
+int devMakeInode(char * devName, char * path) {
+ int i;
+ int major, minor;
+ int type;
+ char *ptr;
+ char *dir;
+
+ if (devName[0] == 's' && devName[1] == 'd') {
+ type = S_IFBLK;
+ major = 8;
+ minor = (devName[2] - 'a') << 4;
+ if (devName[3] && devName[4])
+ minor += 10 + (devName[4] - '0');
+ else if (devName[3])
+ minor += (devName[3] - '0');
+ } else if (devName[0] == 'h' && devName[1] == 'd') {
+ type = S_IFBLK;
+ if (devName[2] == 'a')
+ major = 3, minor = 0;
+ else if (devName[2] == 'b')
+ major = 3, minor = 64;
+ else if (devName[2] == 'c')
+ major = 22, minor = 0;
+ else if (devName[2] == 'd')
+ major = 22, minor = 64;
+ else if (devName[2] == 'e')
+ major = 33, minor = 0;
+ else if (devName[2] == 'f')
+ major = 33, minor = 64;
+ else if (devName[2] == 'g')
+ major = 34, minor = 0;
+ else if (devName[2] == 'h')
+ major = 34, minor = 64;
+ else
+ return -1;
+
+ if (devName[3] && devName[4])
+ minor += 10 + (devName[4] - '0');
+ else if (devName[3])
+ minor += (devName[3] - '0');
+ } else if (!strncmp(devName, "ram", 3)) {
+ type = S_IFBLK;
+ major = 1;
+ minor = 1;
+ if (devName[3])
+ minor += devName[3] - '1';
+ } else if (!strncmp(devName, "rd/", 3)) {
+ /* dac 960 "/rd/c0d0{p1}" */
+ type = S_IFBLK;
+ major = 48 + devName[4] - '0'; /* controller */
+ minor = (devName[6] - '0') * 8; /* disk */
+ if (strlen(devName) > 7) /* partition */
+ minor += devName[8] - '0';
+ } else if (!strncmp(devName, "ida/", 4)) {
+ /* Compaq Smart Array "ida/c0d0{p1} */
+ type = S_IFBLK;
+ major = 72; /* controller */
+ minor = (devName[7] - '0') * 16; /* disk */
+ if (strlen(devName) > 8) /* partition */
+ minor += atoi(devName + 9);
+ } else {
+ for (i = 0; i < numDevices; i++) {
+ if (!strcmp(devices[i].name, devName)) break;
+ }
+ if (i == numDevices) return -1;
+ major = devices[i].major;
+ minor = devices[i].minor;
+
+ if (devices[i].isChar)
+ type = S_IFCHR;
+ else
+ type = S_IFBLK;
+ }
+
+ ptr = path;
+ i = 0;
+ while (*ptr)
+ if (*ptr++ == '/')
+ i++;
+ if (i > 2) {
+ dir = alloca(strlen(path) + 1);
+ strcpy(dir, path);
+ ptr = dir + (strlen(path) - 1);
+ while (*ptr != '/')
+ *ptr-- = '\0';
+ mkdir(dir, 0644);
+ }
+
+ unlink(path);
+ if (mknod(path, type | 0600, makedev(major, minor))) {
+ return -2;
+ }
+
+ return 0;
+}
diff --git a/isys/moduleinfo.c b/isys/moduleinfo.c
new file mode 100644
index 000000000..afc646026
--- /dev/null
+++ b/isys/moduleinfo.c
@@ -0,0 +1,168 @@
+#include <alloca.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "isys.h"
+
+struct moduleInfo * moduleList = NULL;
+int numModules = 0;
+
+struct moduleInfo * isysGetModuleList(enum driverMajor major) {
+ struct moduleInfo * miList, * next;
+ int i;
+
+ next = miList = malloc(sizeof(*miList) * numModules + 1);
+ for (i = 0; i < numModules; i++) {
+ if (moduleList[i].major == major || major == DRIVER_NONE) {
+ *next = moduleList[i];
+ next++;
+ }
+ }
+
+ if (next == miList) {
+ free(next);
+ return NULL;
+ }
+
+ next->moduleName = NULL;
+ next++;
+
+ miList = realloc(miList, sizeof(*miList) * (next - miList));
+ return miList;
+}
+
+struct moduleInfo * isysFindModuleInfo(const char * moduleName) {
+ int i;
+
+ for (i = 0; i < numModules; i++)
+ if (!strcmp(moduleName, moduleList[i].moduleName))
+ return moduleList + i;
+
+ return NULL;
+}
+
+int isysReadModuleInfo(const char * filename) {
+ int fd, isIndented;
+ char * buf, * start, * next, * chptr;
+ struct stat sb;
+ char oldch;
+ struct moduleInfo * nextModule;
+ int modulesAlloced;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) return -1;
+
+ fstat(fd, &sb);
+ buf = alloca(sb.st_size + 1);
+ read(fd, buf, sb.st_size);
+ buf[sb.st_size] = '\0';
+ close(fd);
+
+ nextModule = moduleList;
+ modulesAlloced = numModules;
+
+ if (strncmp(buf, "Version 0\n", 10)) return -1;
+
+ start = buf + 10;
+ while (start && *start) {
+ chptr = strchr(start, '\n');
+ if (chptr) {
+ /* slice and dice */
+ next = chptr + 1;
+ } else {
+ chptr + strlen(start) - 1;
+ }
+
+ chptr--;
+ while (isspace(*chptr)) chptr--;
+ chptr++;
+ *chptr = '\0';
+
+ isIndented = 0;
+ if (isspace(*start)) {
+ while (isspace(*start) && *start != '\n') start++;
+ isIndented = 1;
+ }
+
+ if (*start != '\n' && *start && *start != '#') {
+ if (!isIndented) {
+ if (nextModule && nextModule->moduleName) numModules++;
+
+ if (numModules == modulesAlloced) {
+ modulesAlloced += 5;
+ moduleList = realloc(moduleList,
+ modulesAlloced * sizeof(*moduleList));
+ }
+ nextModule = moduleList + numModules;
+ nextModule->moduleName = strdup(start);
+ nextModule->major = DRIVER_NONE;
+ nextModule->minor = DRIVER_MINOR_NONE;
+ nextModule->description = NULL;
+ nextModule->args = NULL;
+ nextModule->numArgs = 0;
+ } else if (nextModule->major == DRIVER_NONE) {
+ chptr = start + strlen(start) - 1;
+ while (!isspace(*chptr) && chptr > start) chptr--;
+ if (chptr != start) chptr++;
+
+ if (!strcmp(chptr, "eth")) {
+ nextModule->major = DRIVER_NET;
+ nextModule->minor = DRIVER_MINOR_ETHERNET;
+ } else if (!strcmp(chptr, "tr")) {
+ nextModule->major = DRIVER_NET;
+ nextModule->minor = DRIVER_MINOR_TR;
+ } else if (!strcmp(chptr, "plip")) {
+ nextModule->major = DRIVER_NET;
+ nextModule->minor = DRIVER_MINOR_PLIP;
+ } else if (!strcmp(chptr, "scsi_hostadapter")) {
+ nextModule->major = DRIVER_SCSI;
+ } else if (!strcmp(chptr, "cdrom")) {
+ nextModule->major = DRIVER_CDROM;
+ }
+ } else if (!nextModule->description) {
+ chptr = start + strlen(start) - 1;
+ if (*start == '"' && *chptr == '"') {
+ start++;
+ chptr--;
+ *chptr = '\0';
+ nextModule->description = strdup(start);
+ }
+ } else {
+ nextModule->args = realloc(nextModule->args,
+ sizeof(*nextModule->args) * (nextModule->numArgs + 1));
+ chptr = start;
+ while (!isspace(*chptr) && *chptr) chptr++;
+ if (*chptr) {
+ oldch = *chptr;
+ *chptr = '\0';
+ nextModule->args[nextModule->numArgs].arg = strdup(start);
+
+ start = chptr + 1;
+ while (*start && isspace(*start)) start++;
+
+ if (*start == '"') {
+ start++;
+ chptr = strchr(start, '"');
+ if (chptr) {
+ *chptr = '\0';
+ nextModule->args[nextModule->numArgs].description =
+ strdup(start);
+ nextModule->numArgs++;
+ }
+ }
+ }
+ }
+ }
+
+ start = next;
+ }
+
+ if (nextModule && nextModule->moduleName) numModules++;
+ numModules = nextModule - moduleList;
+
+ return 0;
+}
diff --git a/isys/otherinsmod.c b/isys/otherinsmod.c
new file mode 100644
index 000000000..5cbbfae3e
--- /dev/null
+++ b/isys/otherinsmod.c
@@ -0,0 +1,129 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <zlib.h>
+#include <fcntl.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
+
+#include "cpio.h"
+#include "isys.h"
+
+/* hack */
+int insmod_main(int argc, char ** argv);
+int rmmod_main(int argc, char ** argv);
+
+int ourInsmodCommand(int argc, char ** argv) {
+ char * file;
+ char finalName[100];
+ char * chptr;
+ FD_t fd;
+ int rc, rmObj = 0;
+ int sparc64 = 0;
+#ifdef __sparc__
+
+ struct utsname u;
+
+ if (!uname(&u) && !strcmp(u.machine, "sparc64"))
+ sparc64 = 1;
+#endif
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: insmod <module>.o [params]\n");
+ return 1;
+ }
+
+ file = argv[1];
+ if (access(file, R_OK)) {
+ /* it might be having a ball */
+ fd = fdOpen(sparc64 ?
+ "/modules/modules64.cgz" : "/modules/modules.cgz",
+ O_RDONLY, 0);
+ if (fdFileno(fd) < 0) {
+ return 1;
+ }
+
+ chptr = strrchr(file, '/');
+ if (chptr) file = chptr + 1;
+ sprintf(finalName, "/tmp/%s", file);
+
+ if (installCpioFile(fd, file, finalName, 0))
+ return 1;
+
+ rmObj = 1;
+ file = finalName;
+ }
+
+ argv[1] = file;
+
+#ifdef __sparc__
+ if (sparc64) {
+ int pid, status;
+
+ if (!(pid = fork())) {
+ execv("/bin/insmod64", argv);
+ exit(-1);
+ }
+ waitpid(pid, &status, 0);
+ if (WIFEXITED(status))
+ rc = WEXITSTATUS(status);
+ else
+ rc = -1;
+ } else
+#endif
+ rc = insmod_main(argc, argv);
+
+ if (rmObj) unlink(file);
+
+ return rc;
+}
+
+int rmmod(char * modName) {
+ pid_t child;
+ int status;
+ char * argv[] = { "/bin/rmmod", modName, NULL };
+ int argc = 2;
+ int rc = 0;
+
+ if ((child = fork()) == 0) {
+ exit(rmmod_main(argc, argv));
+ }
+
+ waitpid(child, &status, 0);
+
+ if (WIFEXITED(status))
+ rc = WEXITSTATUS(status);
+ else
+ rc = -1;
+
+ return rc;
+}
+
+int insmod(char * modName, char ** args) {
+ int argc;
+ char ** argv;
+ int rc = 0;
+ pid_t child;
+ int status;
+
+ argc = 2;
+ for (argv = args; *argv; argv++, argc++);
+
+ argv = malloc(sizeof(*argv) * (argc + 1));
+ argv[0] = "/bin/insmod";
+ argv[1] = modName;
+ memcpy(argv + 2, args, argc - 1);
+
+ if ((child = fork()) == 0) {
+ exit(ourInsmodCommand(argc, argv));
+ }
+
+ waitpid(child, &status, 0);
+
+ if (WIFEXITED(status))
+ rc = WEXITSTATUS(status);
+ else
+ rc = -1;
+
+ return rc;
+}