rules.c revision 8290
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 * $Id: rules.c,v 1.6 1995/05/04 07:00:56 phk Exp $
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <unistd.h>
16#include <string.h>
17#include <sys/types.h>
18#include <sys/diskslice.h>
19#include <sys/disklabel.h>
20#include <err.h>
21#include "libdisk.h"
22
23int
24Track_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
33u_long
34Prev_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
41u_long
42Next_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
49int
50Cyl_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
59u_long
60Prev_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
67u_long
68Next_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 */
80void
81Rule_000(struct disk *d, struct chunk *c, char *msg)
82{
83	int i=0,j=0;
84	struct chunk *c1;
85
86	if (c->type != whole)
87		return;
88	for (c1=c->part; c1; c1=c1->next) {
89		if (c1->type != unused) continue;
90		if (c1->type != reserved) continue;
91		if (c1->flags & CHUNK_ACTIVE)
92			j++;
93		i++;
94	}
95	if (i > NDOSPART)
96		sprintf(msg+strlen(msg),
97	"%d is too many children of the 'whole' chunk.  Max is %d\n",
98			i, NDOSPART);
99	if (j > 1)
100		sprintf(msg+strlen(msg),
101	"Too many active children of 'whole'");
102}
103
104/*
105 * Rule#1:
106 *	All children of 'whole' and 'extended'  must be track-aligned.
107 *	Exception: the end can be unaligned if it matches the end of 'whole'
108 */
109void
110Rule_001(struct disk *d, struct chunk *c, char *msg)
111{
112	int i;
113	struct chunk *c1;
114
115	if (c->type != whole && c->type != extended)
116		return;
117	for (i=0, c1=c->part; c1; c1=c1->next) {
118		if (c1->type == reserved)
119			continue;
120		if (c1->type == unused)
121			continue;
122		c1->flags |= CHUNK_ALIGN;
123		if (!Track_Aligned(d,c1->offset))
124			sprintf(msg+strlen(msg),
125		    "chunk '%s' [%ld..%ld] does not start on a track boundary\n",
126				c1->name,c1->offset,c1->end);
127		if ((c->type == whole || c->end == c1->end)
128		    || Cyl_Aligned(d,c1->end+1))
129			;
130		else
131			sprintf(msg+strlen(msg),
132		    "chunk '%s' [%ld..%ld] does not end on a cylinder boundary\n",
133				c1->name,c1->offset,c1->end);
134	}
135}
136
137/*
138 * Rule#2:
139 *	Max one 'fat' as child of 'whole'
140 */
141void
142Rule_002(struct disk *d, struct chunk *c, char *msg)
143{
144	int i;
145	struct chunk *c1;
146
147	if (c->type != whole)
148		return;
149	for (i=0, c1=c->part; c1; c1=c1->next) {
150		if (c1->type != fat)
151			continue;
152		i++;
153	}
154	if (i > 1) {
155		sprintf(msg+strlen(msg),
156		    "Max one 'fat' allowed as child of 'whole'\n");
157	}
158}
159
160/*
161 * Rule#3:
162 *	Max one extended as child of 'whole'
163 */
164void
165Rule_003(struct disk *d, struct chunk *c, char *msg)
166{
167	int i;
168	struct chunk *c1;
169
170	if (c->type != whole)
171		return;
172	for (i=0, c1=c->part; c1; c1=c1->next) {
173		if (c1->type != extended)
174			continue;
175		i++;
176	}
177	if (i > 1) {
178		sprintf(msg+strlen(msg),
179		    "Max one 'extended' allowed as child of 'whole'\n");
180	}
181}
182
183/*
184 * Rule#4:
185 *	Max seven 'part' as children of 'freebsd'
186 *	Max one FS_SWAP child per 'freebsd'
187 *	Max one CHUNK_IS_ROOT child per 'freebsd'
188 */
189void
190Rule_004(struct disk *d, struct chunk *c, char *msg)
191{
192	int i=0,j=0,k=0;
193	struct chunk *c1;
194
195	if (c->type != freebsd)
196		return;
197	for (c1=c->part; c1; c1=c1->next) {
198		if (c1->type != part)
199			continue;
200		if (c1->subtype == FS_SWAP)
201			j++;
202		if (c1->flags & CHUNK_IS_ROOT)
203			k++;
204		i++;
205	}
206	if (i > 7) {
207		sprintf(msg+strlen(msg),
208		    "Max seven 'part' per 'freebsd' chunk\n");
209	}
210	if (j > 1) {
211		sprintf(msg+strlen(msg),
212		    "Max one subtype=FS_SWAP child per 'freebsd' chunk\n");
213	}
214	if (k > 1) {
215		sprintf(msg+strlen(msg),
216		    "Max one CHUNK_IS_ROOT child per 'freebsd' chunk\n");
217	}
218}
219
220void
221Check_Chunk(struct disk *d, struct chunk *c, char *msg)
222{
223	Rule_000(d,c,msg);
224	Rule_001(d,c,msg);
225	Rule_002(d,c,msg);
226	Rule_003(d,c,msg);
227	Rule_004(d,c,msg);
228	if (c->part)
229		Check_Chunk(d,c->part,msg);
230	if (c->next)
231		Check_Chunk(d,c->next,msg);
232
233	if (c->end >= 1024*d->bios_hd*d->bios_sect)
234		c->flags |= CHUNK_PAST_1024;
235	else
236		c->flags &= ~CHUNK_PAST_1024;
237}
238
239char *
240CheckRules(struct disk *d)
241{
242	char msg[BUFSIZ];
243
244	*msg = '\0';
245	Check_Chunk(d,d->chunks,msg);
246	if (*msg)
247		return strdup(msg);
248	return 0;
249}
250