rules.c revision 8881
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.9 1995/05/08 01:34:31 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->flags & CHUNK_ACTIVE) 91 j++; 92 i++; 93 } 94 if (i > NDOSPART) 95 sprintf(msg+strlen(msg), 96 "%d is too many children of the 'whole' chunk. Max is %d\n", 97 i, NDOSPART); 98 if (j > 1) 99 sprintf(msg+strlen(msg), 100 "Too many active children of 'whole'"); 101} 102 103/* 104 * Rule#1: 105 * All children of 'whole' and 'extended' must be track-aligned. 106 * Exception: the end can be unaligned if it matches the end of 'whole' 107 */ 108void 109Rule_001(struct disk *d, struct chunk *c, char *msg) 110{ 111 int i; 112 struct chunk *c1; 113 114 if (c->type != whole && c->type != extended) 115 return; 116 for (i=0, c1=c->part; c1; c1=c1->next) { 117 if (c1->type == unused) continue; 118 c1->flags |= CHUNK_ALIGN; 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->type == whole || c->end == c1->end) 124 || Cyl_Aligned(d,c1->end+1)) 125 ; 126 else 127 sprintf(msg+strlen(msg), 128 "chunk '%s' [%ld..%ld] does not end on a cylinder boundary\n", 129 c1->name,c1->offset,c1->end); 130 } 131} 132 133/* 134 * Rule#2: 135 * Max one 'fat' as child of 'whole' 136 */ 137void 138Rule_002(struct disk *d, struct chunk *c, char *msg) 139{ 140 int i; 141 struct chunk *c1; 142 143 if (c->type != whole) 144 return; 145 for (i=0, c1=c->part; c1; c1=c1->next) { 146 if (c1->type != fat) 147 continue; 148 i++; 149 } 150 if (i > 1) { 151 sprintf(msg+strlen(msg), 152 "Max one 'fat' allowed as child of 'whole'\n"); 153 } 154} 155 156/* 157 * Rule#3: 158 * Max one extended as child of 'whole' 159 */ 160void 161Rule_003(struct disk *d, struct chunk *c, char *msg) 162{ 163 int i; 164 struct chunk *c1; 165 166 if (c->type != whole) 167 return; 168 for (i=0, c1=c->part; c1; c1=c1->next) { 169 if (c1->type != extended) 170 continue; 171 i++; 172 } 173 if (i > 1) { 174 sprintf(msg+strlen(msg), 175 "Max one 'extended' allowed as child of 'whole'\n"); 176 } 177} 178 179/* 180 * Rule#4: 181 * Max seven 'part' as children of 'freebsd' 182 * Max one FS_SWAP child per 'freebsd' 183 * Max one CHUNK_IS_ROOT child per 'freebsd' 184 */ 185void 186Rule_004(struct disk *d, struct chunk *c, char *msg) 187{ 188 int i=0,j=0,k=0; 189 struct chunk *c1; 190 191 if (c->type != freebsd) 192 return; 193 for (c1=c->part; c1; c1=c1->next) { 194 if (c1->type != part) 195 continue; 196 if (c1->subtype == FS_SWAP) 197 j++; 198 if (c1->flags & CHUNK_IS_ROOT) { 199 k++; 200 if (c1->flags & CHUNK_PAST_1024) 201 sprintf(msg+strlen(msg), 202 "Root filesystem extends past cylinder 1024, and cannot be booted from\n"); 203 } 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