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>
23 #include <sys/mount.h>
25 #include <sys/sysctl.h>
31 static void msgDebug(char *, ...) __printflike(1, 2);
33 /* Clone these two from sysinstall because we need our own copies
34 * due to link order problems with `crunch'. Feh!
39 static int debug = 0; /* Allow debugger to tweak it */
44 /* Write something to the debugging port */
46 msgDebug(char *fmt, ...)
50 static int DebugFD = -1;
53 DebugFD = open(_PATH_DEV"ttyv1", O_RDWR);
54 dbg = (char *)alloca(FILENAME_MAX);
55 strcpy(dbg, "DEBUG: ");
57 vsnprintf((char *)(dbg + strlen(dbg)), FILENAME_MAX, fmt, args);
59 write(DebugFD, dbg, strlen(dbg));
63 Fixup_FreeBSD_Names(struct disk *d, struct chunk *c)
65 struct chunk *c1, *c3;
68 if (!strcmp(c->name, "X")) return 0;
70 /* reset all names to "X" */
71 for (c1 = c->part; c1; c1 = c1->next) {
73 c1->name = malloc(12);
74 if(!c1->name) return -1;
78 /* Allocate the first swap-partition we find */
79 for (c1 = c->part; c1; c1 = c1->next) {
80 if (c1->type == unused) continue;
81 if (c1->subtype != FS_SWAP) continue;
82 sprintf(c1->name, "%s%c", c->name, SWAP_PART + 'a');
86 /* Allocate the first root-partition we find */
87 for (c1 = c->part; c1; c1 = c1->next) {
88 if (c1->type == unused) continue;
89 if (!(c1->flags & CHUNK_IS_ROOT)) continue;
90 sprintf(c1->name, "%s%c", c->name, 0 + 'a');
94 /* Try to give them the same as they had before */
95 for (c1 = c->part; c1; c1 = c1->next) {
96 if (strcmp(c1->name, "X")) continue;
97 for(c3 = c->part; c3 ; c3 = c3->next)
98 if (c1 != c3 && !strcmp(c3->name, c1->oname)) {
101 strcpy(c1->name, c1->oname);
106 /* Allocate the rest sequentially */
107 for (c1 = c->part; c1; c1 = c1->next) {
108 const char order[] = "efghabd";
109 if (c1->type == unused) continue;
110 if (strcmp("X", c1->name)) continue;
112 for(j = 0; j < strlen(order); j++) {
113 sprintf(c1->name, "%s%c", c->name, order[j]);
114 for(c3 = c->part; c3 ; c3 = c3->next)
115 if (c1 != c3 && !strcmp(c3->name, c1->name))
119 strcpy(c1->name, "X");
123 for (c1 = c->part; c1; c1 = c1->next) {
131 Fixup_Extended_Names(struct disk *d, struct chunk *c)
136 for (c1 = c->part; c1; c1 = c1->next) {
137 if (c1->type == unused) continue;
139 c1->name = malloc(12);
140 if(!c1->name) return -1;
141 sprintf(c1->name, "%ss%d", d->chunks->name, j++);
142 if (c1->type == freebsd)
143 if (Fixup_FreeBSD_Names(d, c1) != 0)
150 Fixup_Names(struct disk *d)
152 struct chunk *c1, *c2;
160 for(i=1,c2 = c1->part; c2 ; c2 = c2->next) {
161 c2->flags &= ~CHUNK_BSD_COMPAT;
162 if (c2->type == unused)
164 if (strcmp(c2->name, "X"))
167 c2->oname = malloc(12);
168 if(!c2->oname) return -1;
169 for(j = 1; j <= NDOSPART; j++) {
170 sprintf(c2->oname, "%ss%d", c1->name, j);
171 for(c3 = c1->part; c3; c3 = c3->next)
172 if (c3 != c2 && !strcmp(c3->name, c2->oname))
175 c2->name = c2->oname;
185 c2->name = strdup(c1->name);
188 for(c2 = c1->part; c2; c2 = c2->next) {
189 if (c2->type == freebsd) {
190 c2->flags |= CHUNK_BSD_COMPAT;
194 for(c2 = c1->part; c2; c2 = c2->next) {
195 if (c2->type == freebsd)
196 Fixup_FreeBSD_Names(d, c2);
198 if (c2->type == extended)
199 Fixup_Extended_Names(d, c2);
207 Create_Chunk(struct disk *d, u_long offset, u_long size, chunk_e type, int subtype, u_long flags, const char *sname)
209 Create_Chunk(struct disk *d, u_long offset, u_long size, chunk_e type, int subtype, u_long flags)
215 if(!(flags & CHUNK_FORCE_ALL))
218 /* Never use the first cylinder */
220 offset += (d->bios_sect * d->bios_hd);
221 size -= (d->bios_sect * d->bios_hd);
224 /* Never use the first track */
226 offset += d->bios_sect;
227 size -= d->bios_sect;
231 /* Always end on cylinder boundary */
232 l = (offset+size) % (d->bios_sect * d->bios_hd);
237 i = Add_Chunk(d, offset, size, "X", type, subtype, flags, sname);
239 i = Add_Chunk(d, offset, size, "X", type, subtype, flags);
246 Create_Chunk_DWIM(struct disk *d, struct chunk *parent , u_long size, chunk_e type, int subtype, u_long flags)
254 for (c1=parent->part; c1; c1 = c1->next) {
255 if (c1->type != unused) continue;
256 if (c1->size < size) continue;
263 i = Add_Chunk(d, offset, size, "X", type, subtype, flags, "-");
265 i = Add_Chunk(d, offset, size, "X", type, subtype, flags);
270 for (c1=parent->part; c1; c1 = c1->next)
271 if (c1->offset == offset)
273 /* barfout(1, "Serious internal trouble"); */
278 MakeDev(struct chunk *c1, const char *path)
281 u_long cmaj, min, unit, part, slice;
282 char buf[BUFSIZ], buf2[BUFSIZ];
291 msgDebug("MakeDev: Called with %s on path %s\n", p, path);
294 if (statfs(path, &fs) != 0) {
296 warn("statfs(%s) failed\n", path);
300 if (strcmp(fs.f_fstypename, "devfs") == 0) {
302 msgDebug("MakeDev: No need to mknod(2) with DEVFS.\n");
306 if (!strncmp(p, "ad", 2))
309 else if (!strncmp(p, "wd", 2))
312 else if (!strncmp(p, "wfd", 3))
314 else if (!strncmp(p, "afd", 3))
316 else if (!strncmp(p, "fla", 3))
318 else if (!strncmp(p, "idad", 4))
320 else if (!strncmp(p, "mlxd", 4))
322 else if (!strncmp(p, "amrd", 4))
324 else if (!strncmp(p, "twed", 4))
326 else if (!strncmp(p, "aacd", 4))
328 else if (!strncmp(p, "ar", 2)) /* ATA RAID */
330 else if (!strncmp(p, "da", 2)) /* CAM support */
333 msgDebug("MakeDev: Unknown major/minor for devtype %s\n", p);
337 msgDebug("MakeDev: Invalid disk unit passed: %s\n", p);
347 else if (isdigit(*p)) {
354 msgDebug("MakeDev: `%s' is not a valid slice delimiter\n", p);
359 msgDebug("MakeDev: `%s' is an invalid slice number\n", p);
375 if(c1->type == freebsd)
376 sprintf(buf2, "%sc", c1->name);
379 if (*p < 'a' || *p > 'h') {
380 msgDebug("MakeDev: `%s' is not a valid partition name.\n", p);
386 msgDebug("MakeDev: Unit %lu, Slice %lu, Part %lu\n", unit, slice, part);
391 if ((pwd = getpwnam("root")) == NULL) {
393 msgDebug("MakeDev: Unable to lookup user \"root\", using 0.\n");
398 if ((grp = getgrnam("operator")) == NULL) {
400 msgDebug("MakeDev: Unable to lookup group \"operator\", using 5.\n");
405 min = unit * 8 + 65536 * slice + part;
406 sprintf(buf, "%s/r%s", path, c1->name);
408 if (mknod(buf, S_IFCHR|0640, makedev(cmaj,min)) == -1) {
409 msgDebug("mknod of %s returned failure status!\n", buf);
412 if (chown(buf, owner, group) == -1) {
413 msgDebug("chown of %s returned failure status!\n", buf);
417 sprintf(buf, "%s/r%s", path, buf2);
419 if (mknod(buf, S_IFCHR|0640, makedev(cmaj,min)) == -1) {
420 msgDebug("mknod of %s returned failure status!\n", buf);
423 if (chown(buf, owner, group) == -1) {
424 msgDebug("chown of %s returned failure status!\n", buf);
428 sprintf(buf, "%s/%s", path, c1->name);
430 if (mknod(buf, S_IFCHR|0640, makedev(cmaj,min)) == -1) {
431 msgDebug("mknod of %s returned failure status!\n", buf);
434 if (chown(buf, owner, group) == -1) {
435 msgDebug("chown of %s returned failure status!\n", buf);
442 MakeDevChunk(struct chunk *c1, const char *path)
446 i = MakeDev(c1, path);
448 MakeDevChunk(c1->next, path);
450 MakeDevChunk(c1->part, path);
455 MakeDevDisk(struct disk *d, const char *path)
457 return MakeDevChunk(d->chunks, path);