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