Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / lib / libdisk / create_chunk.c
1 /*
2  * ----------------------------------------------------------------------------
3  * "THE BEER-WARE LICENSE" (Revision 42):
4  * <phk@login.dknet.dk> 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  * ----------------------------------------------------------------------------
8  *
9  * $FreeBSD: src/lib/libdisk/create_chunk.c,v 1.46.2.8 2001/05/13 21:01:37 jkh Exp $
10  * $DragonFly: src/lib/libdisk/Attic/create_chunk.c,v 1.2 2003/06/17 04:26:49 dillon Exp $
11  *
12  */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include <fcntl.h>
20 #include <stdarg.h>
21 #include <sys/types.h>
22 #include <sys/disklabel.h>
23 #include <sys/diskslice.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <grp.h>
27 #include <paths.h>
28 #include <pwd.h>
29 #include "libdisk.h"
30
31 /* Clone these two from sysinstall because we need our own copies
32  * due to link order problems with `crunch'.  Feh!
33  */
34 static int
35 isDebug()
36 {
37     static int debug = 0;       /* Allow debugger to tweak it */
38
39     return debug;
40 }
41
42 /* Write something to the debugging port */
43 static void
44 msgDebug(char *fmt, ...)
45 {
46     va_list args;
47     char *dbg;
48     static int DebugFD = -1;
49
50     if (DebugFD == -1)
51         DebugFD = open(_PATH_DEV"ttyv1", O_RDWR);
52     dbg = (char *)alloca(FILENAME_MAX);
53     strcpy(dbg, "DEBUG: ");
54     va_start(args, fmt);
55     vsnprintf((char *)(dbg + strlen(dbg)), FILENAME_MAX, fmt, args);
56     va_end(args);
57     write(DebugFD, dbg, strlen(dbg));
58 }
59
60 int
61 Fixup_FreeBSD_Names(struct disk *d, struct chunk *c)
62 {
63     struct chunk *c1, *c3;
64     int j;
65     
66     if (!strcmp(c->name, "X")) return 0;
67     
68     /* reset all names to "X" */
69     for (c1 = c->part; c1; c1 = c1->next) {
70         c1->oname = c1->name;
71         c1->name = malloc(12);
72         if(!c1->name) return -1;
73         strcpy(c1->name,"X");
74     }
75     
76     /* Allocate the first swap-partition we find */
77     for (c1 = c->part; c1; c1 = c1->next) {
78         if (c1->type == unused) continue;
79         if (c1->subtype != FS_SWAP) continue;
80         sprintf(c1->name, "%s%c", c->name, SWAP_PART + 'a');
81         break;
82     }
83     
84     /* Allocate the first root-partition we find */
85     for (c1 = c->part; c1; c1 = c1->next) {
86         if (c1->type == unused) continue;
87         if (!(c1->flags & CHUNK_IS_ROOT)) continue;
88         sprintf(c1->name, "%s%c", c->name, 0 + 'a');
89         break;
90     }
91     
92     /* Try to give them the same as they had before */
93     for (c1 = c->part; c1; c1 = c1->next) {
94         if (strcmp(c1->name, "X")) continue;
95         for(c3 = c->part; c3 ; c3 = c3->next)
96             if (c1 != c3 && !strcmp(c3->name, c1->oname)) {
97                 goto newname;
98             }
99         strcpy(c1->name, c1->oname);
100     newname: ;
101     }
102     
103     
104     /* Allocate the rest sequentially */
105     for (c1 = c->part; c1; c1 = c1->next) {
106         const char order[] = "efghabd";
107         if (c1->type == unused) continue;
108         if (strcmp("X", c1->name)) continue;
109         
110         for(j = 0; j < strlen(order); j++) {
111             sprintf(c1->name, "%s%c", c->name, order[j]);
112             for(c3 = c->part; c3 ; c3 = c3->next)
113                 if (c1 != c3 && !strcmp(c3->name, c1->name))
114                     goto match;
115             break;
116         match:
117             strcpy(c1->name, "X");
118             continue;
119         }
120     }
121     for (c1 = c->part; c1; c1 = c1->next) {
122         free(c1->oname);
123         c1->oname = 0;
124     }
125     return 0;
126 }
127
128 int
129 Fixup_Extended_Names(struct disk *d, struct chunk *c)
130 {
131     struct chunk *c1;
132     int j=5;
133     
134     for (c1 = c->part; c1; c1 = c1->next) {
135         if (c1->type == unused) continue;
136         free(c1->name);
137         c1->name = malloc(12);
138         if(!c1->name) return -1;
139         sprintf(c1->name, "%ss%d", d->chunks->name, j++);
140         if (c1->type == freebsd)
141             if (Fixup_FreeBSD_Names(d, c1) != 0)
142                 return -1;
143     }
144     return 0;
145 }
146
147 int
148 Fixup_Names(struct disk *d)
149 {
150     struct chunk *c1, *c2;
151     int i;
152 #ifdef __i386__
153     struct chunk *c3;
154     int j;
155 #endif
156     
157     c1 = d->chunks;
158     for(i=1,c2 = c1->part; c2 ; c2 = c2->next) {
159         c2->flags &= ~CHUNK_BSD_COMPAT;
160         if (c2->type == unused)
161             continue;
162         if (strcmp(c2->name, "X"))
163             continue;
164 #ifdef __i386__
165         c2->oname = malloc(12);
166         if(!c2->oname) return -1;
167         for(j = 1; j <= NDOSPART; j++) {
168             sprintf(c2->oname, "%ss%d", c1->name, j);
169             for(c3 = c1->part; c3; c3 = c3->next)
170                 if (c3 != c2 && !strcmp(c3->name, c2->oname))
171                     goto match;
172             free(c2->name);
173             c2->name = c2->oname;
174             c2->oname = 0;
175             break;
176         match:
177             continue;
178         }
179         if (c2->oname)
180             free(c2->oname);
181 #else
182         free(c2->name);
183         c2->name = strdup(c1->name);
184 #endif /*__i386__*/
185     }
186     for(c2 = c1->part; c2; c2 = c2->next) {
187         if (c2->type == freebsd) {
188             c2->flags |= CHUNK_BSD_COMPAT;
189             break;
190         }
191     }
192     for(c2 = c1->part; c2; c2 = c2->next) {
193         if (c2->type == freebsd)
194             Fixup_FreeBSD_Names(d, c2);
195 #ifndef PC98
196         if (c2->type == extended)
197             Fixup_Extended_Names(d, c2);
198 #endif
199     }
200     return 0;
201 }
202
203 int
204 #ifdef PC98
205 Create_Chunk(struct disk *d, u_long offset, u_long size, chunk_e type, int subtype, u_long flags, const char *sname)
206 #else
207 Create_Chunk(struct disk *d, u_long offset, u_long size, chunk_e type, int subtype, u_long flags)
208 #endif
209 {
210     int i;
211     u_long l;
212     
213     if(!(flags & CHUNK_FORCE_ALL))
214     {
215 #ifdef PC98
216         /* Never use the first cylinder */
217         if (!offset) {
218             offset += (d->bios_sect * d->bios_hd);
219             size -= (d->bios_sect * d->bios_hd);
220         }
221 #else
222         /* Never use the first track */
223         if (!offset) {
224             offset += d->bios_sect;
225             size -= d->bios_sect;
226         }
227 #endif /* PC98 */
228         
229         /* Always end on cylinder boundary */
230         l = (offset+size) % (d->bios_sect * d->bios_hd);
231         size -= l;
232     }
233     
234 #ifdef PC98
235     i = Add_Chunk(d, offset, size, "X", type, subtype, flags, sname);
236 #else
237     i = Add_Chunk(d, offset, size, "X", type, subtype, flags);
238 #endif
239     Fixup_Names(d);
240     return i;
241 }
242
243 struct chunk *
244 Create_Chunk_DWIM(struct disk *d, struct chunk *parent , u_long size, chunk_e type, int subtype, u_long flags)
245 {
246     int i;
247     struct chunk *c1;
248     u_long offset;
249     
250     if (!parent)
251         parent = d->chunks;
252     for (c1=parent->part; c1; c1 = c1->next) {
253         if (c1->type != unused) continue;
254         if (c1->size < size) continue;
255         offset = c1->offset;
256         goto found;
257     }
258     return 0;
259  found:
260 #ifdef PC98
261     i = Add_Chunk(d, offset, size, "X", type, subtype, flags, "-");
262 #else
263     i = Add_Chunk(d, offset, size, "X", type, subtype, flags);
264 #endif
265     if (i)
266         return 0;
267     Fixup_Names(d);
268     for (c1=parent->part; c1; c1 = c1->next)
269         if (c1->offset == offset)
270             return c1;
271     /* barfout(1, "Serious internal trouble"); */
272     return 0;
273 }
274
275 int
276 MakeDev(struct chunk *c1, const char *path)
277 {
278     char *p = c1->name;
279     u_long cmaj, min, unit, part, slice;
280     char buf[BUFSIZ], buf2[BUFSIZ];
281     struct group *grp;
282     struct passwd *pwd;
283     uid_t owner;
284     gid_t group;
285
286     *buf2 = '\0';
287     if (isDebug())
288         msgDebug("MakeDev: Called with %s on path %s\n", p, path);
289     if (!strcmp(p, "X"))
290         return 0;
291
292     if (!strncmp(p, "ad", 2))
293         cmaj = 116, p += 2;
294 #ifdef PC98
295     else if (!strncmp(p, "wd", 2))
296         cmaj = 3, p += 2;
297 #endif
298     else if (!strncmp(p, "wfd", 3))
299         cmaj = 87, p += 3;
300     else if (!strncmp(p, "afd", 3))
301         cmaj = 118, p += 3;
302     else if (!strncmp(p, "fla", 3))
303         cmaj = 102, p += 3;
304     else if (!strncmp(p, "idad", 4))
305         cmaj = 109, p += 4;
306     else if (!strncmp(p, "mlxd", 4))
307         cmaj = 131, p += 4;
308     else if (!strncmp(p, "amrd", 4))
309         cmaj = 133, p += 4;
310     else if (!strncmp(p, "twed", 4))
311         cmaj = 147, p += 4;
312     else if (!strncmp(p, "aacd", 4))
313         cmaj = 151, p += 4;
314     else if (!strncmp(p, "ar", 2))      /* ATA RAID */
315         cmaj = 157, p += 2;
316     else if (!strncmp(p, "da", 2))      /* CAM support */
317         cmaj = 13, p += 2;
318     else {
319         msgDebug("MakeDev: Unknown major/minor for devtype %s\n", p);
320         return 0;
321     }
322     if (!isdigit(*p)) {
323         msgDebug("MakeDev: Invalid disk unit passed: %s\n", p);
324         return 0;
325     }
326     unit = *p - '0';
327     p++;
328     if (!*p) {
329         slice = 1;
330         part = 2;
331         goto done;
332     }
333     else if (isdigit(*p)) {
334         unit *= 10;
335         unit += (*p - '0');
336         p++;
337     }
338 #ifndef __alpha__
339     if (*p != 's') {
340         msgDebug("MakeDev: `%s' is not a valid slice delimiter\n", p);
341         return 0;
342     }
343     p++;
344     if (!isdigit(*p)) {
345         msgDebug("MakeDev: `%s' is an invalid slice number\n", p);
346         return 0;
347     }
348     slice = *p - '0';
349     p++;
350     if (isdigit(*p)) {
351         slice *= 10;
352         slice += (*p - '0');
353         p++;
354     }
355     slice = slice + 1;
356 #else
357     slice = 0;
358 #endif
359     if (!*p) {
360         part = 2;
361         if(c1->type == freebsd)
362             sprintf(buf2, "%sc", c1->name);
363         goto done;
364     }
365     if (*p < 'a' || *p > 'h') {
366         msgDebug("MakeDev: `%s' is not a valid partition name.\n", p);
367         return 0;
368     }
369     part = *p - 'a';
370  done:
371     if (isDebug())
372         msgDebug("MakeDev: Unit %d, Slice %d, Part %d\n", unit, slice, part);
373     if (unit > 32)
374         return 0;
375     if (slice > 32)
376         return 0;
377     if ((pwd = getpwnam("root")) == NULL) {
378         if (isDebug())
379             msgDebug("MakeDev: Unable to lookup user \"root\", using 0.\n");
380         owner = 0;
381     } else {
382         owner = pwd->pw_uid;
383     }
384     if ((grp = getgrnam("operator")) == NULL) {
385         if (isDebug())
386             msgDebug("MakeDev: Unable to lookup group \"operator\", using 5.\n");
387         group = 5;
388     } else {
389         group = grp->gr_gid;
390     }
391     min = unit * 8 + 65536 * slice + part;
392     sprintf(buf, "%s/r%s", path, c1->name);
393     unlink(buf);
394     if (mknod(buf, S_IFCHR|0640, makedev(cmaj,min)) == -1) {
395         msgDebug("mknod of %s returned failure status!\n", buf);
396         return 0;
397     }
398     if (chown(buf, owner, group) == -1) {
399         msgDebug("chown of %s returned failure status!\n", buf);
400         return 0;
401     }
402     if (*buf2) {
403         sprintf(buf, "%s/r%s", path, buf2);
404         unlink(buf);
405         if (mknod(buf, S_IFCHR|0640, makedev(cmaj,min)) == -1) {
406             msgDebug("mknod of %s returned failure status!\n", buf);
407             return 0;
408         }
409         if (chown(buf, owner, group) == -1) {
410             msgDebug("chown of %s returned failure status!\n", buf);
411             return 0;
412         }
413     }
414     sprintf(buf, "%s/%s", path, c1->name);
415     unlink(buf);
416     if (mknod(buf, S_IFCHR|0640, makedev(cmaj,min)) == -1) {
417         msgDebug("mknod of %s returned failure status!\n", buf);
418         return 0;
419     }
420     if (chown(buf, owner, group) == -1) {
421         msgDebug("chown of %s returned failure status!\n", buf);
422         return 0;
423     }
424     return 1;
425 }
426
427 int
428 MakeDevChunk(struct chunk *c1, const char *path)
429 {
430     int i;
431
432     i = MakeDev(c1, path);
433     if (c1->next)
434         MakeDevChunk(c1->next, path);
435     if (c1->part)
436         MakeDevChunk(c1->part, path);
437     return i;
438 }
439
440 int
441 MakeDevDisk(struct disk *d, const char *path)
442 {
443     return MakeDevChunk(d->chunks, path);
444 }