#include #include #include #include #include #include #include #include #include #include "devices.h" #include "hd.h" #include "intl.h" #include "install.h" #include "log.h" #include "scsi.h" static int scsiChoicePanel(int * addSCSI); static int scsiChoicePanel(int * addSCSI) { int rc; rc = newtWinTernary(_("SCSI Configuration"), _("No"), _("Yes"), _("Back"), _("Do you have any SCSI adapters?")); if (rc == 3) return INST_CANCEL; else if (rc == 2) *addSCSI = 1; else *addSCSI = 0; return 0; } int setupSCSIInterfaces(int forceConfig, struct driversLoaded ** dl) { int rc; int hasscsi; /* if this fails, autoprobe didn't work but we should keep going */ rc = loadDeviceDriver(DRIVER_SCSI, dl, 1); if (!rc || kickstart) return 0; if (rc == INST_CANCEL) return INST_CANCEL; /* we may have something already available as well */ if (scsiDeviceAvailable()) return 0; if (forceConfig) { return loadDeviceDriver(DRIVER_SCSI, dl, 0); } do { if (scsiChoicePanel(&hasscsi) == INST_CANCEL) return INST_CANCEL; if (!hasscsi) return 0; rc = loadDeviceDriver(DRIVER_SCSI, dl, 0); if (rc == INST_ERROR) return INST_ERROR; } while (rc); return 0; } int scsiDeviceAvailable(void) { int fd; char buf[80]; int i; fd = open("/proc/scsi/scsi", O_RDONLY); if (fd < 0) { logMessage("failed to open /proc/scsi/scsi: %s", strerror(errno)); return 0; } i = read(fd, buf, sizeof(buf) - 1); if (i < 1) { logMessage("failed to read /proc/scsi/scsi: %s", strerror(errno)); return 0; } close(fd); buf[i] = '\0'; logMessage("/proc/scsi/scsi: %s", buf); if (strstr(buf, "devices: none")) { logMessage("no scsi devices are available"); return 0; } logMessage("scsi devices are available"); return 1; } #define SCSISCSI_TOP 0 #define SCSISCSI_HOST 1 #define SCSISCSI_VENDOR 2 #define SCSISCSI_TYPE 3 int scsiGetDevices(struct deviceInfo ** sdiPtr) { int fd; char buf[16384]; char linebuf[80]; char typebuf[10]; int i, state = SCSISCSI_TOP; char * start, * chptr, * next, *end; char driveName = 'a'; char cdromNum = '0'; char tapeNum = '0'; int numMatches = 0; struct deviceInfo * sdi; int id = 0; /* FIXME: this should be big enough */ sdi = malloc(sizeof(*sdi) * 65); fd = open("/proc/scsi/scsi", O_RDONLY); if (fd < 0) { logMessage("failed to open /proc/scsi/scsi: %s", strerror(errno)); return 1; } i = read(fd, buf, sizeof(buf) - 1); if (i < 1) { logMessage("failed to read /proc/scsi/scsi: %s", strerror(errno)); return 1; } close(fd); buf[i] = '\0'; start = buf; while (*start) { chptr = start; while (*chptr != '\n') chptr++; *chptr = '\0'; next = chptr + 1; switch (state) { case SCSISCSI_TOP: if (strcmp("Attached devices: ", start)) { logMessage("unexpected line in /proc/scsi/scsi: %s", start); free(sdi); return INST_ERROR; } state = SCSISCSI_HOST; break; case SCSISCSI_HOST: if (strncmp("Host: ", start, 6)) { logMessage("unexpected line in /proc/scsi/scsi: %s", start); free(sdi); return INST_ERROR; } start = strstr(start, "Id: "); if (!start) { logMessage("Id: missing in /proc/scsi/scsi"); return INST_ERROR; } start += 4; id = strtol(start, NULL, 10); state = SCSISCSI_VENDOR; break; case SCSISCSI_VENDOR: if (strncmp(" Vendor: ", start, 10)) { logMessage("unexpected line in /proc/scsi/scsi: %s", start); free(sdi); return INST_ERROR; } start += 10; end = chptr = strstr(start, "Model:"); if (!chptr) { logMessage("Model missing in /proc/scsi/scsi"); free(sdi); return INST_ERROR; } chptr--; while (*chptr == ' ') chptr--; *(chptr + 1) = '\0'; strcpy(linebuf, start); *linebuf = toupper(*linebuf); chptr = linebuf + 1; while (*chptr) { *chptr = tolower(*chptr); chptr++; } start = end; /* beginning of "Model:" */ start += 7; chptr = strstr(start, "Rev:"); if (!chptr) { logMessage("Rev missing in /proc/scsi/scsi"); free(sdi); return INST_ERROR; } chptr--; while (*chptr == ' ') chptr--; *(chptr + 1) = '\0'; strcat(linebuf, " "); strcat(linebuf, start); state = SCSISCSI_TYPE; break; case SCSISCSI_TYPE: if (strncmp(" Type:", start, 7)) { logMessage("unexpected line in /proc/scsi/scsi: %s", start); free(sdi); return INST_ERROR; } *typebuf = '\0'; if (strstr(start, "Direct-Access")) { sprintf(typebuf, "sd%c", driveName++); sdi[numMatches].type = DEVICE_HD; } else if (strstr(start, "Sequential-Access")) { sprintf(typebuf, "st%c", tapeNum++); sdi[numMatches].type = DEVICE_TAPE; } else if (strstr(start, "CD-ROM")) { sprintf(typebuf, "scd%c", cdromNum++); sdi[numMatches].type = DEVICE_CDROM; } if (*typebuf) { /*sdi = realloc(sdi, sizeof(*sdi) * (numMatches + 2));*/ sdi[numMatches].deviceName = strdup(typebuf); sdi[numMatches].info = strdup(linebuf); sdi[numMatches].bus = 0; sdi[numMatches++].id = id; } state = SCSISCSI_HOST; } start = next; } sdi[numMatches].deviceName = NULL; sdi[numMatches].info = NULL; sdi = realloc(sdi, sizeof(*sdi) * (numMatches + 1)); *sdiPtr = sdi; return 0; } /* normal string handling doesn't work here as the syslog can contain binary 0's! */ int ideGetDevices(struct deviceInfo ** idiPtr) { struct deviceInfo * idi; struct stat sb; char * filename = testing ? "/var/log/dmesg" : "/tmp/syslog"; char * buf, * end; char * absend; int numMatches = 0; int fd; int base = testing ? 0 : 3; idi = malloc(sizeof(*idi) * 9); if (stat(filename, &sb)) { newtWinMessage("Error", "Ok", "Failed to stat %s: %s\n", filename, strerror(errno)); return 0; } if ((fd = open(filename, O_RDONLY)) < 0) { newtWinMessage("Error", "Ok", "Failed to open %s: %s\n", filename, strerror(errno)); return INST_ERROR; } buf = alloca(sb.st_size); read(fd, buf, sb.st_size); close(fd); absend = buf + sb.st_size; while (buf && buf < absend) { if (buf[0 + base] == 'h' && buf[1 + base] == 'd' && buf[3 + base] == ':') { idi[numMatches].deviceName = malloc(4); strcpy(idi[numMatches].deviceName, "hda"); idi[numMatches].deviceName[2] = buf[2 + base]; buf += 5 + base; end = buf; while (*end != '\n' && *end != ',') end++; if (*end == ',') { idi[numMatches].info = malloc(end - buf + 1); strncpy(idi[numMatches].info, buf, end - buf); idi[numMatches].info[end - buf] = '\0'; /* see if this is a cdrom or not */ while (*end != '\n' && strncmp(end, "CDROM", 5) && strncmp(end, "TAPE", 4) && strncmp(end, "FLOPPY", 6) && strncmp(end, "CHS", 3)) end++; if (!strncmp(end, "CDROM", 5)) idi[numMatches].type = DEVICE_CDROM; else if (!strncmp(end, "TAPE", 4)) idi[numMatches].type = DEVICE_TAPE; else if (!strncmp(end, "FLOPPY", 6)) idi[numMatches].type = DEVICE_FD; else if (!strncmp(end, "CHS", 3)) idi[numMatches].type = DEVICE_HD; else idi[numMatches].type = DEVICE_NONE; /* we could do better here */ idi[numMatches].bus = idi[numMatches].id = 0; if (idi[numMatches].type != DEVICE_NONE) numMatches++; } } end = memchr(buf, '\n', absend - buf); if (!end) buf = NULL; else buf = end + 1; } idi[numMatches].deviceName = NULL; idi[numMatches].info = NULL; idi = realloc(idi, sizeof(*idi) * (numMatches + 1)); *idiPtr = idi; return 0; }