[9] | 1 | /*
|
---|
| 2 | * mformat.c
|
---|
| 3 | */
|
---|
| 4 | #define DONT_NEED_WAIT
|
---|
| 5 |
|
---|
| 6 | #include "sysincludes.h"
|
---|
| 7 | #include "msdos.h"
|
---|
| 8 | #include "mtools.h"
|
---|
| 9 | #include "mainloop.h"
|
---|
| 10 | #include "fsP.h"
|
---|
| 11 | #include "file.h"
|
---|
| 12 | #include "plain_io.h"
|
---|
| 13 | #include "nameclash.h"
|
---|
| 14 | #include "buffer.h"
|
---|
| 15 | #include "scsi.h"
|
---|
| 16 | #include "partition.h"
|
---|
| 17 |
|
---|
| 18 | #ifdef OS_linux
|
---|
| 19 | #include "linux/hdreg.h"
|
---|
| 20 |
|
---|
| 21 | #define _LINUX_STRING_H_
|
---|
| 22 | #define kdev_t int
|
---|
| 23 | #include "linux/fs.h"
|
---|
| 24 | #undef _LINUX_STRING_H_
|
---|
| 25 |
|
---|
| 26 | #endif
|
---|
| 27 |
|
---|
| 28 | #define tolinear(x) \
|
---|
| 29 | (sector(x)-1+(head(x)+cyl(x)*used_dev->heads)*used_dev->sectors)
|
---|
| 30 |
|
---|
| 31 |
|
---|
| 32 | static inline void print_hsc(hsc *h)
|
---|
| 33 | {
|
---|
| 34 | printf(" h=%d s=%d c=%d\n",
|
---|
| 35 | head(*h), sector(*h), cyl(*h));
|
---|
| 36 | }
|
---|
| 37 |
|
---|
| 38 | static void set_offset(hsc *h, int offset, int heads, int sectors)
|
---|
| 39 | {
|
---|
| 40 | int head, sector, cyl;
|
---|
| 41 |
|
---|
| 42 | if(! heads || !sectors)
|
---|
| 43 | head = sector = cyl = 0; /* linear mode */
|
---|
| 44 | else {
|
---|
| 45 | sector = offset % sectors;
|
---|
| 46 | offset = offset / sectors;
|
---|
| 47 |
|
---|
| 48 | head = offset % heads;
|
---|
| 49 | cyl = offset / heads;
|
---|
| 50 | if(cyl > 1023) cyl = 1023;
|
---|
| 51 | }
|
---|
| 52 |
|
---|
| 53 | h->head = head;
|
---|
| 54 | h->sector = ((sector+1) & 0x3f) | ((cyl & 0x300)>>2);
|
---|
| 55 | h->cyl = cyl & 0xff;
|
---|
| 56 | }
|
---|
| 57 |
|
---|
| 58 | void setBeginEnd(struct partition *partTable, int begin, int end,
|
---|
| 59 | int heads, int sectors, int activate, int type)
|
---|
| 60 | {
|
---|
| 61 | set_offset(&partTable->start, begin, heads, sectors);
|
---|
| 62 | set_offset(&partTable->end, end-1, heads, sectors);
|
---|
| 63 | set_dword(partTable->start_sect, begin);
|
---|
| 64 | set_dword(partTable->nr_sects, end-begin);
|
---|
| 65 | if(activate)
|
---|
| 66 | partTable->boot_ind = 0x80;
|
---|
| 67 | else
|
---|
| 68 | partTable->boot_ind = 0;
|
---|
| 69 | if(!type) {
|
---|
| 70 | if(end-begin < 4096)
|
---|
| 71 | type = 1; /* DOS 12-bit FAT */
|
---|
| 72 | else if(end-begin<32*2048)
|
---|
| 73 | type = 4; /* DOS 16-bit FAT, <32M */
|
---|
| 74 | else
|
---|
| 75 | type = 6; /* DOS 16-bit FAT >= 32M */
|
---|
| 76 | }
|
---|
| 77 | partTable->sys_ind = type;
|
---|
| 78 | }
|
---|
| 79 |
|
---|
| 80 | int consistencyCheck(struct partition *partTable, int doprint, int verbose,
|
---|
| 81 | int *has_activated, int *last_end, int *j,
|
---|
| 82 | struct device *used_dev, int target_partition)
|
---|
| 83 | {
|
---|
| 84 | int i;
|
---|
| 85 | int inconsistency;
|
---|
| 86 |
|
---|
| 87 | *j = 0;
|
---|
| 88 | *last_end = 1;
|
---|
| 89 |
|
---|
| 90 | /* quick consistency check */
|
---|
| 91 | inconsistency = 0;
|
---|
| 92 | *has_activated = 0;
|
---|
| 93 | for(i=1; i<5; i++){
|
---|
| 94 | if(!partTable[i].sys_ind)
|
---|
| 95 | continue;
|
---|
| 96 | if(partTable[i].boot_ind)
|
---|
| 97 | (*has_activated)++;
|
---|
| 98 | if((used_dev &&
|
---|
| 99 | (used_dev->heads != head(partTable[i].end)+1 ||
|
---|
| 100 | used_dev->sectors != sector(partTable[i].end))) ||
|
---|
| 101 | sector(partTable[i].start) != 1){
|
---|
| 102 | fprintf(stderr,
|
---|
| 103 | "Partition %d is not aligned\n",
|
---|
| 104 | i);
|
---|
| 105 | inconsistency=1;
|
---|
| 106 | }
|
---|
| 107 |
|
---|
| 108 | if(*j && *last_end > BEGIN(partTable[i])) {
|
---|
| 109 | fprintf(stderr,
|
---|
| 110 | "Partitions %d and %d badly ordered or overlapping\n",
|
---|
| 111 | *j,i);
|
---|
| 112 | inconsistency=1;
|
---|
| 113 | }
|
---|
| 114 |
|
---|
| 115 | *last_end = END(partTable[i]);
|
---|
| 116 | *j = i;
|
---|
| 117 |
|
---|
| 118 | if(used_dev &&
|
---|
| 119 | cyl(partTable[i].start) != 1023 &&
|
---|
| 120 | tolinear(partTable[i].start) != BEGIN(partTable[i])) {
|
---|
| 121 | fprintf(stderr,
|
---|
| 122 | "Start position mismatch for partition %d\n",
|
---|
| 123 | i);
|
---|
| 124 | inconsistency=1;
|
---|
| 125 | }
|
---|
| 126 | if(used_dev &&
|
---|
| 127 | cyl(partTable[i].end) != 1023 &&
|
---|
| 128 | tolinear(partTable[i].end)+1 != END(partTable[i])) {
|
---|
| 129 | fprintf(stderr,
|
---|
| 130 | "End position mismatch for partition %d\n",
|
---|
| 131 | i);
|
---|
| 132 | inconsistency=1;
|
---|
| 133 | }
|
---|
| 134 |
|
---|
| 135 | if(doprint && verbose) {
|
---|
| 136 | if(i==target_partition)
|
---|
| 137 | putchar('*');
|
---|
| 138 | else
|
---|
| 139 | putchar(' ');
|
---|
| 140 | printf("Partition %d\n",i);
|
---|
| 141 |
|
---|
| 142 | printf(" active=%x\n", partTable[i].boot_ind);
|
---|
| 143 | printf(" start:");
|
---|
| 144 | print_hsc(&partTable[i].start);
|
---|
| 145 | printf(" type=0x%x\n", partTable[i].sys_ind);
|
---|
| 146 | printf(" end:");
|
---|
| 147 | print_hsc(&partTable[i].end);
|
---|
| 148 | printf(" start=%d\n", BEGIN(partTable[i]));
|
---|
| 149 | printf(" nr=%d\n", _DWORD(partTable[i].nr_sects));
|
---|
| 150 | printf("\n");
|
---|
| 151 | }
|
---|
| 152 | }
|
---|
| 153 | return inconsistency;
|
---|
| 154 | }
|
---|
| 155 |
|
---|
| 156 | /* setsize function. Determines scsicam mapping if this cannot be inferred from
|
---|
| 157 | * any existing partitions. Shamelessly snarfed from the Linux kernel ;-) */
|
---|
| 158 |
|
---|
| 159 | /*
|
---|
| 160 | * Function : static int setsize(unsigned long capacity,unsigned int *cyls,
|
---|
| 161 | * unsigned int *hds, unsigned int *secs);
|
---|
| 162 | *
|
---|
| 163 | * Purpose : to determine a near-optimal int 0x13 mapping for a
|
---|
| 164 | * SCSI disk in terms of lost space of size capacity, storing
|
---|
| 165 | * the results in *cyls, *hds, and *secs.
|
---|
| 166 | *
|
---|
| 167 | * Returns : -1 on failure, 0 on success.
|
---|
| 168 | *
|
---|
| 169 | * Extracted from
|
---|
| 170 | *
|
---|
| 171 | * WORKING X3T9.2
|
---|
| 172 | * DRAFT 792D
|
---|
| 173 | *
|
---|
| 174 | *
|
---|
| 175 | * Revision 6
|
---|
| 176 | * 10-MAR-94
|
---|
| 177 | * Information technology -
|
---|
| 178 | * SCSI-2 Common access method
|
---|
| 179 | * transport and SCSI interface module
|
---|
| 180 | *
|
---|
| 181 | * ANNEX A :
|
---|
| 182 | *
|
---|
| 183 | * setsize() converts a read capacity value to int 13h
|
---|
| 184 | * head-cylinder-sector requirements. It minimizes the value for
|
---|
| 185 | * number of heads and maximizes the number of cylinders. This
|
---|
| 186 | * will support rather large disks before the number of heads
|
---|
| 187 | * will not fit in 4 bits (or 6 bits). This algorithm also
|
---|
| 188 | * minimizes the number of sectors that will be unused at the end
|
---|
| 189 | * of the disk while allowing for very large disks to be
|
---|
| 190 | * accommodated. This algorithm does not use physical geometry.
|
---|
| 191 | */
|
---|
| 192 |
|
---|
| 193 | static int setsize(unsigned long capacity,unsigned int *cyls,unsigned int *hds,
|
---|
| 194 | unsigned int *secs) {
|
---|
| 195 | unsigned int rv = 0;
|
---|
| 196 | unsigned long heads, sectors, cylinders, temp;
|
---|
| 197 |
|
---|
| 198 | cylinders = 1024L; /* Set number of cylinders to max */
|
---|
| 199 | sectors = 62L; /* Maximize sectors per track */
|
---|
| 200 |
|
---|
| 201 | temp = cylinders * sectors; /* Compute divisor for heads */
|
---|
| 202 | heads = capacity / temp; /* Compute value for number of heads */
|
---|
| 203 | if (capacity % temp) { /* If no remainder, done! */
|
---|
| 204 | heads++; /* Else, increment number of heads */
|
---|
| 205 | temp = cylinders * heads; /* Compute divisor for sectors */
|
---|
| 206 | sectors = capacity / temp; /* Compute value for sectors per
|
---|
| 207 | track */
|
---|
| 208 | if (capacity % temp) { /* If no remainder, done! */
|
---|
| 209 | sectors++; /* Else, increment number of sectors */
|
---|
| 210 | temp = heads * sectors; /* Compute divisor for cylinders */
|
---|
| 211 | cylinders = capacity / temp;/* Compute number of cylinders */
|
---|
| 212 | }
|
---|
| 213 | }
|
---|
| 214 | if (cylinders == 0) rv=(unsigned)-1;/* Give error if 0 cylinders */
|
---|
| 215 |
|
---|
| 216 | *cyls = (unsigned int) cylinders; /* Stuff return values */
|
---|
| 217 | *secs = (unsigned int) sectors;
|
---|
| 218 | *hds = (unsigned int) heads;
|
---|
| 219 | return(rv);
|
---|
| 220 | }
|
---|
| 221 |
|
---|
| 222 | static void setsize0(unsigned long capacity,unsigned int *cyls,
|
---|
| 223 | unsigned int *hds, unsigned int *secs)
|
---|
| 224 | {
|
---|
| 225 | int r;
|
---|
| 226 |
|
---|
| 227 | /* 1. First try "Megabyte" sizes */
|
---|
| 228 | if(capacity < 1024 * 2048 && !(capacity % 1024)) {
|
---|
| 229 | *cyls = capacity >> 11;
|
---|
| 230 | *hds = 64;
|
---|
| 231 | *secs = 32;
|
---|
| 232 | return;
|
---|
| 233 | }
|
---|
| 234 |
|
---|
| 235 | /* then try scsicam's size */
|
---|
| 236 | r = setsize(capacity,cyls,hds,secs);
|
---|
| 237 | if(r || *hds > 255 || *secs > 63) {
|
---|
| 238 | /* scsicam failed. Do megabytes anyways */
|
---|
| 239 | *cyls = capacity >> 11;
|
---|
| 240 | *hds = 64;
|
---|
| 241 | *secs = 32;
|
---|
| 242 | return;
|
---|
| 243 | }
|
---|
| 244 | }
|
---|
| 245 |
|
---|
| 246 |
|
---|
| 247 | static void usage(void)
|
---|
| 248 | {
|
---|
| 249 | fprintf(stderr,
|
---|
| 250 | "Mtools version %s, dated %s\n", mversion, mdate);
|
---|
| 251 | fprintf(stderr,
|
---|
| 252 | "Usage: %s [-pradcv] [-I [-B bootsect-template] [-s sectors] "
|
---|
| 253 | "[-t cylinders] "
|
---|
| 254 | "[-h heads] [-T type] [-b begin] [-l length] "
|
---|
| 255 | "drive\n", progname);
|
---|
| 256 | exit(1);
|
---|
| 257 | }
|
---|
| 258 |
|
---|
| 259 | void mpartition(int argc, char **argv, int dummy)
|
---|
| 260 | {
|
---|
| 261 | Stream_t *Stream;
|
---|
| 262 | unsigned int dummy2;
|
---|
| 263 |
|
---|
| 264 | int i,j;
|
---|
| 265 |
|
---|
| 266 | int sec_per_cyl;
|
---|
| 267 | int doprint = 0;
|
---|
| 268 | int verbose = 0;
|
---|
| 269 | int create = 0;
|
---|
| 270 | int force = 0;
|
---|
| 271 | int length = 0;
|
---|
| 272 | int remove = 0;
|
---|
| 273 | int initialize = 0;
|
---|
| 274 | int tot_sectors=0;
|
---|
| 275 | int type = 0;
|
---|
| 276 | int begin_set = 0;
|
---|
| 277 | int size_set = 0;
|
---|
| 278 | int end_set = 0;
|
---|
| 279 | int last_end = 0;
|
---|
| 280 | int activate = 0;
|
---|
| 281 | int has_activated = 0;
|
---|
| 282 | int inconsistency=0;
|
---|
| 283 | int begin=0;
|
---|
| 284 | int end=0;
|
---|
| 285 | int sizetest=0;
|
---|
| 286 | int dirty = 0;
|
---|
| 287 | int open2flags = NO_OFFSET;
|
---|
| 288 |
|
---|
| 289 | int c;
|
---|
| 290 | struct device used_dev;
|
---|
| 291 | int argtracks, argheads, argsectors;
|
---|
| 292 |
|
---|
| 293 | char *drive, name[EXPAND_BUF];
|
---|
| 294 | unsigned char buf[512];
|
---|
| 295 | struct partition *partTable=(struct partition *)(buf+ 0x1ae);
|
---|
| 296 | struct device *dev;
|
---|
| 297 | char errmsg[200];
|
---|
| 298 | char *bootSector=0;
|
---|
| 299 |
|
---|
| 300 | argtracks = 0;
|
---|
| 301 | argheads = 0;
|
---|
| 302 | argsectors = 0;
|
---|
| 303 |
|
---|
| 304 | /* get command line options */
|
---|
| 305 | while ((c = getopt(argc, argv, "adprcIT:t:h:s:fvpb:l:S:B:")) != EOF) {
|
---|
| 306 | switch (c) {
|
---|
| 307 | case 'B':
|
---|
| 308 | bootSector = optarg;
|
---|
| 309 | break;
|
---|
| 310 | case 'a':
|
---|
| 311 | /* no privs, as it could be abused to
|
---|
| 312 | * make other partitions unbootable, or
|
---|
| 313 | * to boot a rogue kernel from this one */
|
---|
| 314 | open2flags |= NO_PRIV;
|
---|
| 315 | activate = 1;
|
---|
| 316 | dirty = 1;
|
---|
| 317 | break;
|
---|
| 318 | case 'd':
|
---|
| 319 | activate = -1;
|
---|
| 320 | dirty = 1;
|
---|
| 321 | break;
|
---|
| 322 | case 'p':
|
---|
| 323 | doprint = 1;
|
---|
| 324 | break;
|
---|
| 325 | case 'r':
|
---|
| 326 | remove = 1;
|
---|
| 327 | dirty = 1;
|
---|
| 328 | break;
|
---|
| 329 | case 'I':
|
---|
| 330 | /* could be abused to nuke all other
|
---|
| 331 | * partitions */
|
---|
| 332 | open2flags |= NO_PRIV;
|
---|
| 333 | initialize = 1;
|
---|
| 334 | dirty = 1;
|
---|
| 335 | break;
|
---|
| 336 | case 'c':
|
---|
| 337 | create = 1;
|
---|
| 338 | dirty = 1;
|
---|
| 339 | break;
|
---|
| 340 |
|
---|
| 341 | case 'T':
|
---|
| 342 | /* could be abused to "manually" create
|
---|
| 343 | * extended partitions */
|
---|
| 344 | open2flags |= NO_PRIV;
|
---|
| 345 | type = strtoul(optarg,0,0);
|
---|
| 346 | break;
|
---|
| 347 |
|
---|
| 348 | case 't':
|
---|
| 349 | argtracks = atoi(optarg);
|
---|
| 350 | break;
|
---|
| 351 | case 'h':
|
---|
| 352 | argheads = atoi(optarg);
|
---|
| 353 | break;
|
---|
| 354 | case 's':
|
---|
| 355 | argsectors = atoi(optarg);
|
---|
| 356 | break;
|
---|
| 357 |
|
---|
| 358 | case 'f':
|
---|
| 359 | /* could be abused by creating overlapping
|
---|
| 360 | * partitions and other such Snafu */
|
---|
| 361 | open2flags |= NO_PRIV;
|
---|
| 362 | force = 1;
|
---|
| 363 | break;
|
---|
| 364 |
|
---|
| 365 | case 'v':
|
---|
| 366 | verbose++;
|
---|
| 367 | break;
|
---|
| 368 | case 'S':
|
---|
| 369 | /* testing only */
|
---|
| 370 | /* could be abused to create partitions
|
---|
| 371 | * extending beyond the actual size of the
|
---|
| 372 | * device */
|
---|
| 373 | open2flags |= NO_PRIV;
|
---|
| 374 | tot_sectors = strtoul(optarg,0,0);
|
---|
| 375 | sizetest = 1;
|
---|
| 376 | break;
|
---|
| 377 | case 'b':
|
---|
| 378 | begin_set = 1;
|
---|
| 379 | begin = atoi(optarg);
|
---|
| 380 | break;
|
---|
| 381 | case 'l':
|
---|
| 382 | size_set = 1;
|
---|
| 383 | length = atoi(optarg);
|
---|
| 384 | break;
|
---|
| 385 |
|
---|
| 386 | default:
|
---|
| 387 | usage();
|
---|
| 388 | }
|
---|
| 389 | }
|
---|
| 390 |
|
---|
| 391 | if (argc - optind != 1 || skip_drive(argv[optind]) == argv[optind])
|
---|
| 392 | usage();
|
---|
| 393 |
|
---|
| 394 | drive = get_drive(argv[optind], NULL);
|
---|
| 395 |
|
---|
| 396 | /* check out a drive whose letter and parameters match */
|
---|
| 397 | sprintf(errmsg, "Drive '%s:' not supported", drive);
|
---|
| 398 | Stream = 0;
|
---|
| 399 | for(dev=devices;dev->drive;dev++) {
|
---|
| 400 | FREE(&(Stream));
|
---|
| 401 | /* drive letter */
|
---|
| 402 | if (strcmp(dev->drive, drive) != 0)
|
---|
| 403 | continue;
|
---|
| 404 | if (dev->partition < 1 || dev->partition > 4) {
|
---|
| 405 | sprintf(errmsg,
|
---|
| 406 | "Drive '%c:' is not a partition",
|
---|
| 407 | drive);
|
---|
| 408 | continue;
|
---|
| 409 | }
|
---|
| 410 | used_dev = *dev;
|
---|
| 411 |
|
---|
| 412 | SET_INT(used_dev.tracks, argtracks);
|
---|
| 413 | SET_INT(used_dev.heads, argheads);
|
---|
| 414 | SET_INT(used_dev.sectors, argsectors);
|
---|
| 415 |
|
---|
| 416 | expand(dev->name, name);
|
---|
| 417 | Stream = SimpleFileOpen(&used_dev, dev, name,
|
---|
| 418 | dirty ? O_RDWR : O_RDONLY,
|
---|
| 419 | errmsg, open2flags, 1, 0);
|
---|
| 420 |
|
---|
| 421 | if (!Stream) {
|
---|
| 422 | #ifdef HAVE_SNPRINTF
|
---|
| 423 | snprintf(errmsg,199,"init: open: %s", strerror(errno));
|
---|
| 424 | #else
|
---|
| 425 | sprintf(errmsg,"init: open: %s", strerror(errno));
|
---|
| 426 | #endif
|
---|
| 427 | continue;
|
---|
| 428 | }
|
---|
| 429 |
|
---|
| 430 |
|
---|
| 431 | /* try to find out the size */
|
---|
| 432 | if(!sizetest)
|
---|
| 433 | tot_sectors = 0;
|
---|
| 434 | if(IS_SCSI(dev)) {
|
---|
| 435 | unsigned char cmd[10];
|
---|
| 436 | unsigned char data[10];
|
---|
| 437 | cmd[0] = SCSI_READ_CAPACITY;
|
---|
| 438 | memset ((void *) &cmd[2], 0, 8);
|
---|
| 439 | memset ((void *) &data[0], 137, 10);
|
---|
| 440 | scsi_cmd(get_fd(Stream), cmd, 10, SCSI_IO_READ,
|
---|
| 441 | data, 10, get_extra_data(Stream));
|
---|
| 442 |
|
---|
| 443 | tot_sectors = 1 +
|
---|
| 444 | (data[0] << 24) +
|
---|
| 445 | (data[1] << 16) +
|
---|
| 446 | (data[2] << 8) +
|
---|
| 447 | (data[3] );
|
---|
| 448 | if(verbose)
|
---|
| 449 | printf("%d sectors in total\n", tot_sectors);
|
---|
| 450 | }
|
---|
| 451 |
|
---|
| 452 | #ifdef OS_linux
|
---|
| 453 | if (tot_sectors == 0) {
|
---|
| 454 | ioctl(get_fd(Stream), BLKGETSIZE, &tot_sectors);
|
---|
| 455 | }
|
---|
| 456 | #endif
|
---|
| 457 |
|
---|
| 458 | /* read the partition table */
|
---|
| 459 | if (READS(Stream, (char *) buf, 0, 512) != 512) {
|
---|
| 460 | #ifdef HAVE_SNPRINTF
|
---|
| 461 | snprintf(errmsg, 199,
|
---|
| 462 | "Error reading from '%s', wrong parameters?",
|
---|
| 463 | name);
|
---|
| 464 | #else
|
---|
| 465 | sprintf(errmsg,
|
---|
| 466 | "Error reading from '%s', wrong parameters?",
|
---|
| 467 | name);
|
---|
| 468 | #endif
|
---|
| 469 | continue;
|
---|
| 470 | }
|
---|
| 471 | if(verbose>=2)
|
---|
| 472 | print_sector("Read sector", buf, 512);
|
---|
| 473 | break;
|
---|
| 474 | }
|
---|
| 475 |
|
---|
| 476 | /* print error msg if needed */
|
---|
| 477 | if ( dev->drive == 0 ){
|
---|
| 478 | FREE(&Stream);
|
---|
| 479 | fprintf(stderr,"%s: %s\n", argv[0],errmsg);
|
---|
| 480 | exit(1);
|
---|
| 481 | }
|
---|
| 482 |
|
---|
| 483 | if((used_dev.sectors || used_dev.heads) &&
|
---|
| 484 | (!used_dev.sectors || !used_dev.heads)) {
|
---|
| 485 | fprintf(stderr,"You should either indicate both the number of sectors and the number of heads,\n");
|
---|
| 486 | fprintf(stderr," or none of them\n");
|
---|
| 487 | exit(1);
|
---|
| 488 | }
|
---|
| 489 |
|
---|
| 490 | if(initialize) {
|
---|
| 491 | if (bootSector) {
|
---|
| 492 | int fd;
|
---|
| 493 | fd = open(bootSector, O_RDONLY);
|
---|
| 494 | if (fd < 0) {
|
---|
| 495 | perror("open boot sector");
|
---|
| 496 | exit(1);
|
---|
| 497 | }
|
---|
| 498 | read(fd, (char *) buf, 512);
|
---|
| 499 | }
|
---|
| 500 | memset((char *)(partTable+1), 0, 4*sizeof(*partTable));
|
---|
| 501 | set_dword(((unsigned char*)buf)+510, 0xaa55);
|
---|
| 502 | }
|
---|
| 503 |
|
---|
| 504 | /* check for boot signature, and place it if needed */
|
---|
| 505 | if((buf[510] != 0x55) || (buf[511] != 0xaa)) {
|
---|
| 506 | fprintf(stderr,"Boot signature not set\n");
|
---|
| 507 | fprintf(stderr,
|
---|
| 508 | "Use the -I flag to initialize the partition table, and set the boot signature\n");
|
---|
| 509 | inconsistency = 1;
|
---|
| 510 | }
|
---|
| 511 |
|
---|
| 512 | if(remove){
|
---|
| 513 | if(!partTable[dev->partition].sys_ind)
|
---|
| 514 | fprintf(stderr,
|
---|
| 515 | "Partition for drive %c: does not exist\n",
|
---|
| 516 | drive);
|
---|
| 517 | if((partTable[dev->partition].sys_ind & 0x3f) == 5) {
|
---|
| 518 | fprintf(stderr,
|
---|
| 519 | "Partition for drive %c: may be an extended partition\n",
|
---|
| 520 | drive);
|
---|
| 521 | fprintf(stderr,
|
---|
| 522 | "Use the -f flag to remove it anyways\n");
|
---|
| 523 | inconsistency = 1;
|
---|
| 524 | }
|
---|
| 525 | memset(&partTable[dev->partition], 0, sizeof(*partTable));
|
---|
| 526 | }
|
---|
| 527 |
|
---|
| 528 | if(create && partTable[dev->partition].sys_ind) {
|
---|
| 529 | fprintf(stderr,
|
---|
| 530 | "Partition for drive %c: already exists\n", drive);
|
---|
| 531 | fprintf(stderr,
|
---|
| 532 | "Use the -r flag to remove it before attempting to recreate it\n");
|
---|
| 533 | }
|
---|
| 534 |
|
---|
| 535 |
|
---|
| 536 | /* find out number of heads and sectors, and whether there is
|
---|
| 537 | * any activated partition */
|
---|
| 538 | has_activated = 0;
|
---|
| 539 | for(i=1; i<5; i++){
|
---|
| 540 | if(!partTable[i].sys_ind)
|
---|
| 541 | continue;
|
---|
| 542 |
|
---|
| 543 | if(partTable[i].boot_ind)
|
---|
| 544 | has_activated++;
|
---|
| 545 |
|
---|
| 546 | /* set geometry from entry */
|
---|
| 547 | if (!used_dev.heads)
|
---|
| 548 | used_dev.heads = head(partTable[i].end)+1;
|
---|
| 549 | if(!used_dev.sectors)
|
---|
| 550 | used_dev.sectors = sector(partTable[i].end);
|
---|
| 551 | if(i<dev->partition && !begin_set)
|
---|
| 552 | begin = END(partTable[i]);
|
---|
| 553 | if(i>dev->partition && !end_set && !size_set) {
|
---|
| 554 | end = BEGIN(partTable[i]);
|
---|
| 555 | end_set = 1;
|
---|
| 556 | }
|
---|
| 557 | }
|
---|
| 558 |
|
---|
| 559 | #ifdef OS_linux
|
---|
| 560 | if(!used_dev.sectors && !used_dev.heads) {
|
---|
| 561 | if(!IS_SCSI(dev)) {
|
---|
| 562 | struct hd_geometry geom;
|
---|
| 563 | if(ioctl(get_fd(Stream), HDIO_GETGEO, &geom) == 0) {
|
---|
| 564 | used_dev.heads = geom.heads;
|
---|
| 565 | used_dev.sectors = geom.sectors;
|
---|
| 566 | }
|
---|
| 567 | }
|
---|
| 568 | }
|
---|
| 569 | #endif
|
---|
| 570 |
|
---|
| 571 | if(!used_dev.sectors && !used_dev.heads) {
|
---|
| 572 | if(tot_sectors)
|
---|
| 573 | setsize0(tot_sectors,&dummy2,&used_dev.heads,
|
---|
| 574 | &used_dev.sectors);
|
---|
| 575 | else {
|
---|
| 576 | used_dev.heads = 64;
|
---|
| 577 | used_dev.sectors = 32;
|
---|
| 578 | }
|
---|
| 579 | }
|
---|
| 580 |
|
---|
| 581 | if(verbose)
|
---|
| 582 | fprintf(stderr,"sectors: %d heads: %d %d\n",
|
---|
| 583 | used_dev.sectors, used_dev.heads, tot_sectors);
|
---|
| 584 |
|
---|
| 585 | sec_per_cyl = used_dev.sectors * used_dev.heads;
|
---|
| 586 | if(create) {
|
---|
| 587 | if(!end_set && tot_sectors) {
|
---|
| 588 | end = tot_sectors - tot_sectors % sec_per_cyl;
|
---|
| 589 | end_set = 1;
|
---|
| 590 | }
|
---|
| 591 |
|
---|
| 592 | /* if the partition starts right at the beginning of
|
---|
| 593 | * the disk, keep one track unused to allow place for
|
---|
| 594 | * the master boot record */
|
---|
| 595 | if(!begin && !begin_set)
|
---|
| 596 | begin = used_dev.sectors;
|
---|
| 597 | if(!size_set && used_dev.tracks) {
|
---|
| 598 | size_set = 2;
|
---|
| 599 | length = sec_per_cyl * used_dev.tracks;
|
---|
| 600 |
|
---|
| 601 | /* round the size in order to take
|
---|
| 602 | * into account any "hidden" sectors */
|
---|
| 603 |
|
---|
| 604 | /* do we anchor this at the beginning ?*/
|
---|
| 605 | if(begin_set || dev->partition <= 2 || !end_set)
|
---|
| 606 | length -= begin % sec_per_cyl;
|
---|
| 607 | else if(end - length < begin)
|
---|
| 608 | /* truncate any overlap */
|
---|
| 609 | length = end - begin;
|
---|
| 610 | }
|
---|
| 611 | if(size_set) {
|
---|
| 612 | if(!begin_set && dev->partition >2 && end_set)
|
---|
| 613 | begin = end - length;
|
---|
| 614 | else
|
---|
| 615 | end = begin + length;
|
---|
| 616 | } else if(!end_set) {
|
---|
| 617 | fprintf(stderr,"Unknown size\n");
|
---|
| 618 | exit(1);
|
---|
| 619 | }
|
---|
| 620 |
|
---|
| 621 | setBeginEnd(&partTable[dev->partition], begin, end,
|
---|
| 622 | used_dev.heads, used_dev.sectors,
|
---|
| 623 | !has_activated, type);
|
---|
| 624 | }
|
---|
| 625 |
|
---|
| 626 | if(activate) {
|
---|
| 627 | if(!partTable[dev->partition].sys_ind) {
|
---|
| 628 | fprintf(stderr,
|
---|
| 629 | "Partition for drive %c: does not exist\n",
|
---|
| 630 | drive);
|
---|
| 631 | } else {
|
---|
| 632 | switch(activate) {
|
---|
| 633 | case 1:
|
---|
| 634 | partTable[dev->partition].boot_ind=0x80;
|
---|
| 635 | break;
|
---|
| 636 | case -1:
|
---|
| 637 | partTable[dev->partition].boot_ind=0x00;
|
---|
| 638 | break;
|
---|
| 639 | }
|
---|
| 640 | }
|
---|
| 641 | }
|
---|
| 642 |
|
---|
| 643 |
|
---|
| 644 | inconsistency |= consistencyCheck(partTable, doprint, verbose,
|
---|
| 645 | &has_activated, &last_end, &j,
|
---|
| 646 | &used_dev, dev->partition);
|
---|
| 647 |
|
---|
| 648 | if(doprint && !inconsistency && partTable[dev->partition].sys_ind) {
|
---|
| 649 | printf("The following command will recreate the partition for drive %c:\n",
|
---|
| 650 | drive);
|
---|
| 651 | used_dev.tracks =
|
---|
| 652 | (_DWORD(partTable[dev->partition].nr_sects) +
|
---|
| 653 | (BEGIN(partTable[dev->partition]) % sec_per_cyl)) /
|
---|
| 654 | sec_per_cyl;
|
---|
| 655 | printf("mpartition -c -t %d -h %d -s %d -b %u %c:\n",
|
---|
| 656 | used_dev.tracks, used_dev.heads, used_dev.sectors,
|
---|
| 657 | BEGIN(partTable[dev->partition]), drive);
|
---|
| 658 | }
|
---|
| 659 |
|
---|
| 660 | if(tot_sectors && last_end >tot_sectors) {
|
---|
| 661 | fprintf(stderr,
|
---|
| 662 | "Partition %d exceeds beyond end of disk\n",
|
---|
| 663 | j);
|
---|
| 664 | exit(1);
|
---|
| 665 | }
|
---|
| 666 |
|
---|
| 667 |
|
---|
| 668 | switch(has_activated) {
|
---|
| 669 | case 0:
|
---|
| 670 | fprintf(stderr,
|
---|
| 671 | "Warning: no active (bootable) partition present\n");
|
---|
| 672 | break;
|
---|
| 673 | case 1:
|
---|
| 674 | break;
|
---|
| 675 | default:
|
---|
| 676 | fprintf(stderr,
|
---|
| 677 | "Warning: %d active (bootable) partitions present\n",
|
---|
| 678 | has_activated);
|
---|
| 679 | fprintf(stderr,
|
---|
| 680 | "Usually, a disk should have exactly one active partition\n");
|
---|
| 681 | break;
|
---|
| 682 | }
|
---|
| 683 |
|
---|
| 684 | if(inconsistency && !force) {
|
---|
| 685 | fprintf(stderr,
|
---|
| 686 | "inconsistency detected!\n" );
|
---|
| 687 | if(dirty)
|
---|
| 688 | fprintf(stderr,
|
---|
| 689 | "Retry with the -f switch to go ahead anyways\n");
|
---|
| 690 | exit(1);
|
---|
| 691 | }
|
---|
| 692 |
|
---|
| 693 | if(dirty) {
|
---|
| 694 | /* write data back to the disk */
|
---|
| 695 | if(verbose>=2)
|
---|
| 696 | print_sector("Writing sector", buf, 512);
|
---|
| 697 | if (WRITES(Stream, (char *) buf, 0, 512) != 512) {
|
---|
| 698 | fprintf(stderr,"Error writing partition table");
|
---|
| 699 | exit(1);
|
---|
| 700 | }
|
---|
| 701 | if(verbose>=3)
|
---|
| 702 | print_sector("Sector written", buf, 512);
|
---|
| 703 | FREE(&Stream);
|
---|
| 704 | }
|
---|
| 705 | exit(0);
|
---|
| 706 | }
|
---|