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