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