1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific prior written permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 */ 12 13 #ifndef lint 14 char copyright[] = 15 "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 16 All rights reserved.\n"; 17 #endif /* not lint */ 18 19 #ifndef lint 20 static char sccsid[] = "@(#)diskpart.c 5.8 (Berkeley) 02/19/88"; 21 #endif /* not lint */ 22 23 /* 24 * Program to calculate standard disk partition sizes. 25 */ 26 #include <sys/param.h> 27 #define DKTYPENAMES 28 #include <sys/disklabel.h> 29 30 #include <stdio.h> 31 #include <ctype.h> 32 33 #define for_now /* show all of `c' partition for disklabel */ 34 #define NPARTITIONS 8 35 #define PART(x) (x - 'a') 36 37 /* 38 * Default partition sizes, where they exist. 39 */ 40 #define NDEFAULTS 4 41 int defpart[NDEFAULTS][NPARTITIONS] = { 42 { 15884, 66880, 0, 15884, 307200, 0, 0, 291346 }, /* ~ 356+ Mbytes */ 43 { 15884, 33440, 0, 15884, 55936, 0, 0, 291346 }, /* ~ 206-355 Mbytes */ 44 { 15884, 33440, 0, 15884, 55936, 0, 0, 0 }, /* ~ 61-205 Mbytes */ 45 { 15884, 10032, 0, 15884, 0, 0, 0, 0 }, /* ~ 20-60 Mbytes */ 46 }; 47 48 /* 49 * Each array defines a layout for a disk; 50 * that is, the collection of partitions totally 51 * covers the physical space on a disk. 52 */ 53 #define NLAYOUTS 3 54 char layouts[NLAYOUTS][NPARTITIONS] = { 55 { 'a', 'b', 'h', 'g' }, 56 { 'a', 'b', 'h', 'd', 'e', 'f' }, 57 { 'c' }, 58 }; 59 60 /* 61 * Default disk block and disk block fragment 62 * sizes for each file system. Those file systems 63 * with zero block and frag sizes are special cases 64 * (e.g. swap areas or for access to the entire device). 65 */ 66 struct partition defparam[NPARTITIONS] = { 67 { 0, 0, 1024, FS_UNUSED, 8, 0 }, /* a */ 68 { 0, 0, 1024, FS_SWAP, 8, 0 }, /* b */ 69 { 0, 0, 1024, FS_UNUSED, 8, 0 }, /* c */ 70 { 0, 0, 512, FS_UNUSED, 8, 0 }, /* d */ 71 { 0, 0, 1024, FS_UNUSED, 8, 0 }, /* e */ 72 { 0, 0, 1024, FS_UNUSED, 8, 0 }, /* f */ 73 { 0, 0, 1024, FS_UNUSED, 8, 0 }, /* g */ 74 { 0, 0, 1024, FS_UNUSED, 8, 0 } /* h */ 75 }; 76 77 /* 78 * Each disk has some space reserved for a bad sector 79 * forwarding table. DEC standard 144 uses the first 80 * 5 even numbered sectors in the last track of the 81 * last cylinder for replicated storage of the bad sector 82 * table; another 126 sectors past this is needed as a 83 * pool of replacement sectors. 84 */ 85 int badsecttable = 126; /* # sectors */ 86 87 int pflag; /* print device driver partition tables */ 88 int dflag; /* print disktab entry */ 89 90 struct disklabel *promptfordisk(); 91 92 main(argc, argv) 93 int argc; 94 char *argv[]; 95 { 96 struct disklabel *dp; 97 register int curcyl, spc, def, part, layout, j; 98 int threshhold, numcyls[NPARTITIONS], startcyl[NPARTITIONS]; 99 char *lp; 100 101 argc--, argv++; 102 if (argc < 1) { 103 fprintf(stderr, "usage: disktab [ -p ] [ -d ] disk-type\n"); 104 exit(1); 105 } 106 if (argc > 0 && strcmp(*argv, "-p") == 0) { 107 pflag++; 108 argc--, argv++; 109 } 110 if (argc > 0 && strcmp(*argv, "-d") == 0) { 111 dflag++; 112 argc--, argv++; 113 } 114 dp = getdiskbyname(*argv); 115 if (dp == NULL) { 116 if (isatty(0)) 117 dp = promptfordisk(*argv); 118 if (dp == NULL) { 119 fprintf(stderr, "%s: unknown disk type\n", *argv); 120 exit(2); 121 } 122 } else { 123 if (dp->d_flags & D_REMOVABLE) 124 strncpy(dp->d_typename, "removable", 125 sizeof(dp->d_typename)); 126 else if (dp->d_flags & D_RAMDISK) 127 strncpy(dp->d_typename, "simulated", 128 sizeof(dp->d_typename)); 129 else 130 strncpy(dp->d_typename, "winchester", 131 sizeof(dp->d_typename)); 132 } 133 spc = dp->d_secpercyl; 134 /* 135 * Bad sector table contains one track for the replicated 136 * copies of the table and enough full tracks preceding 137 * the last track to hold the pool of free blocks to which 138 * bad sectors are mapped. 139 */ 140 if (dp->d_type == DTYPE_SMD && dp->d_flags & D_BADSECT) { 141 badsecttable = dp->d_nsectors + 142 roundup(badsecttable, dp->d_nsectors); 143 threshhold = howmany(spc, badsecttable); 144 } else { 145 badsecttable = 0; 146 threshhold = 0; 147 } 148 149 /* 150 * Figure out if disk is large enough for 151 * expanded swap area and 'd', 'e', and 'f' 152 * partitions. Otherwise, use smaller defaults 153 * based on RK07. 154 */ 155 for (def = 0; def < NDEFAULTS; def++) { 156 curcyl = 0; 157 for (part = PART('a'); part < NPARTITIONS; part++) 158 curcyl += howmany(defpart[def][part], spc); 159 if (curcyl < dp->d_ncylinders - threshhold) 160 break; 161 } 162 if (def >= NDEFAULTS) { 163 fprintf(stderr, "%s: disk too small, calculate by hand\n", 164 *argv); 165 exit(3); 166 } 167 168 /* 169 * Calculate number of cylinders allocated to each disk 170 * partition. We may waste a bit of space here, but it's 171 * in the interest of compatibility (for mixed disk systems). 172 */ 173 for (curcyl = 0, part = PART('a'); part < NPARTITIONS; part++) { 174 numcyls[part] = 0; 175 if (defpart[def][part] != 0) { 176 numcyls[part] = howmany(defpart[def][part], spc); 177 curcyl += numcyls[part]; 178 } 179 } 180 numcyls[PART('f')] = dp->d_ncylinders - curcyl; 181 numcyls[PART('g')] = 182 numcyls[PART('d')] + numcyls[PART('e')] + numcyls[PART('f')]; 183 numcyls[PART('c')] = dp->d_ncylinders; 184 defpart[def][PART('f')] = numcyls[PART('f')] * spc - badsecttable; 185 defpart[def][PART('g')] = numcyls[PART('g')] * spc - badsecttable; 186 defpart[def][PART('c')] = numcyls[PART('c')] * spc; 187 #ifndef for_now 188 if (!pflag) 189 defpart[def][PART('c')] -= badsecttable; 190 #endif 191 192 /* 193 * Calculate starting cylinder number for each partition. 194 * Note the 'h' partition is physically located before the 195 * 'g' or 'd' partition. This is reflected in the layout 196 * arrays defined above. 197 */ 198 for (layout = 0; layout < NLAYOUTS; layout++) { 199 curcyl = 0; 200 for (lp = layouts[layout]; *lp != 0; lp++) { 201 startcyl[PART(*lp)] = curcyl; 202 curcyl += numcyls[PART(*lp)]; 203 } 204 } 205 206 if (pflag) { 207 printf("}, %s_sizes[%d] = {\n", dp->d_typename, NPARTITIONS); 208 for (part = PART('a'); part < NPARTITIONS; part++) { 209 if (numcyls[part] == 0) { 210 printf("\t0,\t0,\n"); 211 continue; 212 } 213 if (dp->d_type != DTYPE_MSCP) { 214 printf("\t%d,\t%d,\t\t/* %c=cyl %d thru %d */\n", 215 defpart[def][part], startcyl[part], 216 'A' + part, startcyl[part], 217 startcyl[part] + numcyls[part] - 1); 218 continue; 219 } 220 printf("\t%d,\t%d,\t\t/* %c=sectors %d thru %d */\n", 221 defpart[def][part], spc * startcyl[part], 222 'A' + part, spc * startcyl[part], 223 spc * startcyl[part] + defpart[def][part] - 1); 224 } 225 exit(0); 226 } 227 if (dflag) { 228 int nparts; 229 230 /* 231 * In case the disk is in the ``in-between'' range 232 * where the 'g' partition is smaller than the 'h' 233 * partition, reverse the frag sizes so the /usr partition 234 * is always set up with a frag size larger than the 235 * user's partition. 236 */ 237 if (defpart[def][PART('g')] < defpart[def][PART('h')]) { 238 int temp; 239 240 temp = defparam[PART('h')].p_fsize; 241 defparam[PART('h')].p_fsize = 242 defparam[PART('g')].p_fsize; 243 defparam[PART('g')].p_fsize = temp; 244 } 245 printf("%s:\\\n", dp->d_typename); 246 printf("\t:ty=%s:ns#%d:nt#%d:nc#%d:", dp->d_typename, 247 dp->d_nsectors, dp->d_ntracks, dp->d_ncylinders); 248 if (dp->d_secpercyl != dp->d_nsectors * dp->d_ntracks) 249 printf("sc#%d:", dp->d_secpercyl); 250 if (dp->d_type == DTYPE_SMD && dp->d_flags & D_BADSECT) 251 printf("sf:"); 252 printf("\\\n\t:dt=%s:", dktypenames[dp->d_type]); 253 for (part = NDDATA - 1; part >= 0; part--) 254 if (dp->d_drivedata[part]) 255 break; 256 for (j = 0; j <= part; j++) 257 printf("d%d#%d:", j, dp->d_drivedata[j]); 258 printf("\\\n"); 259 for (nparts = 0, part = PART('a'); part < NPARTITIONS; part++) 260 if (defpart[def][part] != 0) 261 nparts++; 262 for (part = PART('a'); part < NPARTITIONS; part++) { 263 if (defpart[def][part] == 0) 264 continue; 265 printf("\t:p%c#%d:", 'a' + part, defpart[def][part]); 266 printf("o%c#%d:b%c#%d:f%c#%d:", 267 'a' + part, spc * startcyl[part], 268 'a' + part, 269 defparam[part].p_frag * defparam[part].p_fsize, 270 'a' + part, defparam[part].p_fsize); 271 if (defparam[part].p_fstype == FS_SWAP) 272 printf("t%c=swap:", 'a' + part); 273 nparts--; 274 printf("%s\n", nparts > 0 ? "\\" : ""); 275 } 276 #ifdef for_now 277 defpart[def][PART('c')] -= badsecttable; 278 part = PART('c'); 279 printf("#\t:p%c#%d:", 'a' + part, defpart[def][part]); 280 printf("o%c#%d:b%c#%d:f%c#%d:\n", 281 'a' + part, spc * startcyl[part], 282 'a' + part, 283 defparam[part].p_frag * defparam[part].p_fsize, 284 'a' + part, defparam[part].p_fsize); 285 #endif 286 exit(0); 287 } 288 printf("%s: #sectors/track=%d, #tracks/cylinder=%d #cylinders=%d\n", 289 dp->d_typename, dp->d_nsectors, dp->d_ntracks, 290 dp->d_ncylinders); 291 printf("\n Partition\t Size\t Range\n"); 292 for (part = PART('a'); part < NPARTITIONS; part++) { 293 printf("\t%c\t", 'a' + part); 294 if (numcyls[part] == 0) { 295 printf(" unused\n"); 296 continue; 297 } 298 printf("%7d\t%4d - %d\n", defpart[def][part], startcyl[part], 299 startcyl[part] + numcyls[part] - 1); 300 } 301 } 302 303 struct disklabel disk; 304 305 struct field { 306 char *f_name; 307 char *f_defaults; 308 u_long *f_location; 309 } fields[] = { 310 { "sector size", "512", &disk.d_secsize }, 311 { "#sectors/track", 0, &disk.d_nsectors }, 312 { "#tracks/cylinder", 0, &disk.d_ntracks }, 313 { "#cylinders", 0, &disk.d_ncylinders }, 314 { 0, 0, 0 }, 315 }; 316 317 struct disklabel * 318 promptfordisk(name) 319 char *name; 320 { 321 register struct disklabel *dp = &disk; 322 register struct field *fp; 323 register i; 324 char buf[BUFSIZ], **tp, *cp, *gets(); 325 326 strncpy(dp->d_typename, name, sizeof(dp->d_typename)); 327 fprintf(stderr, 328 "%s: unknown disk type, want to supply parameters (y/n)? ", 329 name); 330 (void) gets(buf); 331 if (*buf != 'y') 332 return ((struct disklabel *)0); 333 for (;;) { 334 fprintf(stderr, "Disk/controller type (%s)? ", dktypenames[1]); 335 (void) gets(buf); 336 if (buf[0] == 0) 337 dp->d_type = 1; 338 else 339 dp->d_type = gettype(buf, dktypenames); 340 if (dp->d_type >= 0) 341 break; 342 fprintf(stderr, "%s: unrecognized controller type\n", buf); 343 fprintf(stderr, "use one of:\n", buf); 344 for (tp = dktypenames; *tp; tp++) 345 if (index(*tp, ' ') == 0) 346 fprintf(stderr, "\t%s\n", *tp); 347 } 348 gettype: 349 dp->d_flags = 0; 350 fprintf(stderr, "type (winchester|removable|simulated)? "); 351 (void) gets(buf); 352 if (strcmp(buf, "removable") == 0) 353 dp->d_flags = D_REMOVABLE; 354 else if (strcmp(buf, "simulated") == 0) 355 dp->d_flags = D_RAMDISK; 356 else if (strcmp(buf, "winchester")) { 357 fprintf(stderr, "%s: bad disk type\n", buf); 358 goto gettype; 359 } 360 strncpy(dp->d_typename, buf, sizeof(dp->d_typename)); 361 fprintf(stderr, "(type <cr> to get default value, if only one)\n"); 362 if (dp->d_type == DTYPE_SMD) 363 fprintf(stderr, "Do %ss support bad144 bad block forwarding (yes)? ", 364 dp->d_typename); 365 (void) gets(buf); 366 if (*buf != 'n') 367 dp->d_flags |= D_BADSECT; 368 for (fp = fields; fp->f_name != NULL; fp++) { 369 again: 370 fprintf(stderr, "%s ", fp->f_name); 371 if (fp->f_defaults != NULL) 372 fprintf(stderr, "(%s)", fp->f_defaults); 373 fprintf(stderr, "? "); 374 cp = gets(buf); 375 if (*cp == '\0') { 376 if (fp->f_defaults == NULL) { 377 fprintf(stderr, "no default value\n"); 378 goto again; 379 } 380 cp = fp->f_defaults; 381 } 382 *fp->f_location = atol(cp); 383 if (*fp->f_location == 0) { 384 fprintf(stderr, "%s: bad value\n", cp); 385 goto again; 386 } 387 } 388 fprintf(stderr, "sectors/cylinder (%d)? ", 389 dp->d_nsectors * dp->d_ntracks); 390 (void) gets(buf); 391 if (buf[0] == 0) 392 dp->d_secpercyl = dp->d_nsectors * dp->d_ntracks; 393 else 394 dp->d_secpercyl = atol(buf); 395 fprintf(stderr, "Drive-type-specific parameters, <cr> to terminate:\n"); 396 for (i = 0; i < NDDATA; i++) { 397 fprintf(stderr, "d%d? ", i); 398 (void) gets(buf); 399 if (buf[0] == 0) 400 break; 401 dp->d_drivedata[i] = atol(buf); 402 } 403 return (dp); 404 } 405 406 gettype(t, names) 407 char *t; 408 char **names; 409 { 410 register char **nm; 411 412 for (nm = names; *nm; nm++) 413 if (ustrcmp(t, *nm) == 0) 414 return (nm - names); 415 if (isdigit(*t)) 416 return (atoi(t)); 417 return (-1); 418 } 419 420 ustrcmp(s1, s2) 421 register char *s1, *s2; 422 { 423 #define lower(c) (islower(c) ? (c) : tolower(c)) 424 425 for (; *s1; s1++, s2++) { 426 if (*s1 == *s2) 427 continue; 428 if (isalpha(*s1) && isalpha(*s2) && 429 lower(*s1) == lower(*s2)) 430 continue; 431 return (*s2 - *s1); 432 } 433 return (0); 434 } 435