1 #ifndef lint 2 static char sccsid[] = "@(#)diskpart.c 4.3 (Berkeley) 05/03/83"; 3 #endif 4 5 /* 6 * Program to calculate standard disk partition sizes. 7 */ 8 #include <sys/param.h> 9 10 #include <stdio.h> 11 #include <disktab.h> 12 13 #define NPARTITIONS 8 14 #define PART(x) (x - 'a') 15 16 /* 17 * Default partition sizes, where they exist. 18 */ 19 #define NDEFAULTS 4 20 int defpart[NDEFAULTS][NPARTITIONS] = { 21 { 15884, 66880, 0, 15884, 307200, 0, 0, 291346 }, /* ~ 356+ Mbytes */ 22 { 15884, 33440, 0, 15884, 55936, 0, 0, 291346 }, /* ~ 206-355 Mbytes */ 23 { 15884, 33440, 0, 15884, 55936, 0, 0, 0 }, /* ~ 61-205 Mbytes */ 24 { 15884, 10032, 0, 15884, 0, 0, 0, 0 }, /* ~ 20-60 Mbytes */ 25 }; 26 27 /* 28 * Each array defines a layout for a disk; 29 * that is, the collection of partitions totally 30 * covers the physical space on a disk. 31 */ 32 #define NLAYOUTS 3 33 char layouts[NLAYOUTS][NPARTITIONS] = { 34 { 'a', 'b', 'h', 'g' }, 35 { 'a', 'b', 'h', 'd', 'e', 'f' }, 36 { 'c' }, 37 }; 38 39 /* 40 * Default disk block and disk block fragment 41 * sizes for each file system. Those file systems 42 * with zero block and frag sizes are special cases 43 * (e.g. swap areas or for access to the entire device). 44 */ 45 struct defparam { 46 int p_bsize; /* block size */ 47 int p_fsize; /* frag size */ 48 } defparam[NPARTITIONS] = { 49 { 8192, 1024 }, /* a */ 50 { 0 }, /* b */ 51 { 0 }, /* c */ 52 { 8192, 1024 }, /* d */ 53 { 4096, 512 }, /* e */ 54 { 4096, 1024 }, /* f */ 55 { 4096, 1024 }, /* g */ 56 { 4096, 512 } /* h */ 57 }; 58 59 /* 60 * Each disk has some space reserved for a bad sector 61 * forwarding table. DEC standard 144 uses the first 62 * 5 even numbered sectors in the last track of the 63 * last cylinder for replicated storage of the bad sector 64 * table; another 126 sectors past this is needed as a 65 * pool of replacement sectors. 66 */ 67 int badsecttable = 126; /* # sectors */ 68 69 int pflag; /* print device driver partition tables */ 70 int dflag; /* print disktab entry */ 71 72 struct disktab *promptfordisk(); 73 74 main(argc, argv) 75 int argc; 76 char *argv[]; 77 { 78 struct disktab *dp; 79 register int curcyl, spc, def, part, layout; 80 int threshhold, numcyls[NPARTITIONS], startcyl[NPARTITIONS]; 81 char *lp; 82 83 argc--, argv++; 84 if (argc < 1) { 85 fprintf(stderr, "usage: disktab [ -p ] [ -d ] disk-type\n"); 86 exit(1); 87 } 88 if (argc > 0 && strcmp(*argv, "-p") == 0) { 89 pflag++; 90 argc--, argv++; 91 } 92 if (argc > 0 && strcmp(*argv, "-d") == 0) { 93 dflag++; 94 argc--, argv++; 95 } 96 dp = getdiskbyname(*argv); 97 if (dp == NULL) { 98 if (isatty(0)) 99 dp = promptfordisk(*argv); 100 if (dp == NULL) { 101 fprintf(stderr, "%s: unknown disk type\n", *argv); 102 exit(2); 103 } 104 } 105 spc = dp->d_nsectors * dp->d_ntracks; 106 /* 107 * Bad sector table contains one track for the replicated 108 * copies of the table and enough full tracks preceding 109 * the last track to hold the pool of free blocks to which 110 * bad sectors are mapped. 111 */ 112 badsecttable = dp->d_nsectors + roundup(badsecttable, dp->d_nsectors); 113 threshhold = howmany(spc, badsecttable); 114 115 /* 116 * Figure out if disk is large enough for 117 * expanded swap area and 'd', 'e', and 'f' 118 * partitions. Otherwise, use smaller defaults 119 * based on RK07. 120 */ 121 for (def = 0; def < NDEFAULTS; def++) { 122 curcyl = 0; 123 for (part = PART('a'); part < NPARTITIONS; part++) 124 curcyl += howmany(defpart[def][part], spc); 125 if (curcyl < dp->d_ncylinders - threshhold) 126 break; 127 } 128 if (def >= NDEFAULTS) { 129 fprintf(stderr, "%s: disk too small, calculate by hand\n", 130 *argv); 131 exit(3); 132 } 133 134 /* 135 * Calculate number of cylinders allocated to each disk 136 * partition. We may waste a bit of space here, but it's 137 * in the interest of compatibility (for mixed disk systems). 138 */ 139 for (curcyl = 0, part = PART('a'); part < NPARTITIONS; part++) { 140 numcyls[part] = 0; 141 if (defpart[def][part] != 0) { 142 numcyls[part] = howmany(defpart[def][part], spc); 143 curcyl += numcyls[part]; 144 } 145 } 146 numcyls[PART('f')] = dp->d_ncylinders - curcyl; 147 numcyls[PART('g')] = 148 numcyls[PART('d')] + numcyls[PART('e')] + numcyls[PART('f')]; 149 numcyls[PART('c')] = dp->d_ncylinders; 150 defpart[def][PART('f')] = numcyls[PART('f')] * spc - badsecttable; 151 defpart[def][PART('g')] = numcyls[PART('g')] * spc - badsecttable; 152 defpart[def][PART('c')] = numcyls[PART('c')] * spc; 153 154 /* 155 * Calculate starting cylinder number for each partition. 156 * Note the 'h' partition is physically located before the 157 * 'g' or 'd' partition. This is reflected in the layout 158 * arrays defined above. 159 */ 160 for (layout = 0; layout < NLAYOUTS; layout++) { 161 curcyl = 0; 162 for (lp = layouts[layout]; *lp != 0; lp++) { 163 startcyl[PART(*lp)] = curcyl; 164 curcyl += numcyls[PART(*lp)]; 165 } 166 } 167 168 if (pflag) { 169 printf("}, %s_sizes[%d] = {\n", dp->d_name, NPARTITIONS); 170 for (part = PART('a'); part < NPARTITIONS; part++) { 171 if (numcyls[part] == 0) { 172 printf("\t0,\t0,\n"); 173 continue; 174 } 175 printf("\t%d,\t%d,\t\t/* %c=cyl %d thru %d */\n", 176 defpart[def][part], startcyl[part], 177 'A' + part, startcyl[part], 178 startcyl[part] + numcyls[part] - 1); 179 } 180 exit(0); 181 } 182 if (dflag) { 183 int nparts; 184 185 /* 186 * In case the disk is in the ``in-between'' range 187 * where the 'g' partition is smaller than the 'h' 188 * partition, reverse the frag sizes so the /usr partition 189 * is always set up with a frag size larger than the 190 * user's partition. 191 */ 192 if (defpart[def][PART('g')] < defpart[def][PART('h')]) { 193 int temp; 194 195 temp = defparam[PART('h')].p_fsize; 196 defparam[PART('h')].p_fsize = 197 defparam[PART('g')].p_fsize; 198 defparam[PART('g')].p_fsize = temp; 199 } 200 printf("%s:\\\n", dp->d_name); 201 printf("\t:ty=%s:ns#%d:nt#%d:nc#%d:\\\n", dp->d_type, 202 dp->d_nsectors, dp->d_ntracks, dp->d_ncylinders); 203 for (nparts = 0, part = PART('a'); part < NPARTITIONS; part++) 204 if (defpart[def][part] != 0) 205 nparts++; 206 for (part = PART('a'); part < NPARTITIONS; part++) { 207 if (defpart[def][part] == 0) 208 continue; 209 printf("\t:p%c#%d:", 'a' + part, defpart[def][part]); 210 if (defparam[part].p_bsize != 0) { 211 printf("b%c#%d:f%c#%d:", 212 'a' + part, defparam[part].p_bsize, 213 'a' + part, defparam[part].p_fsize); 214 } 215 nparts--; 216 printf("%s\n", nparts > 0 ? "\\" : ""); 217 } 218 exit(0); 219 } 220 printf("%s: #sectors/track=%d, #tracks/cylinder=%d #cylinders=%d\n", 221 dp->d_name, dp->d_nsectors, dp->d_ntracks, dp->d_ncylinders); 222 printf("\n Partition\t Size\t Range\n"); 223 for (part = PART('a'); part < NPARTITIONS; part++) { 224 printf("\t%c\t", 'a' + part); 225 if (numcyls[part] == 0) { 226 printf(" unused\n"); 227 continue; 228 } 229 printf("%7d\t%4d - %d\n", defpart[def][part], startcyl[part], 230 startcyl[part] + numcyls[part] - 1); 231 } 232 } 233 234 struct disktab disk; 235 236 struct field { 237 char *f_name; 238 char *f_defaults; 239 int *f_location; 240 } fields[] = { 241 { "sector size", "512", &disk.d_secsize }, 242 { "#sectors/track", 0, &disk.d_nsectors }, 243 { "#tracks/cylinder", 0, &disk.d_ntracks }, 244 { "#cylinders", 0, &disk.d_ncylinders }, 245 { "revolutions/minute", "3600", &disk.d_rpm }, 246 { 0, 0, 0 }, 247 }; 248 249 struct disktab * 250 promptfordisk(name) 251 char *name; 252 { 253 register struct disktab *dp = &disk; 254 register struct field *fp; 255 static char type[BUFSIZ]; 256 char buf[BUFSIZ], *cp, *gets(); 257 258 dp->d_name = name; 259 fprintf(stderr, 260 "%s: unknown disk type, want to supply parameters (y/n)? ", 261 name); 262 (void) gets(buf); 263 if (*buf != 'y') 264 return ((struct disktab *)0); 265 gettype: 266 fprintf(stderr, "type (winchester|removable|simulated)? "); 267 (void) gets(type); 268 if (strcmp(type, "winchester") && strcmp(type, "removable") && 269 strcmp(type, "simulated")) { 270 fprintf(stderr, "%s: bad disk type\n", type); 271 goto gettype; 272 } 273 dp->d_type = type; 274 fprintf(stderr, "(type <cr> to get default value, if only one)\n"); 275 for (fp = fields; fp->f_name != NULL; fp++) { 276 again: 277 fprintf(stderr, "%s ", fp->f_name); 278 if (fp->f_defaults != NULL) 279 fprintf(stderr, "(%s)", fp->f_defaults); 280 fprintf(stderr, "? "); 281 cp = gets(buf); 282 if (*cp == '\0') { 283 if (fp->f_defaults == NULL) { 284 fprintf(stderr, "no default value\n"); 285 goto again; 286 } 287 cp = fp->f_defaults; 288 } 289 *fp->f_location = atoi(cp); 290 if (*fp->f_location == 0) { 291 fprintf(stderr, "%s: bad value\n", cp); 292 goto again; 293 } 294 } 295 return (dp); 296 } 297