00001
00002
00003
00004 #define nil ((void*)0)
00005 #include <stdio.h>
00006 #include <sys/types.h>
00007 #include <stdlib.h>
00008 #include <unistd.h>
00009 #include <fcntl.h>
00010 #include <minix/config.h>
00011 #include <minix/const.h>
00012 #include <minix/partition.h>
00013 #include <minix/u64.h>
00014 #include <ibm/partition.h>
00015 #include <sys/stat.h>
00016 #include <string.h>
00017 #include <errno.h>
00018 #include <sys/ioctl.h>
00019 #include <limits.h>
00020
00021 #define SECTOR_SIZE 512
00022
00023 #define arraysize(a) (sizeof(a)/sizeof((a)[0]))
00024 #define arraylimit(a) ((a) + arraysize(a))
00025
00026 char *arg0;
00027
00028 void report(const char *label)
00029 {
00030 fprintf(stderr, "%s: %s: %s\n", arg0, label, strerror(errno));
00031 }
00032
00033 void fatal(const char *label)
00034 {
00035 report(label);
00036 exit(1);
00037 }
00038
00039 #ifndef makedev
00040 #define minor(dev) (((dev) >> MINOR) & BYTE)
00041 #define major(dev) (((dev) >> MAJOR) & BYTE)
00042 #define makedev(major, minor) \
00043 ((dev_t) (((major) << MAJOR) | ((minor) << MINOR)))
00044 #endif
00045
00046 int aflag;
00047 int mflag;
00048 int rflag;
00049 int fflag;
00050 int nflag;
00051
00052 int cylinders, heads, sectors;
00053 int pad;
00054
00055
00056
00057
00058 char *device;
00059 struct part_entry primary, table[2 * NR_PARTITIONS + 1];
00060 int npart;
00061
00062
00063 #define EXPAND_FLAG 0x01
00064 #define EXIST_FLAG 0x02
00065
00066 void find_exist(struct part_entry *exist, int sysind, int nr)
00067 {
00068 int f;
00069 u16_t signature;
00070 struct part_entry oldtable[NR_PARTITIONS];
00071 int n, i;
00072 u32_t minlow, curlow;
00073 struct part_entry *cur;
00074 char *nr_s[] = { "", "second ", "third ", "fourth" };
00075
00076 if ((f= open(device, O_RDONLY)) < 0
00077
00078 || lseek(f, (off_t) PART_TABLE_OFF, SEEK_SET) == -1
00079
00080 || read(f, oldtable, sizeof(oldtable)) < 0
00081
00082 || read(f, &signature, sizeof(signature)) < 0
00083
00084 || close(f) < 0
00085 ) fatal(device);
00086
00087 minlow= 0;
00088 n= 0;
00089 for (;;) {
00090 curlow= -1;
00091 cur= nil;
00092 for (i= 0; i < NR_PARTITIONS; i++) {
00093 if (signature == 0xAA55
00094 && oldtable[i].sysind != NO_PART
00095 && oldtable[i].lowsec >= minlow
00096 && oldtable[i].lowsec < curlow
00097 ) {
00098 cur= &oldtable[i];
00099 curlow= oldtable[i].lowsec;
00100 }
00101 }
00102 if (n == nr) break;
00103 n++;
00104 minlow= curlow+1;
00105 }
00106
00107 if (cur == nil || cur->sysind != sysind) {
00108 fprintf(stderr,
00109 "%s: Can't find a %sexisting partition of type 0x%02X\n",
00110 arg0, nr_s[nr], sysind);
00111 exit(1);
00112 }
00113 *exist = *cur;
00114 }
00115
00116 void write_table(void)
00117 {
00118 int f;
00119 u16_t signature= 0xAA55;
00120 struct part_entry newtable[NR_PARTITIONS];
00121 int i;
00122
00123 if (nflag) {
00124 printf("(Table not written)\n");
00125 return;
00126 }
00127
00128 for (i= 0; i < NR_PARTITIONS; i++) newtable[i]= table[1 + 2*i];
00129
00130 if ((f= open(device, O_WRONLY)) < 0
00131
00132 || lseek(f, (off_t) PART_TABLE_OFF, SEEK_SET) == -1
00133
00134 || write(f, newtable, sizeof(newtable)) < 0
00135
00136 || write(f, &signature, sizeof(signature)) < 0
00137
00138 || close(f) < 0
00139 ) fatal(device);
00140 }
00141
00142 void sec2dos(unsigned long sec, unsigned char *dos)
00143
00144 {
00145 unsigned secspcyl= heads * sectors;
00146 unsigned cyl;
00147
00148 cyl= sec / secspcyl;
00149 dos[2]= cyl;
00150 dos[1]= ((sec % sectors) + 1) | ((cyl >> 2) & 0xC0);
00151 dos[0]= (sec % secspcyl) / sectors;
00152 }
00153
00154 void show_chs(unsigned long pos)
00155 {
00156 int cyl, head, sec;
00157
00158 if (pos == -1) {
00159 cyl= head= 0;
00160 sec= -1;
00161 } else {
00162 cyl= pos / (heads * sectors);
00163 head= (pos / sectors) - (cyl * heads);
00164 sec= pos % sectors;
00165 }
00166 printf(" %4d/%03d/%02d", cyl, head, sec);
00167 }
00168
00169 void show_part(struct part_entry *p)
00170 {
00171 static int banner= 0;
00172 int n;
00173
00174 n= p - table;
00175 if ((n % 2) == 0) return;
00176
00177 if (!banner) {
00178 printf(
00179 "Part First Last Base Size Kb\n");
00180 banner= 1;
00181 }
00182
00183 printf("%3d ", (n-1) / 2);
00184 show_chs(p->lowsec);
00185 show_chs(p->lowsec + p->size - 1);
00186 printf(" %8lu %8lu %7lu\n", p->lowsec, p->size, p->size / 2);
00187 }
00188
00189 void usage(void)
00190 {
00191 fprintf(stderr,
00192 "Usage: partition [-mfn] device [type:]length[+*] ...\n");
00193 exit(1);
00194 }
00195
00196 #define between(a, c, z) ((unsigned) ((c) - (a)) <= ((z) - (a)))
00197
00198 void parse(char *descr)
00199 {
00200 int seen= 0, sysind, flags, c;
00201 unsigned long lowsec, size;
00202
00203 lowsec= 0;
00204
00205 if (strchr(descr, ':') == nil) {
00206
00207 if ((npart % 2) != 0) {
00208 fprintf(stderr, "%s: Two holes can't be adjacent.\n",
00209 arg0);
00210 exit(1);
00211 }
00212 sysind= NO_PART;
00213 seen|= 1;
00214 } else {
00215
00216 if ((npart % 2) == 0) {
00217
00218 if (npart == 0) {
00219
00220 table[0].size= 1;
00221 }
00222 npart++;
00223 }
00224 sysind= 0;
00225 for (;;) {
00226 c= *descr++;
00227 if (between('0', c, '9'))
00228 c= (c - '0') + 0x0;
00229 else
00230 if (between('a', c, 'z'))
00231 c= (c - 'a') + 0xa;
00232 else
00233 if (between('A', c, 'Z'))
00234 c= (c - 'A') + 0xA;
00235 else
00236 break;
00237 sysind= 0x10 * sysind + c;
00238 seen|= 1;
00239 }
00240 if (c != ':') usage();
00241 }
00242
00243 flags= 0;
00244
00245 if (strncmp(descr, "exist", 5) == 0 && (npart % 2) == 1) {
00246 struct part_entry exist;
00247
00248 find_exist(&exist, sysind, (npart - 1) / 2);
00249 sysind= exist.sysind;
00250 lowsec= exist.lowsec;
00251 size= exist.size;
00252 flags |= EXIST_FLAG;
00253 descr += 5;
00254 c= *descr++;
00255 seen|= 2;
00256 } else {
00257 size= 0;
00258 while (between('0', (c= *descr++), '9')) {
00259 size= 10 * size + (c - '0');
00260 seen|= 2;
00261 }
00262 }
00263
00264 for (;;) {
00265 if (c == '*')
00266 flags|= ACTIVE_FLAG;
00267 else
00268 if (c == '+' && !(flags & EXIST_FLAG))
00269 flags|= EXPAND_FLAG;
00270 else
00271 break;
00272 c= *descr++;
00273 }
00274
00275 if (seen != 3 || c != 0) usage();
00276
00277 if (npart == arraysize(table)) {
00278 fprintf(stderr, "%s: too many partitions, only %d possible.\n",
00279 arg0, NR_PARTITIONS);
00280 exit(1);
00281 }
00282 table[npart].bootind= flags;
00283 table[npart].sysind= sysind;
00284 table[npart].lowsec= lowsec;
00285 table[npart].size= size;
00286 npart++;
00287 }
00288
00289 void geometry(void)
00290
00291
00292
00293 {
00294 int fd;
00295 struct partition geometry;
00296 struct stat sb;
00297
00298 if ((fd= open(device, O_RDONLY)) < 0) fatal(device);
00299
00300
00301 if (ioctl(fd, DIOCGETP, &geometry) < 0)
00302 {
00303
00304 if (fstat(fd, &sb) < 0)
00305 fatal(device);
00306 geometry.base= cvul64(0);
00307 geometry.size= cvul64(sb.st_size);
00308 geometry.sectors= 32;
00309 geometry.heads= 64;
00310 geometry.cylinders= (sb.st_size-1)/SECTOR_SIZE/
00311 (geometry.sectors*geometry.heads) + 1;
00312 }
00313 close(fd);
00314 primary.lowsec= div64u(geometry.base, SECTOR_SIZE);
00315 primary.size= div64u(geometry.size, SECTOR_SIZE);
00316 cylinders= geometry.cylinders;
00317 heads= geometry.heads;
00318 sectors= geometry.sectors;
00319
00320
00321 pad= (!mflag && primary.lowsec == 0);
00322 }
00323
00324 void boundary(struct part_entry *pe, int exp)
00325
00326
00327
00328 {
00329 unsigned n;
00330
00331 n= !pad ? 1 : pe == &table[0] ? sectors : heads * sectors;
00332 if (exp) pe->size+= n - 1;
00333 pe->size= ((pe->lowsec + pe->size) / n * n) - pe->lowsec;
00334 }
00335
00336 void distribute(void)
00337
00338
00339
00340
00341 {
00342 struct part_entry *pe, *exp;
00343 long count;
00344 unsigned long base, size, oldbase;
00345
00346 do {
00347 exp= nil;
00348 base= primary.lowsec;
00349 count= primary.size;
00350
00351 for (pe= table; pe < arraylimit(table); pe++) {
00352 oldbase= base;
00353 if (pe->bootind & EXIST_FLAG) {
00354 if (base > pe->lowsec) {
00355 fprintf(stderr,
00356 "%s: fixed partition %d is preceded by too big partitions/holes\n",
00357 arg0, ((pe - table) - 1) / 2);
00358 exit(1);
00359 }
00360 exp= nil;
00361 } else {
00362 pe->lowsec= base;
00363 boundary(pe, 1);
00364 if (pe->bootind & EXPAND_FLAG) exp= pe;
00365 }
00366 base= pe->lowsec + pe->size;
00367 count-= base - oldbase;
00368 }
00369 if (count < 0) {
00370 if (fflag) break;
00371 fprintf(stderr, "%s: %s is %ld sectors too small\n",
00372 arg0, device, -count);
00373 exit(1);
00374 }
00375 if (exp != nil) {
00376
00377
00378
00379 exp->size+= count;
00380 boundary(exp, 0);
00381 exp->bootind&= ~EXPAND_FLAG;
00382 }
00383 } while (exp != nil);
00384
00385 for (pe= table; pe < arraylimit(table); pe++) {
00386 if (pe->sysind == NO_PART) {
00387 memset(pe, 0, sizeof(*pe));
00388 } else {
00389 sec2dos(pe->lowsec, &pe->start_head);
00390 sec2dos(pe->lowsec + pe->size - 1, &pe->last_head);
00391 pe->bootind&= ACTIVE_FLAG;
00392 }
00393 show_part(pe);
00394 }
00395 }
00396
00397 int main(int argc, char **argv)
00398 {
00399 int i;
00400
00401 if ((arg0= strrchr(argv[0], '/')) == nil) arg0= argv[0]; else arg0++;
00402
00403 i= 1;
00404 while (i < argc && argv[i][0] == '-') {
00405 char *opt= argv[i++] + 1;
00406
00407 if (opt[0] == '-' && opt[1] == 0) break;
00408
00409 while (*opt != 0) switch (*opt++) {
00410 case 'a': aflag= 1; break;
00411 case 'm': mflag= 1; break;
00412 case 'r': rflag= 1; break;
00413 case 'f': fflag= 1; break;
00414 case 'n': nflag= 1; break;
00415 default: usage();
00416 }
00417 }
00418
00419 if (rflag) {
00420 if (aflag) usage();
00421 if ((argc - i) != 1) usage();
00422 fprintf(stderr, "%s: -r is not yet implemented\n");
00423 exit(1);
00424 } else {
00425 if ((argc - i) < 1) usage();
00426 if (aflag) fprintf(stderr, "%s: -a is not yet implemented\n");
00427
00428 device= argv[i++];
00429 geometry();
00430
00431 while (i < argc) parse(argv[i++]);
00432
00433 distribute();
00434 write_table();
00435 }
00436 exit(0);
00437 }