rules.c revision 105681
1/* 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@FreeBSD.org> 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 10#include <sys/cdefs.h> 11__FBSDID("$FreeBSD: head/lib/libdisk/rules.c 105681 2002-10-22 09:13:02Z phk $"); 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#ifdef PC98 21#include <sys/diskpc98.h> 22#else 23#include <sys/diskmbr.h> 24#endif 25#include "libdisk.h" 26 27int 28Track_Aligned(const struct disk *d, u_long offset) 29{ 30 if (!d->bios_sect) 31 return 1; 32 if (offset % d->bios_sect) 33 return 0; 34 return 1; 35} 36 37u_long 38Prev_Track_Aligned(const struct disk *d, u_long offset) 39{ 40 if (!d->bios_sect) 41 return offset; 42 return (offset / d->bios_sect) * d->bios_sect; 43} 44 45u_long 46Next_Track_Aligned(const struct disk *d, u_long offset) 47{ 48 if (!d->bios_sect) 49 return offset; 50 return Prev_Track_Aligned(d, offset + d->bios_sect-1); 51} 52 53static int 54Cyl_Aligned(const struct disk *d, u_long offset) 55{ 56 if (!d->bios_sect || !d->bios_hd) 57 return 1; 58 if (offset % (d->bios_sect * d->bios_hd)) 59 return 0; 60 return 1; 61} 62 63u_long 64Prev_Cyl_Aligned(const struct disk *d, u_long offset) 65{ 66 if (!d->bios_sect || !d->bios_hd) 67 return offset; 68 return (offset / (d->bios_sect*d->bios_hd)) * d->bios_sect * d->bios_hd; 69} 70 71u_long 72Next_Cyl_Aligned(const struct disk *d, u_long offset) 73{ 74 if (!d->bios_sect || !d->bios_hd) 75 return offset; 76 return Prev_Cyl_Aligned(d,offset + (d->bios_sect * d->bios_hd)-1); 77} 78 79/* 80 * Rule#0: 81 * Chunks of type 'whole' can have max NDOSPART children. 82 * Only one of them can have the "active" flag 83 */ 84static void 85Rule_000(const struct disk *d, const struct chunk *c, char *msg) 86{ 87#ifdef PC98 88 int i=0; 89#else 90 int i=0,j=0; 91#endif 92 struct chunk *c1; 93 94 if (c->type != whole) 95 return; 96 for (c1 = c->part; c1; c1 = c1->next) { 97 if (c1->type != unused) continue; 98#ifndef PC98 99 if (c1->flags & CHUNK_ACTIVE) 100 j++; 101#endif 102 i++; 103 } 104 if (i > NDOSPART) 105 sprintf(msg + strlen(msg), 106 "%d is too many children of the 'whole' chunk. Max is %d\n", 107 i, NDOSPART); 108#ifndef PC98 109 if (j > 1) 110 sprintf(msg + strlen(msg), 111 "Too many active children of 'whole'"); 112#endif 113} 114 115/* 116 * Rule#1: 117 * All children of 'whole' and 'extended' must be track-aligned. 118 * Exception: the end can be unaligned if it matches the end of 'whole' 119 */ 120static void 121Rule_001(const struct disk *d, const struct chunk *c, char *msg) 122{ 123 struct chunk *c1; 124 125 if (c->type != whole && c->type != extended) 126 return; 127 for (c1 = c->part; c1; c1 = c1->next) { 128 if (c1->type == unused) continue; 129 c1->flags |= CHUNK_ALIGN; 130#ifdef PC98 131 if (!Cyl_Aligned(d, c1->offset)) 132#else 133 if (!Track_Aligned(d, c1->offset)) 134#endif 135 sprintf(msg + strlen(msg), 136#ifdef PC98 137 "chunk '%s' [%ld..%ld] does not start on a cylinder boundary\n", 138#else 139 "chunk '%s' [%ld..%ld] does not start on a track boundary\n", 140#endif 141 c1->name, c1->offset, c1->end); 142 if ((c->type == whole || c->end == c1->end) 143 || Cyl_Aligned(d, c1->end + 1)) 144 ; 145 else 146 sprintf(msg + strlen(msg), 147 "chunk '%s' [%ld..%ld] does not end on a cylinder boundary\n", 148 c1->name, c1->offset, c1->end); 149 } 150} 151 152/* 153 * Rule#2: 154 * Max one 'fat' as child of 'whole' 155 */ 156static void 157Rule_002(const struct disk *d, const struct chunk *c, char *msg) 158{ 159#ifndef PC98 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 != fat) 167 continue; 168 i++; 169 } 170 if (i > 1) { 171 sprintf(msg + strlen(msg), 172 "Max one 'fat' allowed as child of 'whole'\n"); 173 } 174#endif 175} 176 177/* 178 * Rule#3: 179 * Max one extended as child of 'whole' 180 */ 181static void 182Rule_003(const struct disk *d, const struct chunk *c, char *msg) 183{ 184#ifndef PC98 185 int i; 186 struct chunk *c1; 187 188 if (c->type != whole) 189 return; 190 for (i = 0, c1 = c->part; c1; c1 = c1->next) { 191 if (c1->type != extended) 192 continue; 193 i++; 194 } 195 if (i > 1) { 196 sprintf(msg + strlen(msg), 197 "Max one 'extended' allowed as child of 'whole'\n"); 198 } 199#endif 200} 201 202/* 203 * Rule#4: 204 * Max seven 'part' as children of 'freebsd' 205 * Max one CHUNK_IS_ROOT child per 'freebsd' 206 */ 207static void 208Rule_004(const struct disk *d, const struct chunk *c, char *msg) 209{ 210 int i=0,k=0; 211 struct chunk *c1; 212 213 if (c->type != freebsd) 214 return; 215 216 for (c1 = c->part; c1; c1 = c1->next) { 217 if (c1->type != part) 218 continue; 219 if (c1->flags & CHUNK_IS_ROOT) 220 k++; 221 i++; 222 } 223 if (i > 7) { 224 sprintf(msg + strlen(msg), 225 "Max seven partitions per freebsd slice\n"); 226 } 227 if (k > 1) { 228 sprintf(msg + strlen(msg), 229 "Max one root partition child per freebsd slice\n"); 230 } 231} 232 233static void 234Check_Chunk(const struct disk *d, const struct chunk *c, char *msg) 235{ 236 Rule_000(d, c, msg); 237 Rule_001(d, c, msg); 238 Rule_002(d, c, msg); 239 Rule_003(d, c, msg); 240 Rule_004(d, c, msg); 241 if (c->part) 242 Check_Chunk(d, c->part, msg); 243 if (c->next) 244 Check_Chunk(d, c->next, msg); 245} 246 247char * 248CheckRules(const struct disk *d) 249{ 250 char msg[BUFSIZ]; 251 252 *msg = '\0'; 253 Check_Chunk(d, d->chunks, msg); 254 if (*msg) 255 return strdup(msg); 256 return 0; 257} 258