Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / lib / libdisk / rules.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/rules.c,v 1.16.2.4 2001/05/13 20:16:32 jkh Exp $
10  * $DragonFly: src/lib/libdisk/Attic/rules.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 <sys/types.h>
19 #include <sys/diskslice.h>
20 #include <sys/disklabel.h>
21 #include "libdisk.h"
22
23 int
24 Track_Aligned(struct disk *d, u_long offset)
25 {
26         if (!d->bios_sect)
27                 return 1;
28         if (offset % d->bios_sect)
29                 return 0;
30         return 1;
31 }
32
33 u_long
34 Prev_Track_Aligned(struct disk *d, u_long offset)
35 {
36         if (!d->bios_sect)
37                 return offset;
38         return (offset / d->bios_sect) * d->bios_sect;
39 }
40
41 u_long
42 Next_Track_Aligned(struct disk *d, u_long offset)
43 {
44         if (!d->bios_sect)
45                 return offset;
46         return Prev_Track_Aligned(d, offset + d->bios_sect-1);
47 }
48
49 int
50 Cyl_Aligned(struct disk *d, u_long offset)
51 {
52         if (!d->bios_sect || !d->bios_hd)
53                 return 1;
54         if (offset % (d->bios_sect * d->bios_hd))
55                 return 0;
56         return 1;
57 }
58
59 u_long
60 Prev_Cyl_Aligned(struct disk *d, u_long offset)
61 {
62         if (!d->bios_sect || !d->bios_hd)
63                 return offset;
64         return (offset / (d->bios_sect*d->bios_hd)) * d->bios_sect * d->bios_hd;
65 }
66
67 u_long
68 Next_Cyl_Aligned(struct disk *d, u_long offset)
69 {
70         if (!d->bios_sect || !d->bios_hd)
71                 return offset;
72         return Prev_Cyl_Aligned(d,offset + (d->bios_sect * d->bios_hd)-1);
73 }
74
75 /*
76  *  Rule#0:
77  *      Chunks of type 'whole' can have max NDOSPART children.
78  *      Only one of them can have the "active" flag
79  */
80 void
81 Rule_000(struct disk *d, struct chunk *c, char *msg)
82 {
83 #ifdef PC98
84         int i=0;
85 #else
86         int i=0,j=0;
87 #endif
88         struct chunk *c1;
89
90         if (c->type != whole)
91                 return;
92         for (c1 = c->part; c1; c1 = c1->next) {
93                 if (c1->type != unused) continue;
94 #ifndef PC98
95                 if (c1->flags & CHUNK_ACTIVE)
96                         j++;
97 #endif
98                 i++;
99         }
100         if (i > NDOSPART)
101                 sprintf(msg + strlen(msg),
102         "%d is too many children of the 'whole' chunk.  Max is %d\n",
103                         i, NDOSPART);
104 #ifndef PC98
105         if (j > 1)
106                 sprintf(msg + strlen(msg),
107         "Too many active children of 'whole'");
108 #endif
109 }
110
111 /*
112  * Rule#1:
113  *      All children of 'whole' and 'extended'  must be track-aligned.
114  *      Exception: the end can be unaligned if it matches the end of 'whole'
115  */
116 void
117 Rule_001(struct disk *d, struct chunk *c, char *msg)
118 {
119         int i;
120         struct chunk *c1;
121
122         if (c->type != whole && c->type != extended)
123                 return;
124         for (i = 0, c1 = c->part; c1; c1 = c1->next) {
125                 if (c1->type == unused) continue;
126                 c1->flags |= CHUNK_ALIGN;
127 #ifdef PC98
128                 if (!Cyl_Aligned(d, c1->offset))
129 #else
130                 if (!Track_Aligned(d, c1->offset))
131 #endif
132                         sprintf(msg + strlen(msg),
133 #ifdef PC98
134                     "chunk '%s' [%ld..%ld] does not start on a cylinder boundary\n",
135 #else
136                     "chunk '%s' [%ld..%ld] does not start on a track boundary\n",
137 #endif
138                                 c1->name, c1->offset, c1->end);
139                 if ((c->type == whole || c->end == c1->end)
140                     || Cyl_Aligned(d, c1->end + 1))
141                         ;
142                 else
143                         sprintf(msg + strlen(msg),
144                     "chunk '%s' [%ld..%ld] does not end on a cylinder boundary\n",
145                                 c1->name, c1->offset, c1->end);
146         }
147 }
148
149 /*
150  * Rule#2:
151  *      Max one 'fat' as child of 'whole'
152  */
153 void
154 Rule_002(struct disk *d, struct chunk *c, char *msg)
155 {
156 #ifndef PC98
157         int i;
158         struct chunk *c1;
159
160         if (c->type != whole)
161                 return;
162         for (i = 0, c1 = c->part; c1; c1 = c1->next) {
163                 if (c1->type != fat)
164                         continue;
165                 i++;
166         }
167         if (i > 1) {
168                 sprintf(msg + strlen(msg),
169                     "Max one 'fat' allowed as child of 'whole'\n");
170         }
171 #endif
172 }
173
174 /*
175  * Rule#3:
176  *      Max one extended as child of 'whole'
177  */
178 void
179 Rule_003(struct disk *d, struct chunk *c, char *msg)
180 {
181 #ifndef PC98
182         int i;
183         struct chunk *c1;
184
185         if (c->type != whole)
186                 return;
187         for (i = 0, c1 = c->part; c1; c1 = c1->next) {
188                 if (c1->type != extended)
189                         continue;
190                 i++;
191         }
192         if (i > 1) {
193                 sprintf(msg + strlen(msg),
194                     "Max one 'extended' allowed as child of 'whole'\n");
195         }
196 #endif
197 }
198
199 /*
200  * Rule#4:
201  *      Max seven 'part' as children of 'freebsd'
202  *      Max one CHUNK_IS_ROOT child per 'freebsd'
203  */
204 void
205 Rule_004(struct disk *d, struct chunk *c, char *msg)
206 {
207         int i=0,k=0;
208         struct chunk *c1;
209
210         if (c->type != freebsd)
211                 return;
212
213         for (c1 = c->part; c1; c1 = c1->next) {
214                 if (c1->type != part)
215                         continue;
216                 if (c1->flags & CHUNK_IS_ROOT)
217                         k++;
218                 i++;
219         }
220         if (i > 7) {
221                 sprintf(msg + strlen(msg),
222                     "Max seven partitions per freebsd slice\n");
223         }
224         if (k > 1) {
225                 sprintf(msg + strlen(msg),
226                     "Max one root partition child per freebsd slice\n");
227         }
228 }
229
230 void
231 Check_Chunk(struct disk *d, struct chunk *c, char *msg)
232 {
233         Rule_000(d, c, msg);
234         Rule_001(d, c, msg);
235         Rule_002(d, c, msg);
236         Rule_003(d, c, msg);
237         Rule_004(d, c, msg);
238         if (c->part)
239                 Check_Chunk(d, c->part, msg);
240         if (c->next)
241                 Check_Chunk(d, c->next, msg);
242 }
243
244 char *
245 CheckRules(struct disk *d)
246 {
247         char msg[BUFSIZ];
248
249         *msg = '\0';
250         Check_Chunk(d, d->chunks, msg);
251         if (*msg)
252                 return strdup(msg);
253         return 0;
254 }
255
256 char *
257 ChunkCanBeRoot(struct chunk *c)
258 {
259         struct chunk *c1;
260         struct disk *d = c->disk;
261         char msg[BUFSIZ];
262
263         *msg = '\0';
264         for (c1 = d->chunks->part; ; ) {
265                 for (; c1; c1 = c1->next)
266                         if (c1->offset <= c->offset && c1->end >= c->end)
267                                 break;
268                 if (!c1) {
269                         strcat(msg,
270 "Internal trouble, cannot find this chunk in the chunk-tree\n");
271                         return strdup(msg);
272                 }
273                 if (c1->type == freebsd)
274                         break;
275                 c1 = c1->part;
276         }
277
278 #ifndef PC98
279         if (c1->type != freebsd) {
280                 strcat(msg,
281 "The root partition must be in a FreeBSD slice, otherwise\n");
282                 strcat(msg,
283 "the kernel cannot be booted from it\n");
284                 return strdup(msg);
285         }
286 #endif
287
288         return NULL;
289 }