blob: efc5d408792d5c1dd37ca7529cb9ff3be2d47142 [file] [log] [blame]
Alistair Delvabeaee832021-02-24 11:27:23 -08001/* Copyright 1997-2003,2005-2007,2009 Alain Knaff.
2 * This file is part of mtools.
3 *
4 * Mtools is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * Mtools is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
16 *
17 * mformat.c
18 */
19#define DONT_NEED_WAIT
20
21#include "sysincludes.h"
22#include "msdos.h"
23#include "mtools.h"
24#include "mainloop.h"
25#include "fsP.h"
26#include "file.h"
27#include "plain_io.h"
28#include "nameclash.h"
29#include "buffer.h"
Alistair Delvabeaee832021-02-24 11:27:23 -080030#include "partition.h"
Yi Kong39bbd962022-01-09 19:41:38 +080031#include "open_image.h"
32#include "lba.h"
Alistair Delvabeaee832021-02-24 11:27:23 -080033
34#ifdef OS_linux
35#include "linux/hdreg.h"
Alistair Delvabeaee832021-02-24 11:27:23 -080036#include "linux/fs.h"
Alistair Delvabeaee832021-02-24 11:27:23 -080037#endif
38
Yi Kong39bbd962022-01-09 19:41:38 +080039static void set_offset(hsc *h, unsigned long offset,
40 uint16_t heads, uint16_t sectors)
Alistair Delvabeaee832021-02-24 11:27:23 -080041{
Yi Kong39bbd962022-01-09 19:41:38 +080042 uint16_t head, sector;
43 unsigned int cyl;
Alistair Delvabeaee832021-02-24 11:27:23 -080044
45 if(! heads || !sectors)
46 head = sector = cyl = 0; /* linear mode */
47 else {
48 sector = offset % sectors;
49 offset = offset / sectors;
50
51 head = offset % heads;
Yi Kong39bbd962022-01-09 19:41:38 +080052 offset = offset / heads;
53 if(offset > 1023)
54 cyl = 1023;
55 else
56 cyl = (uint16_t) offset;
Alistair Delvabeaee832021-02-24 11:27:23 -080057 }
Yi Kong39bbd962022-01-09 19:41:38 +080058 if(head > UINT8_MAX) {
59 /* sector or head out of range => linear mode */
60 head = sector = cyl = 0;
61 }
62 h->head = (uint8_t) head;
Alistair Delvabeaee832021-02-24 11:27:23 -080063 h->sector = ((sector+1) & 0x3f) | ((cyl & 0x300)>>2);
64 h->cyl = cyl & 0xff;
65}
66
67void setBeginEnd(struct partition *partTable,
Yi Kong39bbd962022-01-09 19:41:38 +080068 uint32_t begin, uint32_t end,
69 uint16_t iheads, uint16_t isectors,
70 int activate, uint8_t type, unsigned int fat_bits)
Alistair Delvabeaee832021-02-24 11:27:23 -080071{
Yi Kong39bbd962022-01-09 19:41:38 +080072 uint8_t heads, sectors;
73
74 if(iheads > UINT8_MAX) {
75 fprintf(stderr,
76 "Too many heads for partition: %d\n",
77 iheads);
78 exit(1);
79 }
80 heads=(uint8_t) iheads;
81 if(isectors > UINT8_MAX) {
82 fprintf(stderr,
83 "Too many sectors for partition: %d\n",
84 isectors);
85 exit(1);
86 }
87 sectors=(uint8_t) isectors;
88
Alistair Delvabeaee832021-02-24 11:27:23 -080089 set_offset(&partTable->start, begin, heads, sectors);
90 set_offset(&partTable->end, end-1, heads, sectors);
91 set_dword(partTable->start_sect, begin);
92 set_dword(partTable->nr_sects, end-begin);
93 if(activate)
94 partTable->boot_ind = 0x80;
95 else
96 partTable->boot_ind = 0;
97 if(!type) {
98 if (fat_bits == 0) {
99 /**
100 * Fat bits unknown / not specified. We look
101 * at size to get a rough estimate what FAT
102 * bits are used. Note: this is only an
103 * estimate, the precise calculation would
104 * involve the number of clusters, which is
105 * not necessarily known here.
106 */
107 /* cc977219 would have a cutoff number of 32680,
108 * corresponding to a FAT12 partition with 4K
109 * clusters, however other information hints that
110 * only partitions with less than 4096 sectors are
111 * considered */
112 if(end-begin < 4096)
113 fat_bits = 12;
114 else
115 fat_bits = 16;
116 }
117
118 /* Description of various partition types in
119 * https://en.wikipedia.org/wiki/Partition_type#List_of_partition_IDs
120 * and
121 * https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc977219(v=technet.10)
122 */
123 if (fat_bits == 32)
124 /* FAT 32 partition. For now, we disregard the
125 * possibility of FAT 32 CHS partitions */
126 type = 0x0C; /* Win95 FAT32, LBA */
127 else if (end < 65536) {
128 /* FAT 12 or FAT 16 partitions which fit entirely below
129 the 32M mark */
130 /* The 32M restriction doesn't apply to logical
131 partitions within an extended partition, but for the
132 moment mpartition only makes primary partitions */
133 if(fat_bits == 12)
134 /* FAT 12 partition */
135 type = 0x01; /* DOS FAT12, CHS */
136 else if (fat_bits == 16)
137 /* FAT 16 partition */
138 type = 0x04; /* DOS FAT16, CHS */
Yi Kong39bbd962022-01-09 19:41:38 +0800139 } else if (end < sectors * heads * 1024u)
Alistair Delvabeaee832021-02-24 11:27:23 -0800140 /* FAT 12 or FAT16 partition above the 32M
141 * mark but below the 1024 cylinder mark.
142 * Indeed, there can be no CHS partition
143 * beyond 1024 cylinders */
144 type = 0x06; /* DOS BIG FAT16 or FAT12, CHS */
145 else
146 type = 0x0E; /* Win95 BIG FAT16, LBA */
147 }
148 partTable->sys_ind = type;
149}
150
Alistair Delvabeaee832021-02-24 11:27:23 -0800151
152/* setsize function. Determines scsicam mapping if this cannot be inferred from
153 * any existing partitions. Shamelessly snarfed from the Linux kernel ;-) */
154
155/*
156 * Function : static int setsize(unsigned long capacity,unsigned int *cyls,
157 * unsigned int *hds, unsigned int *secs);
158 *
159 * Purpose : to determine a near-optimal int 0x13 mapping for a
160 * SCSI disk in terms of lost space of size capacity, storing
161 * the results in *cyls, *hds, and *secs.
162 *
163 * Returns : -1 on failure, 0 on success.
164 *
165 * Extracted from
166 *
167 * WORKING X3T9.2
168 * DRAFT 792D
169 *
170 *
171 * Revision 6
172 * 10-MAR-94
173 * Information technology -
174 * SCSI-2 Common access method
175 * transport and SCSI interface module
176 *
177 * ANNEX A :
178 *
179 * setsize() converts a read capacity value to int 13h
180 * head-cylinder-sector requirements. It minimizes the value for
181 * number of heads and maximizes the number of cylinders. This
182 * will support rather large disks before the number of heads
183 * will not fit in 4 bits (or 6 bits). This algorithm also
184 * minimizes the number of sectors that will be unused at the end
185 * of the disk while allowing for very large disks to be
186 * accommodated. This algorithm does not use physical geometry.
187 */
188
189static int setsize(unsigned long capacity,unsigned int *cyls,
190 uint16_t *hds, uint16_t *secs) {
Yi Kong39bbd962022-01-09 19:41:38 +0800191 int rv = 0;
Alistair Delvabeaee832021-02-24 11:27:23 -0800192 unsigned long heads, sectors, cylinders, temp;
193
194 cylinders = 1024L; /* Set number of cylinders to max */
195 sectors = 62L; /* Maximize sectors per track */
196
197 temp = cylinders * sectors; /* Compute divisor for heads */
198 heads = capacity / temp; /* Compute value for number of heads */
199 if (capacity % temp) { /* If no remainder, done! */
200 heads++; /* Else, increment number of heads */
201 temp = cylinders * heads; /* Compute divisor for sectors */
202 sectors = capacity / temp; /* Compute value for sectors per
203 track */
204 if (capacity % temp) { /* If no remainder, done! */
205 sectors++; /* Else, increment number of sectors */
206 temp = heads * sectors; /* Compute divisor for cylinders */
207 cylinders = capacity / temp;/* Compute number of cylinders */
208 }
209 }
Yi Kong39bbd962022-01-09 19:41:38 +0800210 if (cylinders == 0) rv=-1;/* Give error if 0 cylinders */
Alistair Delvabeaee832021-02-24 11:27:23 -0800211
212 *cyls = (unsigned int) cylinders; /* Stuff return values */
Yi Kong39bbd962022-01-09 19:41:38 +0800213 *secs = (uint16_t) sectors;
214 *hds = (uint16_t) heads;
Alistair Delvabeaee832021-02-24 11:27:23 -0800215 return(rv);
216}
217
Yi Kong39bbd962022-01-09 19:41:38 +0800218static void setsize0(uint32_t capacity,unsigned int *cyls,
Alistair Delvabeaee832021-02-24 11:27:23 -0800219 uint16_t *hds, uint16_t *secs)
220{
221 int r;
222
223 /* 1. First try "Megabyte" sizes */
224 if(capacity < 1024 * 2048 && !(capacity % 1024)) {
225 *cyls = capacity >> 11;
226 *hds = 64;
227 *secs = 32;
228 return;
229 }
230
231 /* then try scsicam's size */
232 r = setsize(capacity,cyls,hds,secs);
233 if(r || *hds > 255 || *secs > 63) {
234 /* scsicam failed. Do megabytes anyways */
235 *cyls = capacity >> 11;
236 *hds = 64;
237 *secs = 32;
238 return;
239 }
240}
241
242
243static void usage(int ret) NORETURN;
244static void usage(int ret)
245{
246 fprintf(stderr,
247 "Mtools version %s, dated %s\n", mversion, mdate);
248 fprintf(stderr,
249 "Usage: %s [-pradcv] [-I] [-B bootsect-template] [-s sectors] "
250 "[-t cylinders] "
251 "[-h heads] [-T type] [-b begin] [-l length] "
252 "drive\n", progname);
253 exit(ret);
254}
255
256void mpartition(int argc, char **argv, int dummy UNUSEDP) NORETURN;
257void mpartition(int argc, char **argv, int dummy UNUSEDP)
258{
259 Stream_t *Stream;
260 unsigned int dummy2;
261
Yi Kong39bbd962022-01-09 19:41:38 +0800262 unsigned int i;
Alistair Delvabeaee832021-02-24 11:27:23 -0800263
Yi Kong39bbd962022-01-09 19:41:38 +0800264 uint16_t sec_per_cyl;
Alistair Delvabeaee832021-02-24 11:27:23 -0800265 int doprint = 0;
266 int verbose = 0;
267 int create = 0;
268 int force = 0;
269 unsigned int length = 0;
270 int do_remove = 0;
271 int initialize = 0;
Yi Kong39bbd962022-01-09 19:41:38 +0800272
273 uint32_t tot_sectors=0;
274 /* Needs to be long due to BLKGETSIZE ioctl */
275
276 uint8_t type = 0;
Alistair Delvabeaee832021-02-24 11:27:23 -0800277 int begin_set = 0;
278 int size_set = 0;
279 int end_set = 0;
Alistair Delvabeaee832021-02-24 11:27:23 -0800280 int activate = 0;
281 int has_activated = 0;
282 int inconsistency=0;
283 unsigned int begin=0;
284 unsigned int end=0;
Alistair Delvabeaee832021-02-24 11:27:23 -0800285 int dirty = 0;
Yi Kong39bbd962022-01-09 19:41:38 +0800286 int open2flags = 0;
Alistair Delvabeaee832021-02-24 11:27:23 -0800287
288 int c;
289 struct device used_dev;
Yi Kong39bbd962022-01-09 19:41:38 +0800290 unsigned int argtracks;
291 uint16_t argheads, argsectors;
Alistair Delvabeaee832021-02-24 11:27:23 -0800292
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[2100];
298 char *bootSector=0;
Yi Kong39bbd962022-01-09 19:41:38 +0800299 struct partition *tpartition;
Alistair Delvabeaee832021-02-24 11:27:23 -0800300
301 argtracks = 0;
302 argheads = 0;
303 argsectors = 0;
304
305 /* get command line options */
306 if(helpFlag(argc, argv))
307 usage(0);
308 while ((c = getopt(argc, argv, "i:adprcIT:t:h:s:fvpb:l:S:B:")) != EOF) {
309 char *endptr=NULL;
310 errno=0;
311 switch (c) {
312 case 'i':
313 set_cmd_line_image(optarg);
314 break;
315 case 'B':
316 bootSector = optarg;
317 break;
318 case 'a':
319 /* no privs, as it could be abused to
320 * make other partitions unbootable, or
321 * to boot a rogue kernel from this one */
322 open2flags |= NO_PRIV;
323 activate = 1;
324 dirty = 1;
325 break;
326 case 'd':
327 activate = -1;
328 dirty = 1;
329 break;
330 case 'p':
331 doprint = 1;
332 break;
333 case 'r':
334 do_remove = 1;
335 dirty = 1;
336 break;
337 case 'I':
338 /* could be abused to nuke all other
339 * partitions */
340 open2flags |= NO_PRIV;
341 initialize = 1;
342 dirty = 1;
343 break;
344 case 'c':
345 create = 1;
346 dirty = 1;
347 break;
348
349 case 'T':
350 /* could be abused to "manually" create
351 * extended partitions */
352 open2flags |= NO_PRIV;
Yi Kong39bbd962022-01-09 19:41:38 +0800353 type = strtou8(optarg, &endptr, 0);
Alistair Delvabeaee832021-02-24 11:27:23 -0800354 break;
355
356 case 't':
Yi Kong39bbd962022-01-09 19:41:38 +0800357 argtracks = atoui(optarg);
Alistair Delvabeaee832021-02-24 11:27:23 -0800358 break;
359 case 'h':
Yi Kong39bbd962022-01-09 19:41:38 +0800360 argheads = atou16(optarg);
Alistair Delvabeaee832021-02-24 11:27:23 -0800361 break;
362 case 's':
Yi Kong39bbd962022-01-09 19:41:38 +0800363 argsectors = atou16(optarg);
Alistair Delvabeaee832021-02-24 11:27:23 -0800364 break;
365
366 case 'f':
367 /* could be abused by creating overlapping
368 * partitions and other such Snafu */
369 open2flags |= NO_PRIV;
370 force = 1;
371 break;
372
373 case 'v':
374 verbose++;
375 break;
Alistair Delvabeaee832021-02-24 11:27:23 -0800376 case 'b':
377 begin_set = 1;
378 begin = strtoui(optarg, &endptr, 0);
379 break;
380 case 'l':
381 size_set = 1;
Yi Kong39bbd962022-01-09 19:41:38 +0800382 length = parseSize(optarg);
Alistair Delvabeaee832021-02-24 11:27:23 -0800383 break;
384
385 default:
386 usage(1);
387 }
Yi Kong39bbd962022-01-09 19:41:38 +0800388 check_number_parse_errno((char)c, optarg, endptr);
Alistair Delvabeaee832021-02-24 11:27:23 -0800389 }
390
391 if (argc - optind != 1 ||
392 !argv[optind][0] || argv[optind][1] != ':')
393 usage(1);
394
395 drive = ch_toupper(argv[optind][0]);
396
397 /* check out a drive whose letter and parameters match */
398 sprintf(errmsg, "Drive '%c:' not supported", drive);
399 Stream = 0;
400 for(dev=devices;dev->drive;dev++) {
401 int mode ;
402
403 FREE(&(Stream));
404 /* drive letter */
405 if (dev->drive != drive)
406 continue;
407 if (dev->partition < 1 || dev->partition > 4) {
408 sprintf(errmsg,
409 "Drive '%c:' is not a partition",
410 drive);
411 continue;
412 }
413 used_dev = *dev;
414
415 SET_INT(used_dev.tracks, argtracks);
416 SET_INT(used_dev.heads, argheads);
417 SET_INT(used_dev.sectors, argsectors);
418
419 expand(dev->name, name);
420
421 mode = dirty ? O_RDWR : O_RDONLY;
422 if(initialize)
423 mode |= O_CREAT;
424
425#ifdef USING_NEW_VOLD
426 strcpy(name, getVoldName(dev, name));
427#endif
Yi Kong39bbd962022-01-09 19:41:38 +0800428 Stream = OpenImage(&used_dev, dev, name, mode, errmsg,
429 open2flags | SKIP_PARTITION | ALWAYS_GET_GEOMETRY,
430 mode, NULL, NULL, NULL);
Alistair Delvabeaee832021-02-24 11:27:23 -0800431
432 if (!Stream) {
433#ifdef HAVE_SNPRINTF
434 snprintf(errmsg,sizeof(errmsg)-1,
435 "init: open: %s", strerror(errno));
436#else
437 sprintf(errmsg,"init: open: %s", strerror(errno));
438#endif
439 continue;
440 }
441
Yi Kong39bbd962022-01-09 19:41:38 +0800442 tot_sectors = used_dev.tot_sectors;
Alistair Delvabeaee832021-02-24 11:27:23 -0800443
444 /* read the partition table */
Yi Kong39bbd962022-01-09 19:41:38 +0800445 if (PREADS(Stream, (char *) buf, 0, 512) != 512 && !initialize){
Alistair Delvabeaee832021-02-24 11:27:23 -0800446#ifdef HAVE_SNPRINTF
447 snprintf(errmsg, sizeof(errmsg)-1,
448 "Error reading from '%s', wrong parameters?",
449 name);
450#else
451 sprintf(errmsg,
452 "Error reading from '%s', wrong parameters?",
453 name);
454#endif
455 continue;
456 }
457 if(verbose>=2)
458 print_sector("Read sector", buf, 512);
459 break;
460 }
461
462 /* print error msg if needed */
463 if ( dev->drive == 0 ){
464 FREE(&Stream);
465 fprintf(stderr,"%s: %s\n", argv[0],errmsg);
466 exit(1);
467 }
468
469 if((used_dev.sectors || used_dev.heads) &&
470 (!used_dev.sectors || !used_dev.heads)) {
471 fprintf(stderr,"You should either indicate both the number of sectors and the number of heads,\n");
472 fprintf(stderr," or none of them\n");
473 exit(1);
474 }
475
476 if(initialize) {
477 if (bootSector) {
478 int fd;
479 fd = open(bootSector, O_RDONLY | O_BINARY | O_LARGEFILE);
480 if (fd < 0) {
481 perror("open MBR");
482 exit(1);
483 }
484 if(read(fd, (char *) buf, 512) < 512) {
485 perror("read MBR");
486 exit(1);
487 }
488 }
489 memset((char *)(partTable+1), 0, 4*sizeof(*partTable));
490 set_word(((unsigned char*)buf)+510, 0xaa55);
491 }
492
493 /* check for boot signature, and place it if needed */
494 if((buf[510] != 0x55) || (buf[511] != 0xaa)) {
495 fprintf(stderr,"Boot signature not set\n");
496 fprintf(stderr,
497 "Use the -I flag to initialize the partition table, and set the boot signature\n");
498 inconsistency = 1;
499 }
500
Yi Kong39bbd962022-01-09 19:41:38 +0800501 tpartition=&partTable[dev->partition];
Alistair Delvabeaee832021-02-24 11:27:23 -0800502 if(do_remove){
Yi Kong39bbd962022-01-09 19:41:38 +0800503 if(!tpartition->sys_ind)
Alistair Delvabeaee832021-02-24 11:27:23 -0800504 fprintf(stderr,
505 "Partition for drive %c: does not exist\n",
506 drive);
Yi Kong39bbd962022-01-09 19:41:38 +0800507 if((tpartition->sys_ind & 0x3f) == 5) {
Alistair Delvabeaee832021-02-24 11:27:23 -0800508 fprintf(stderr,
509 "Partition for drive %c: may be an extended partition\n",
510 drive);
511 fprintf(stderr,
512 "Use the -f flag to remove it anyways\n");
513 inconsistency = 1;
514 }
Yi Kong39bbd962022-01-09 19:41:38 +0800515 memset(tpartition, 0, sizeof(*tpartition));
Alistair Delvabeaee832021-02-24 11:27:23 -0800516 }
517
Yi Kong39bbd962022-01-09 19:41:38 +0800518 if(create && tpartition->sys_ind) {
Alistair Delvabeaee832021-02-24 11:27:23 -0800519 fprintf(stderr,
520 "Partition for drive %c: already exists\n", drive);
521 fprintf(stderr,
522 "Use the -r flag to remove it before attempting to recreate it\n");
523 }
524
Yi Kong39bbd962022-01-09 19:41:38 +0800525 /* if number of heads and sectors not known yet, set "reasonable"
526 * defaults */
527 compute_lba_geom_from_tot_sectors(&used_dev);
Alistair Delvabeaee832021-02-24 11:27:23 -0800528
Yi Kong39bbd962022-01-09 19:41:38 +0800529 /* find out whether there is any activated partition. Moreover
530 * if no offset of a partition to be created have been
531 * specificed, find out whether it may be placed between the
532 * preceding and following partition already existing */
Alistair Delvabeaee832021-02-24 11:27:23 -0800533 has_activated = 0;
534 for(i=1; i<5; i++){
Yi Kong39bbd962022-01-09 19:41:38 +0800535 struct partition *partition=&partTable[i];
536 if(!partition->sys_ind)
Alistair Delvabeaee832021-02-24 11:27:23 -0800537 continue;
538
Yi Kong39bbd962022-01-09 19:41:38 +0800539 if(partition->boot_ind)
Alistair Delvabeaee832021-02-24 11:27:23 -0800540 has_activated++;
541
Alistair Delvabeaee832021-02-24 11:27:23 -0800542 if(i<dev->partition && !begin_set)
Yi Kong39bbd962022-01-09 19:41:38 +0800543 begin = END(partition);
Alistair Delvabeaee832021-02-24 11:27:23 -0800544 if(i>dev->partition && !end_set && !size_set) {
Yi Kong39bbd962022-01-09 19:41:38 +0800545 end = BEGIN(partition);
Alistair Delvabeaee832021-02-24 11:27:23 -0800546 end_set = 1;
547 }
548 }
549
Alistair Delvabeaee832021-02-24 11:27:23 -0800550 if(!used_dev.sectors && !used_dev.heads) {
Yi Kong39bbd962022-01-09 19:41:38 +0800551 if(tot_sectors) {
552 setsize0((uint32_t)tot_sectors,&dummy2,&used_dev.heads,
Alistair Delvabeaee832021-02-24 11:27:23 -0800553 &used_dev.sectors);
Yi Kong39bbd962022-01-09 19:41:38 +0800554 } else {
Alistair Delvabeaee832021-02-24 11:27:23 -0800555 used_dev.heads = 64;
556 used_dev.sectors = 32;
557 }
558 }
559
560 if(verbose)
Yi Kong39bbd962022-01-09 19:41:38 +0800561 fprintf(stderr,"sectors: %d heads: %d %u\n",
Alistair Delvabeaee832021-02-24 11:27:23 -0800562 used_dev.sectors, used_dev.heads, tot_sectors);
563
564 sec_per_cyl = used_dev.sectors * used_dev.heads;
565 if(create) {
Yi Kong39bbd962022-01-09 19:41:38 +0800566 unsigned int overlap;
567 if(!end_set && !size_set && tot_sectors) {
Alistair Delvabeaee832021-02-24 11:27:23 -0800568 end = tot_sectors - tot_sectors % sec_per_cyl;
569 end_set = 1;
570 }
571
572 /* if the partition starts right at the beginning of
573 * the disk, keep one track unused to allow place for
574 * the master boot record */
575 if(!begin && !begin_set)
Yi Kong39bbd962022-01-09 19:41:38 +0800576 begin = used_dev.sectors ? used_dev.sectors : 2048;
Alistair Delvabeaee832021-02-24 11:27:23 -0800577
Yi Kong39bbd962022-01-09 19:41:38 +0800578 /* Do not try to align partitions (other than first) on track
579 * boundaries here: apparently this was a thing of the past */
Alistair Delvabeaee832021-02-24 11:27:23 -0800580
Alistair Delvabeaee832021-02-24 11:27:23 -0800581 if(size_set) {
Yi Kong39bbd962022-01-09 19:41:38 +0800582 end = begin + length;
Alistair Delvabeaee832021-02-24 11:27:23 -0800583 } else if(!end_set) {
584 fprintf(stderr,"Unknown size\n");
585 exit(1);
586 }
587
Yi Kong39bbd962022-01-09 19:41:38 +0800588 /* Make sure partition boundaries are correctly ordered
589 * (end > begin) */
590 if(begin >= end) {
591 fprintf(stderr, "Begin larger than end\n");
592 exit(1);
593 }
594
595 /* Check whether new partition doesn't overlap with
596 * any of those already in place */
597 if((overlap=findOverlap(partTable, 4, begin, end))) {
598 fprintf(stderr,
599 "Partition would overlap with partition %d\n",
600 overlap);
601 exit(1);
602 }
603
604 setBeginEnd(tpartition, begin, end,
Alistair Delvabeaee832021-02-24 11:27:23 -0800605 used_dev.heads, used_dev.sectors,
606 !has_activated, type,
Yi Kong39bbd962022-01-09 19:41:38 +0800607 abs(dev->fat_bits));
Alistair Delvabeaee832021-02-24 11:27:23 -0800608 }
609
610 if(activate) {
Yi Kong39bbd962022-01-09 19:41:38 +0800611 if(!tpartition->sys_ind) {
Alistair Delvabeaee832021-02-24 11:27:23 -0800612 fprintf(stderr,
613 "Partition for drive %c: does not exist\n",
614 drive);
615 } else {
616 switch(activate) {
617 case 1:
Yi Kong39bbd962022-01-09 19:41:38 +0800618 tpartition->boot_ind=0x80;
Alistair Delvabeaee832021-02-24 11:27:23 -0800619 break;
620 case -1:
Yi Kong39bbd962022-01-09 19:41:38 +0800621 tpartition->boot_ind=0x00;
Alistair Delvabeaee832021-02-24 11:27:23 -0800622 break;
623 }
624 }
625 }
626
Alistair Delvabeaee832021-02-24 11:27:23 -0800627 inconsistency |= consistencyCheck(partTable, doprint, verbose,
Yi Kong39bbd962022-01-09 19:41:38 +0800628 &has_activated, tot_sectors,
Alistair Delvabeaee832021-02-24 11:27:23 -0800629 &used_dev, dev->partition);
630
Alistair Delvabeaee832021-02-24 11:27:23 -0800631 switch(has_activated) {
632 case 0:
633 fprintf(stderr,
634 "Warning: no active (bootable) partition present\n");
635 break;
636 case 1:
637 break;
638 default:
639 fprintf(stderr,
640 "Warning: %d active (bootable) partitions present\n",
641 has_activated);
642 fprintf(stderr,
643 "Usually, a disk should have exactly one active partition\n");
644 break;
645 }
646
647 if(inconsistency && !force) {
648 fprintf(stderr,
649 "inconsistency detected!\n" );
Yi Kong39bbd962022-01-09 19:41:38 +0800650 if(dirty) {
Alistair Delvabeaee832021-02-24 11:27:23 -0800651 fprintf(stderr,
652 "Retry with the -f switch to go ahead anyways\n");
Yi Kong39bbd962022-01-09 19:41:38 +0800653 exit(1);
654 }
655 }
656
657 if(doprint && tpartition->sys_ind) {
658 printf("The following command will recreate the partition for drive %c:\n",
659 drive);
660 used_dev.tracks =
661 (_DWORD(tpartition->nr_sects) +
662 (BEGIN(tpartition) % sec_per_cyl)) /
663 sec_per_cyl;
664 printf("mpartition -c -b %d -l %d -t %d -h %d -s %d -b %u %c:\n",
665 BEGIN(tpartition), PART_SIZE(tpartition),
666 used_dev.tracks, used_dev.heads, used_dev.sectors,
667 BEGIN(tpartition), drive);
Alistair Delvabeaee832021-02-24 11:27:23 -0800668 }
669
670 if(dirty) {
671 /* write data back to the disk */
672 if(verbose>=2)
673 print_sector("Writing sector", buf, 512);
Yi Kong39bbd962022-01-09 19:41:38 +0800674 if (PWRITES(Stream, (char *) buf, 0, 512) != 512) {
Alistair Delvabeaee832021-02-24 11:27:23 -0800675 fprintf(stderr,"Error writing partition table");
676 exit(1);
677 }
678 if(verbose>=3)
679 print_sector("Sector written", buf, 512);
680 }
681 FREE(&Stream);
682 exit(0);
683}