rules.c revision 8233
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.4 1995/04/30 06:09:27 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);
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));
73}
74
75/*
76 *  Rule#0:
77 *	Chunks of type 'whole' can have max NDOSPART children.
78 */
79void
80Rule_000(struct disk *d, struct chunk *c, char *msg)
81{
82	int i;
83	struct chunk *c1;
84
85	if (c->type != whole)
86		return;
87	for (i=0, c1=c->part; c1; c1=c1->next) {
88		if (c1->type != reserved)
89			continue;
90		if (c1->type != reserved)
91			continue;
92		i++;
93	}
94	if (i <= NDOSPART)
95		return;
96	sprintf(msg+strlen(msg),
97		"%d is too many children of the 'whole' chunk.  Max is %d\n",
98		i, NDOSPART);
99}
100
101/*
102 * Rule#1:
103 *	All children of 'whole' must be track-aligned.
104 *	Exception: the end can be unaligned if it matches the end of 'whole'
105 */
106void
107Rule_001(struct disk *d, struct chunk *c, char *msg)
108{
109	int i;
110	struct chunk *c1;
111
112	if (c->type != whole)
113		return;
114	for (i=0, c1=c->part; c1; c1=c1->next) {
115		if (c1->type == reserved)
116			continue;
117		if (c1->type == unused)
118			continue;
119		if (!Track_Aligned(d,c1->offset))
120			sprintf(msg+strlen(msg),
121		    "chunk '%s' [%ld..%ld] does not start on a track boundary\n",
122				c1->name,c1->offset,c1->end);
123		if (c->end != c1->end && !Cyl_Aligned(d,c1->end+1))
124			sprintf(msg+strlen(msg),
125		    "chunk '%s' [%ld..%ld] does not end on a cylinder boundary\n",
126				c1->name,c1->offset,c1->end);
127	}
128}
129
130/*
131 * Rule#2:
132 *	Max one 'fat' as child of 'whole'
133 */
134void
135Rule_002(struct disk *d, struct chunk *c, char *msg)
136{
137	int i;
138	struct chunk *c1;
139
140	if (c->type != whole)
141		return;
142	for (i=0, c1=c->part; c1; c1=c1->next) {
143		if (c1->type != fat)
144			continue;
145		i++;
146	}
147	if (i > 1) {
148		sprintf(msg+strlen(msg),
149		    "Max one 'fat' allowed as child of 'whole'\n");
150	}
151}
152
153/*
154 * Rule#3:
155 *	Max one extended as child of 'whole'
156 */
157void
158Rule_003(struct disk *d, struct chunk *c, char *msg)
159{
160	int i;
161	struct chunk *c1;
162
163	if (c->type != whole)
164		return;
165	for (i=0, c1=c->part; c1; c1=c1->next) {
166		if (c1->type != extended)
167			continue;
168		i++;
169	}
170	if (i > 1) {
171		sprintf(msg+strlen(msg),
172		    "Max one 'extended' allowed as child of 'whole'\n");
173	}
174}
175
176/*
177 * Rule#4:
178 *	Max seven 'part' as children of 'freebsd'
179 */
180void
181Rule_004(struct disk *d, struct chunk *c, char *msg)
182{
183	int i=0,j=0,k=0;
184	struct chunk *c1;
185
186	if (c->type != freebsd)
187		return;
188	for (c1=c->part; c1; c1=c1->next) {
189		if (c1->type != part)
190			continue;
191		if (c1->subtype == FS_SWAP)
192			j++;
193		if (c1->flags & CHUNK_IS_ROOT)
194			k++;
195		i++;
196	}
197	if (i > 7) {
198		sprintf(msg+strlen(msg),
199		    "Max seven 'part' per 'freebsd' chunk\n");
200	}
201	if (j > 1) {
202		sprintf(msg+strlen(msg),
203		    "Max one subtype=FS_SWAP child per 'freebsd' chunk\n");
204	}
205	if (k > 1) {
206		sprintf(msg+strlen(msg),
207		    "Max one CHUNK_IS_ROOT child per 'freebsd' chunk\n");
208	}
209}
210
211void
212Check_Chunk(struct disk *d, struct chunk *c, char *msg)
213{
214	Rule_000(d,c,msg);
215	Rule_001(d,c,msg);
216	Rule_002(d,c,msg);
217	Rule_003(d,c,msg);
218	Rule_004(d,c,msg);
219	if (c->part)
220		Check_Chunk(d,c->part,msg);
221	if (c->next)
222		Check_Chunk(d,c->next,msg);
223	return;
224}
225
226char *
227CheckRules(struct disk *d)
228{
229	char msg[BUFSIZ];
230
231	*msg = '\0';
232	Check_Chunk(d,d->chunks,msg);
233	if (*msg)
234		return strdup(msg);
235	return 0;
236}
237