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