2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
10 #include <sys/cdefs.h>
11 __FBSDID("$FreeBSD$");
20 #include <sys/param.h>
21 #include <sys/disklabel.h>
22 #include <sys/diskslice.h>
24 #include <sys/diskpc98.h>
26 #include <sys/diskmbr.h>
28 #include <sys/mount.h>
30 #include <sys/sysctl.h>
36 static void msgDebug(char *, ...) __printflike(1, 2);
38 /* Clone these two from sysinstall because we need our own copies
39 * due to link order problems with `crunch'. Feh!
44 static int debug = 0; /* Allow debugger to tweak it */
49 /* Write something to the debugging port */
51 msgDebug(char *fmt, ...)
55 static int DebugFD = -1;
58 DebugFD = open(_PATH_DEV"ttyv1", O_RDWR);
59 dbg = (char *)alloca(FILENAME_MAX);
60 strcpy(dbg, "DEBUG: ");
62 vsnprintf((char *)(dbg + strlen(dbg)), FILENAME_MAX, fmt, args);
64 write(DebugFD, dbg, strlen(dbg));
68 Fixup_FreeBSD_Names(struct disk *d, struct chunk *c)
70 struct chunk *c1, *c3;
73 if (!strcmp(c->name, "X")) return 0;
75 /* reset all names to "X" */
76 for (c1 = c->part; c1; c1 = c1->next) {
78 c1->name = malloc(12);
79 if(!c1->name) return -1;
83 /* Allocate the first swap-partition we find */
84 for (c1 = c->part; c1; c1 = c1->next) {
85 if (c1->type == unused) continue;
86 if (c1->subtype != FS_SWAP) continue;
87 sprintf(c1->name, "%s%c", c->name, SWAP_PART + 'a');
91 /* Allocate the first root-partition we find */
92 for (c1 = c->part; c1; c1 = c1->next) {
93 if (c1->type == unused) continue;
94 if (!(c1->flags & CHUNK_IS_ROOT)) continue;
95 sprintf(c1->name, "%s%c", c->name, 0 + 'a');
99 /* Try to give them the same as they had before */
100 for (c1 = c->part; c1; c1 = c1->next) {
101 if (strcmp(c1->name, "X")) continue;
102 for(c3 = c->part; c3 ; c3 = c3->next)
103 if (c1 != c3 && !strcmp(c3->name, c1->oname)) {
106 strcpy(c1->name, c1->oname);
111 /* Allocate the rest sequentially */
112 for (c1 = c->part; c1; c1 = c1->next) {
113 const char order[] = "efghabd";
114 if (c1->type == unused) continue;
115 if (strcmp("X", c1->name)) continue;
117 for(j = 0; j < strlen(order); j++) {
118 sprintf(c1->name, "%s%c", c->name, order[j]);
119 for(c3 = c->part; c3 ; c3 = c3->next)
120 if (c1 != c3 && !strcmp(c3->name, c1->name))
124 strcpy(c1->name, "X");
128 for (c1 = c->part; c1; c1 = c1->next) {
136 Fixup_Extended_Names(struct disk *d, struct chunk *c)
141 for (c1 = c->part; c1; c1 = c1->next) {
142 if (c1->type == unused) continue;
144 c1->name = malloc(12);
145 if(!c1->name) return -1;
146 sprintf(c1->name, "%ss%d", d->chunks->name, j++);
147 if (c1->type == freebsd)
148 if (Fixup_FreeBSD_Names(d, c1) != 0)
155 Fixup_Names(struct disk *d)
157 struct chunk *c1, *c2;
165 for(i=1,c2 = c1->part; c2 ; c2 = c2->next) {
166 c2->flags &= ~CHUNK_BSD_COMPAT;
167 if (c2->type == unused)
169 if (strcmp(c2->name, "X"))
172 c2->oname = malloc(12);
173 if(!c2->oname) return -1;
174 for(j = 1; j <= NDOSPART; j++) {
175 sprintf(c2->oname, "%ss%d", c1->name, j);
176 for(c3 = c1->part; c3; c3 = c3->next)
177 if (c3 != c2 && !strcmp(c3->name, c2->oname))
180 c2->name = c2->oname;
190 c2->name = strdup(c1->name);
193 for(c2 = c1->part; c2; c2 = c2->next) {
194 if (c2->type == freebsd) {
195 c2->flags |= CHUNK_BSD_COMPAT;
199 for(c2 = c1->part; c2; c2 = c2->next) {
200 if (c2->type == freebsd)
201 Fixup_FreeBSD_Names(d, c2);
203 if (c2->type == extended)
204 Fixup_Extended_Names(d, c2);
212 Create_Chunk(struct disk *d, u_long offset, u_long size, chunk_e type, int subtype, u_long flags, const char *sname)
214 Create_Chunk(struct disk *d, u_long offset, u_long size, chunk_e type, int subtype, u_long flags)
220 if(!(flags & CHUNK_FORCE_ALL)) {
222 /* Never use the first cylinder */
224 offset += (d->bios_sect * d->bios_hd);
225 size -= (d->bios_sect * d->bios_hd);
228 /* Never use the first track */
230 offset += d->bios_sect;
231 size -= d->bios_sect;
235 /* Always end on cylinder boundary */
236 l = (offset+size) % (d->bios_sect * d->bios_hd);
241 i = Add_Chunk(d, offset, size, "X", type, subtype, flags, sname);
243 i = Add_Chunk(d, offset, size, "X", type, subtype, flags);
250 Create_Chunk_DWIM(struct disk *d, struct chunk *parent , u_long size, chunk_e type, int subtype, u_long flags)
258 for (c1=parent->part; c1; c1 = c1->next) {
259 if (c1->type != unused) continue;
260 if (c1->size < size) continue;
267 i = Add_Chunk(d, offset, size, "X", type, subtype, flags, "-");
269 i = Add_Chunk(d, offset, size, "X", type, subtype, flags);
274 for (c1=parent->part; c1; c1 = c1->next)
275 if (c1->offset == offset)
277 /* barfout(1, "Serious internal trouble"); */
282 MakeDev(struct chunk *c1, const char *path)
285 u_long cmaj, min, unit, part, slice;
286 char buf[BUFSIZ], buf2[BUFSIZ];
295 msgDebug("MakeDev: Called with %s on path %s\n", p, path);
298 if (statfs(path, &fs) != 0) {
300 warn("statfs(%s) failed\n", path);
304 if (strcmp(fs.f_fstypename, "devfs") == 0) {
306 msgDebug("MakeDev: No need to mknod(2) with DEVFS.\n");
310 if (!strncmp(p, "ad", 2))
313 else if (!strncmp(p, "wd", 2))
316 else if (!strncmp(p, "wfd", 3))
318 else if (!strncmp(p, "afd", 3))
320 else if (!strncmp(p, "fla", 3))
322 else if (!strncmp(p, "idad", 4))
324 else if (!strncmp(p, "mlxd", 4))
326 else if (!strncmp(p, "amrd", 4))
328 else if (!strncmp(p, "twed", 4))
330 else if (!strncmp(p, "aacd", 4))
332 else if (!strncmp(p, "ar", 2)) /* ATA RAID */
334 else if (!strncmp(p, "da", 2)) /* CAM support */
337 msgDebug("MakeDev: Unknown major/minor for devtype %s\n", p);
341 msgDebug("MakeDev: Invalid disk unit passed: %s\n", p);
351 else if (isdigit(*p)) {
358 msgDebug("MakeDev: `%s' is not a valid slice delimiter\n", p);
363 msgDebug("MakeDev: `%s' is an invalid slice number\n", p);
379 if(c1->type == freebsd)
380 sprintf(buf2, "%sc", c1->name);
383 if (*p < 'a' || *p > 'h') {
384 msgDebug("MakeDev: `%s' is not a valid partition name.\n", p);
390 msgDebug("MakeDev: Unit %lu, Slice %lu, Part %lu\n", unit, slice, part);
395 if ((pwd = getpwnam("root")) == NULL) {
397 msgDebug("MakeDev: Unable to lookup user \"root\", using 0.\n");
402 if ((grp = getgrnam("operator")) == NULL) {
404 msgDebug("MakeDev: Unable to lookup group \"operator\", using 5.\n");
409 min = unit * 8 + 65536 * slice + part;
410 sprintf(buf, "%s/r%s", path, c1->name);
412 if (mknod(buf, S_IFCHR|0640, makedev(cmaj,min)) == -1) {
413 msgDebug("mknod of %s returned failure status!\n", buf);
416 if (chown(buf, owner, group) == -1) {
417 msgDebug("chown of %s returned failure status!\n", buf);
421 sprintf(buf, "%s/r%s", path, buf2);
423 if (mknod(buf, S_IFCHR|0640, makedev(cmaj,min)) == -1) {
424 msgDebug("mknod of %s returned failure status!\n", buf);
427 if (chown(buf, owner, group) == -1) {
428 msgDebug("chown of %s returned failure status!\n", buf);
432 sprintf(buf, "%s/%s", path, c1->name);
434 if (mknod(buf, S_IFCHR|0640, makedev(cmaj,min)) == -1) {
435 msgDebug("mknod of %s returned failure status!\n", buf);
438 if (chown(buf, owner, group) == -1) {
439 msgDebug("chown of %s returned failure status!\n", buf);
446 MakeDevChunk(struct chunk *c1, const char *path)
450 i = MakeDev(c1, path);
452 MakeDevChunk(c1->next, path);
454 MakeDevChunk(c1->part, path);
459 MakeDevDisk(struct disk *d, const char *path)
461 return MakeDevChunk(d->chunks, path);