/* * devnodes.c - device inode creation functions * * Erik Troan * Matt Wilson * Peter Jones * * Copyright 1998-2005 Red Hat, Inc. * Copyright 1996-1998 Red Hat Software, Inc. * * This software may be freely redistributed under the terms of the GNU * public license. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include #include #include #include #include #include struct devnum { char * name; short major, minor; int isChar; }; static struct devnum devices[] = { { "aztcd", 29, 0, 0 }, { "pcd", 46, 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 }, { "input/mouse0", 13, 32, 1 }, { "input/mouse1", 13, 33, 1 }, { "input/mouse2", 13, 34, 1 }, { "input/mouse3", 13, 35, 1 }, { "input/event0", 13, 64, 1 }, { "input/event1", 13, 65, 1 }, { "input/event2", 13, 66, 1 }, { "input/event3", 13, 67, 1 }, { "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 }, { "psaux", 10, 1, 1 }, { "sbpcd", 25, 0, 0 }, { "sjcd", 18, 0, 0 }, { "ttyS0", 4, 64, 1 }, { "ttyS1", 4, 65, 1 }, { "ttyS2", 4, 66, 1 }, { "ttyS3", 4, 67, 1 }, }; int idemajors[] = { 3, 22, 33, 34, 56, 57, 88, 89, 90, 91 }; int numDevices = sizeof(devices) / sizeof(struct devnum); #include /* from linux/drivers/scsi/sd.c */ static int sd_major(int major_idx) { switch (major_idx) { case 0: return SCSI_DISK0_MAJOR; case 1 ... 7: return SCSI_DISK1_MAJOR + major_idx - 1; case 8 ... 15: return SCSI_DISK8_MAJOR + major_idx - 8; default: /* this shouldn't happen... but if it does, return -1 */ return -1; } } int devMakeInode(char * devName, char * path) { int i; int major, minor; int type; char *ptr; char *dir; if (!strncmp(devName, "mapper/", 7)) { struct dm_task *task; struct dm_info *info = alloca(sizeof *info); devName += 7; if (!info || !*devName) return -3; memset(info, '\0', sizeof (*info)); task = dm_task_create(DM_DEVICE_INFO); if (!task) return -3; dm_task_set_name(task, devName); i = dm_task_run(task); if (i < 0) { dm_task_destroy(task); return -3; } i = dm_task_get_info(task, info); dm_task_destroy(task); if (i < 0) { return -3; } type = S_IFBLK; major = info->major; minor = info->minor; } else if (devName[0] == 's' && devName[1] == 'd') { /* scsi devices sda - sdp: major 8, minor 0 - 255 */ /* scsi devices sdq - sdaf: major 65, minor 0 - 255 */ /* scsi devices sdqg - sdav: major 66, minor 0 - 255 */ /* etc... */ int drive = 0; char *num = NULL; type = S_IFBLK; if (devName[3] && isdigit(devName[3])) { drive = devName[2] - 'a'; num = devName + 3; } else if (devName[3] && islower(devName[3])) { drive = ((devName[2] - 'a' + 1) * 26) + devName[3] - 'a'; num = devName + 4; } else drive = devName[2] - 'a'; major = sd_major((drive & 0xf0) >> 4); if (major < 0) return major; minor = (drive * 16) % 256; minor += (drive & 0xfff00); if (num && num[0] && num[1]) minor += (num[0] - '0') * 10 + (num[1] - '0'); else if (num && num[0]) minor += (num[0] - '0'); } else if (devName[0] == 'm' && devName[1] == 'd') { type = S_IFBLK; major = 9; minor = atoi(devName + 2); } else if (devName[0] == 'x' && devName[1] == 'v' && devName[2] == 'd') { /* xen xvd devices */ type = S_IFBLK; major = 202; minor = ( devName[3] - 'a' ) * 16; if (devName[4] && isdigit(devName[4])) { minor += devName[4] - '0'; } } else if (devName[0] == 'u' && devName[1] == 'b') { /* usb block (ub) devices */ type = S_IFBLK; major = 180; minor = ( devName[2] - 'a' ) * 8; if (devName[3] && isdigit(devName[3])) { minor += devName[3] - '0'; } } else if (devName[0] == 's' && devName[1] == 'g') { type = S_IFBLK; major = 21; minor = atoi(devName + 2); } else if (!strncmp(devName, "loop", 4)) { type = S_IFBLK; major = 7; minor = atoi(devName + 4); } else if (!strncmp(devName, "scd", 3)) { type = S_IFBLK; major = 11; minor = atoi(devName + 3); } else if (devName[0] == 'h' && devName[1] == 'd') { int drive = 0; type = S_IFBLK; drive = devName[2] - 'a'; if (drive > 19) return -1; major = idemajors[drive/2]; minor = (drive % 2) * 64; if (devName[3] && devName[4]) minor += (devName[3] - '0') * 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'; #if defined (__s390__) || defined (__s390x__) } else if (!strncmp(devName, "dasd", 4) && strlen(devName) > 4) { /* IBM Dasd Drives */ type = S_IFBLK; major = 94; minor = ( devName[4] - 'a' ) * 4; if (devName[5] && isalpha(devName[5])) { minor += 26 * 4 + ( devName[5] - 'a' ) * 4; if (devName[6] && isdigit(devName[6]) ) minor += devName[6] - '0'; } else if (devName[5] && isdigit(devName[5])) { minor += devName[5] - '0'; } } else if (!strncmp(devName, "mnd", 4)) { /* IBM MiniDisk Drives */ type = S_IFBLK; major = 95; minor = devName[3] - 'a'; #endif } else if (!strncmp(devName, "rd/", 3)) { /* dac 960 "/rd/c0d0{p1}" */ int c, d, p, e; c = d = p = 0; e = sscanf(devName + 3, "c%dd%dp%d", &c, &d, &p); type = S_IFBLK; major = 48 + c; /* controller */ minor = d * 8; /* disk */ minor += p; /* partition */ } else if (!strncmp(devName, "ida/", 4)) { /* Compaq Smart Array "ida/c0d0{p1} */ int c, d, p, e; c = d = p = 0; e = sscanf(devName + 4, "c%dd%dp%d", &c, &d, &p); type = S_IFBLK; major = 72 + c; /* controller */ minor = d * 16; /* disk */ minor += p; /* partition */ } else if (!strncmp(devName, "cciss/", 6)) { /* Compaq Smart Array 5300 "cciss/c0d0{p1} */ int c, d, p, e; c = d = p = 0; e = sscanf(devName + 6, "c%dd%dp%d", &c, &d, &p); type = S_IFBLK; major = 104 + c; /* controller */ minor = d * 16; /* disk */ minor += p; /* partition */ } else if (!strncmp(devName, "ataraid/", 8)) { type = S_IFBLK; major = 114; /* controller */ minor = (devName[9] - '0') * 16; /* disk */ if (strlen(devName) > 10) /* partition */ minor += atoi(devName + 11); } else if (!strncmp(devName, "sx8/", 4)) { /* Promise SX8 "sx8/0{p1} */ int d, p, e; d = p = 0; e = sscanf(devName + 4, "%dp%d", &d, &p); type = S_IFBLK; major = 160 + (d/8); /* controller */ minor = (d % 8) * 32; /* disk */ minor += p; /* partition */ } else if (!strncmp(devName, "i2o/", 4)) { /* I2O Block Device "i2o/hda */ type = S_IFBLK; major = 80; /* controller */ minor = (devName[6] - 'a')*16; if ((devName[7]) && isdigit(devName[7])) { minor = minor + atoi(devName + 7); } } else if (!strncmp(devName, "iseries/vcd", 11)) { /* IBM virtual cdrom (iseries) */ type = S_IFBLK; major = 113; minor = devName[11] - 'a'; } else if (!strncmp(devName, "iseries/vd", 10)) { int drive = 0; char * num = NULL; /* IBM virtual disk (iseries) */ type = S_IFBLK; major = 112; if (devName[11] && isdigit(devName[11])) { drive = devName[10] - 'a'; num = devName + 11; } else if (devName[11] && islower(devName[11])) { drive = ((devName[10] - 'a' + 1) * 26) + devName[11] - 'a'; num = devName + 12; } else { drive = devName[10] - 'a'; } minor = (drive * 8); if (num && num[0]) minor += (num[0] - '0'); } 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)) < 0) return -2; return 0; }