C:Partition: make WIPE option more deadly
[AROS.git] / workbench / c / Partition / main.c
blobaea40670fa792c5642c0bf7e3f0d7eb4cbee3eb6
1 /*
2 Copyright © 2003-2013, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /******************************************************************************
8 NAME
10 Partition
12 SYNOPSIS
14 DEVICE, UNIT/N, SYSSIZE/K/N, SYSTYPE/K, SYSNAME/K, WORKSIZE/K/N,
15 MAXWORK/S, WORKTYPE/K, WORKNAME/K, WIPE/S, FORCE/S, QUIET/S, RDB/S
17 LOCATION
21 FUNCTION
23 Partition creates either one or two AROS partitions on a given drive.
24 Existing partitions will be kept unless the WIPE option is specified
25 (or a serious bug occurs, for which we take no responsibility).
26 Partitions created by this command must be formatted before they can
27 be used.
29 By default, a single SFS System partition is created using the
30 largest amount of free space possible. A smaller size can be chosen
31 using the SYSSIZE argument. To also create a Work partition, either
32 WORKSIZE or MAXWORK must additionally be specified. The WORKSIZE
33 argument allows the size of the Work partition to be specified,
34 while setting the MAXWORK switch makes the Work partition as large
35 as possible.
37 The filesystems used by the System and Work partitions may be
38 specified using the SYSTYPE and WORKTYPE arguments respectively.
39 The available options are "SFS" (Smart Filesystem, the default), and
40 "FFSIntl" (the traditional so-called Fast Filesystem).
42 The DOS device names used for the System and Work partitions may be
43 specified using the SYSNAME and WORKNAME arguments respectively.
44 By default, these are DH0 and DH1.
46 If you wish to use only AROS on the drive you run this command on,
47 you can specify the WIPE option, which destroys all existing
48 partitions on the drive. Be very careful with this option: it
49 deletes all other operating systems and data on the drive, and could
50 be disastrous if the wrong drive is accidentally partitioned.
52 If the drive does not already contain an extended partition, one is
53 created using the largest available region of free space. The AROS
54 partitions are then created as a logical partition within. This is
55 in order to make the addition of further partitions easier.
57 INPUTS
59 DEVICE -- Device driver name (ata.device by default)
60 UNIT -- The drive's unit number (0 by default, which is the primary
61 master when using ata.device)
62 SYSSIZE -- The System (boot) partition size in megabytes.
63 SYSTYPE -- The file system to use for the system partition, either
64 "SFS" (the default) or "FFSIntl".
65 SYSNAME -- The name to use for the system partition (defaults to DH0).
66 WORKSIZE -- The Work (secondary) partition size in megabytes. To use
67 this option, SYSSIZE must also be specified.
68 MAXWORK -- Make the Work partition as large as possible. To use this
69 option, SYSSIZE must also be specified.
70 WORKTYPE -- The file system to use for the work partition, either
71 "SFS" (the default) or "FFSIntl".
72 WORKNAME -- The name to use for the work partition (defaults to DH1).
73 WIPE -- Destroy all other partitions on the drive, including those
74 used by other operating systems (CAUTION!).
75 FORCE -- Do not ask for confirmation before partitioning the drive.
76 QUIET -- Do not print any output. This option can only be used when
77 FORCE is also specified.
78 RDB -- Create only RDB partitions, no MBR or EBR partitions will be
79 created.
81 RESULT
83 Standard DOS error codes.
85 NOTES
87 Using HDToolBox instead of this command may sometimes be safer, as
88 it shows where partitions will be created on the drive before
89 changes are written to disk. However, HDToolBox can be unreliable.
91 EXAMPLE
93 Partition ata.device 1 SYSSIZE 200 MAXWORK
95 BUGS
97 SEE ALSO
99 Sys:System/Format, SFSFormat
101 ******************************************************************************/
103 #include <utility/tagitem.h>
104 #include <libraries/partition.h>
105 #include <devices/trackdisk.h>
106 #include <proto/exec.h>
107 #include <proto/dos.h>
108 #include <proto/partition.h>
109 #include <proto/utility.h>
111 #define DEBUG 0
112 #include <aros/debug.h>
114 #include "args.h"
116 #define MB (1024LL * 1024LL)
117 #define MIN_SIZE 50 /* Minimum disk space allowed in MBs */
118 #define MAX_FFS_SIZE (4L * 1024)
119 #define MAX_SFS_SIZE (124L * 1024)
120 #define MAX_SIZE(A) (((A) == &sfs0) ? MAX_SFS_SIZE : MAX_FFS_SIZE)
122 const TEXT version_string[] = "$VER: Partition 41.6 (15.10.2013)";
124 static const struct PartitionType dos3 = { "DOS\3", 4 };
125 #if AROS_BIG_ENDIAN
126 static const struct PartitionType sfs0 = { "SFS\0", 4 };
127 #else
128 /* atm, SFS is BE on AROS */
129 static const struct PartitionType sfs0 = { "SFS\0", 4 };
130 #endif
133 /*** Prototypes *************************************************************/
134 static VOID FindLargestGap(struct PartitionHandle *root, QUAD *gapLowBlock,
135 QUAD *gapHighBlock);
136 static VOID CheckGap(struct PartitionHandle *root, QUAD partLimitBlock,
137 QUAD *gapLowBlock, QUAD *gapHighBlock);
138 static struct PartitionHandle *CreateMBRPartition(
139 struct PartitionHandle *parent, ULONG lowcyl, ULONG highcyl, UBYTE id);
140 static struct PartitionHandle *CreateRDBPartition(
141 struct PartitionHandle *parent, ULONG lowcyl, ULONG highcyl,
142 CONST_STRPTR name, BOOL bootable, const struct PartitionType *type);
143 static ULONG MBsToCylinders(ULONG size, struct DosEnvec *de);
144 static LONG RecurviseDestroyPartitions(struct PartitionHandle *root);
146 /*** Functions **************************************************************/
147 int main(void)
149 struct PartitionHandle *diskPart = NULL, *sysPart, *workPart,
150 *root = NULL, *partition, *extPartition = NULL, *parent = NULL;
151 TEXT choice = 'N';
152 CONST_STRPTR device;
153 const struct PartitionType *sysType = NULL, *workType = NULL;
154 LONG error = 0, sysSize = 0, workSize = 0, sysHighCyl, lowCyl, highCyl,
155 reqHighCyl, unit, hasActive = FALSE;
156 QUAD rootLowBlock = 1, rootHighBlock = 0, extLowBlock = 1,
157 extHighBlock = 0, lowBlock, highBlock, rootBlocks, extBlocks;
158 UWORD partCount = 0;
160 /* Read and check arguments */
161 if (!ReadArguments())
162 error = IoErr();
164 if (error == 0)
166 if (ARG(WORKSIZE) != (IPTR)NULL && ARG(SYSSIZE) == (IPTR)NULL)
168 PutStr("ERROR: Cannot specify WORKSIZE without SYSSIZE.\n");
169 error = ERROR_REQUIRED_ARG_MISSING;
172 if (ARG(WORKSIZE) != (IPTR)NULL && ARG(MAXWORK))
174 PutStr("ERROR: Cannot specify both WORKSIZE and MAXWORK.\n");
175 error = ERROR_TOO_MANY_ARGS;
178 if (ARG(QUIET) && !ARG(FORCE))
180 PutStr("ERROR: Cannot specify QUIET without FORCE.\n");
181 error = ERROR_REQUIRED_ARG_MISSING;
184 if (ARG(SYSTYPE) != (IPTR)NULL &&
185 Stricmp((CONST_STRPTR)ARG(SYSTYPE), "FFSIntl") != 0 &&
186 Stricmp((CONST_STRPTR)ARG(SYSTYPE), "SFS") != 0)
188 PutStr("ERROR: SYSTYPE must be either 'FFSIntl' or 'SFS'.\n");
189 error = ERROR_REQUIRED_ARG_MISSING;
192 if (ARG(WORKTYPE) != (IPTR)NULL &&
193 Stricmp((CONST_STRPTR)ARG(WORKTYPE), "FFSIntl") != 0 &&
194 Stricmp((CONST_STRPTR)ARG(WORKTYPE), "SFS") != 0)
196 PutStr("ERROR: WORKTYPE must be either 'FFSIntl' or 'SFS'.\n");
197 error = ERROR_REQUIRED_ARG_MISSING;
201 if (error == 0)
203 /* Get DOSType for each partition */
204 if (ARG(SYSTYPE) == (IPTR)NULL ||
205 Stricmp((CONST_STRPTR)ARG(SYSTYPE), "SFS") != 0)
206 sysType = &dos3;
207 else
208 sysType = &sfs0;
210 if (ARG(WORKTYPE) == (IPTR)NULL ||
211 Stricmp((CONST_STRPTR)ARG(WORKTYPE), "FFSIntl") != 0)
212 workType = &sfs0;
213 else
214 workType = &dos3;
216 device = (CONST_STRPTR) ARG(DEVICE);
217 unit = *(LONG *)ARG(UNIT);
218 if (ARG(SYSSIZE) != (IPTR)NULL)
219 sysSize = *(LONG *)ARG(SYSSIZE);
220 if (ARG(WORKSIZE) != (IPTR)NULL)
221 workSize = *(LONG *)ARG(WORKSIZE);
223 D(bug("[C:Partition] Using %s, unit %ld\n", device, unit));
225 if (!ARG(FORCE))
227 Printf("About to partition %s unit %d.\n", device, unit);
228 if (ARG(WIPE))
229 Printf("This will DESTROY ALL DATA on the drive!\n");
230 Printf("Are you sure? (y/N)"); Flush(Output());
232 Read(Input(), &choice, 1);
234 else
236 choice = 'y';
239 if (choice != 'y' && choice != 'Y') return RETURN_WARN;
241 if (!ARG(QUIET))
243 Printf("Partitioning drive...");
244 Flush(Output());
247 D(bug("[C:Partition] Partitioning drive...\n"));
250 if (error == 0)
252 D(bug("[C:Partition] Open root partition\n"));
253 if ((root = OpenRootPartition(device, unit)) == NULL)
255 error = ERROR_UNKNOWN;
256 PutStr("*** Could not open root partition!\n");
260 /* Destroy any existing partition table if requested */
261 if (error == 0 && ARG(WIPE))
263 if (OpenPartitionTable(root) == 0)
265 D(bug("[C:Partition] WIPE partitions\n"));
266 error = RecurviseDestroyPartitions(root);
270 if (error == 0)
272 /* Open the existing partition table, or create it if none exists */
273 D(bug("[C:Partition] Opening existing root partition table..."));
274 if (OpenPartitionTable(root) != 0)
276 D(bug("failed\n[C:Partition] Creating %s root partition table\n",
277 ARG(RDB) ? "RDB" : "MBR"));
279 ULONG type = ARG(RDB) ? PHPTT_RDB : PHPTT_MBR;
280 /* Create a root partition table */
281 if (CreatePartitionTable(root, type) != 0)
283 error = ERROR_UNKNOWN;
284 PutStr("*** ERROR: Creating root partition table failed.\n");
285 CloseRootPartition(root);
286 root = NULL;
289 else
290 D(bug("ok\n"));
293 if (error == 0)
295 /* Find largest gap in root partition */
296 FindLargestGap(root, &rootLowBlock, &rootHighBlock);
298 if (!ARG(RDB))
300 /* Look for extended partition and count partitions */
301 ForeachNode(&root->table->list, partition)
303 if (OpenPartitionTable(partition) == 0)
305 if (partition->table->type == PHPTT_EBR)
306 extPartition = partition;
307 else
308 ClosePartitionTable(partition);
311 if (!hasActive)
312 GetPartitionAttrsTags(partition,
313 PT_ACTIVE, (IPTR) &hasActive, TAG_DONE);
315 partCount++;
318 /* Create extended partition if it doesn't exist */
319 if (extPartition == NULL)
321 D(bug("[C:Partition] Creating EBR partition\n"));
322 lowCyl = (rootLowBlock - 1)
323 / (LONG)(root->de.de_Surfaces * root->de.de_BlocksPerTrack)
324 + 1;
325 highCyl = (rootHighBlock + 1)
326 / (root->de.de_Surfaces * root->de.de_BlocksPerTrack) - 1;
327 extPartition =
328 CreateMBRPartition(root, lowCyl, highCyl, 0x5);
329 if (extPartition != NULL)
331 if (CreatePartitionTable(extPartition, PHPTT_EBR) != 0)
333 PutStr("*** ERROR: Creating extended partition table failed.\n");
334 extPartition = NULL;
336 rootLowBlock = 1;
337 rootHighBlock = 0;
338 partCount++;
344 if (error == 0)
346 /* Find largest gap in extended partition */
347 if (extPartition != NULL)
349 FindLargestGap(extPartition, &extLowBlock, &extHighBlock);
352 /* Choose whether to create primary or logical partition */
353 rootBlocks = rootHighBlock - rootLowBlock + 1;
354 extBlocks = extHighBlock - extLowBlock + 1;
355 if (extBlocks > rootBlocks || partCount == 4)
357 parent = extPartition;
358 lowBlock = extLowBlock;
359 highBlock = extHighBlock;
361 else
363 parent = root;
364 lowBlock = rootLowBlock;
365 highBlock = rootHighBlock;
368 /* Convert block range to cylinders */
369 lowCyl = (lowBlock - 1)
370 / (LONG)(parent->de.de_Surfaces * parent->de.de_BlocksPerTrack) + 1;
371 highCyl = (highBlock + 1)
372 / (LONG)(parent->de.de_Surfaces * parent->de.de_BlocksPerTrack) - 1;
374 /* Ensure neither partition is too large for its filesystem */
375 if ((sysSize == 0 &&
376 highCyl - lowCyl + 1 >
377 MBsToCylinders(MAX_SIZE(sysType), &parent->de)) ||
378 sysSize > MAX_SIZE(sysType))
379 sysSize = MAX_SIZE(sysType);
380 if ((ARG(MAXWORK) &&
381 (highCyl - lowCyl + 1)
382 - MBsToCylinders(sysSize, &parent->de) + 1 >
383 MBsToCylinders(MAX_SIZE(workType), &parent->de)) ||
384 workSize > MAX_SIZE(workType))
385 workSize = MAX_SIZE(workType);
387 /* Decide geometry for RDB virtual disk */
388 reqHighCyl = lowCyl + MBsToCylinders(sysSize, &parent->de)
389 + MBsToCylinders(workSize, &parent->de);
390 if (sysSize != 0 && (workSize != 0 || !ARG(MAXWORK))
391 && reqHighCyl < highCyl)
392 highCyl = reqHighCyl;
393 if (reqHighCyl > highCyl
394 || (highCyl - lowCyl + 1 < MBsToCylinders(MIN_SIZE, &parent->de)
395 && workSize == 0))
396 error = ERROR_DISK_FULL;
399 if (error == 0 && !ARG(RDB))
401 /* Create RDB virtual disk */
402 D(bug("[C:Partition] Creating RDB virtual disk\n"));
403 diskPart = CreateMBRPartition(parent, lowCyl, highCyl, 0x30);
404 if (diskPart == NULL)
406 PutStr("*** ERROR: Not enough disk space.\n");
407 error = ERROR_UNKNOWN;
411 if (error == 0 && !ARG(RDB))
413 /* Create RDB partition table inside virtual-disk partition */
414 D(bug("[C:Partition] Creating RDB partition table\n"));
415 error = CreatePartitionTable(diskPart, PHPTT_RDB);
416 if (error != 0)
418 PutStr(
419 "*** ERROR: Creating RDB partition table failed. Aborting.\n");
423 if (error == 0)
425 if (ARG(RDB))
427 diskPart = parent;
429 /* Create partitions in the RDB table */
430 sysHighCyl = sysSize != 0
431 ? lowCyl + MBsToCylinders(sysSize, &diskPart->de)
432 : highCyl;
434 /* Create System partition (defaults to FFSIntl) */
435 sysPart = CreateRDBPartition(diskPart, lowCyl, sysHighCyl, (APTR)ARG(SYSNAME),
436 TRUE, sysType);
437 if (sysPart == NULL)
438 error = ERROR_UNKNOWN;
440 if (error == 0
441 && workSize != 0
442 && sysHighCyl < diskPart->de.de_HighCyl - diskPart->de.de_LowCyl)
444 /* Create Work partition (defaults to SFS) */
445 workPart = CreateRDBPartition(diskPart, sysHighCyl + 1, highCyl,
446 (APTR)ARG(WORKNAME), FALSE, workType);
447 if (workPart == NULL)
448 error = ERROR_UNKNOWN;
451 else
453 /* Create partitions in the RDB table */
454 sysHighCyl = MBsToCylinders(sysSize, &diskPart->de);
456 /* Create System partition (defaults to FFSIntl) */
457 sysPart = CreateRDBPartition(diskPart, 0, sysHighCyl, (APTR)ARG(SYSNAME),
458 TRUE, sysType);
459 if (sysPart == NULL)
460 error = ERROR_UNKNOWN;
462 if (sysSize != 0
463 && sysHighCyl < diskPart->de.de_HighCyl - diskPart->de.de_LowCyl)
465 /* Create Work partition (defaults to SFS) */
466 workPart = CreateRDBPartition(diskPart, sysHighCyl + 1, 0,
467 (APTR)ARG(WORKNAME), FALSE, workType);
468 if (workPart == NULL)
469 error = ERROR_UNKNOWN;
474 if (error == 0)
476 /* If MBR has no active partition, make extended partition active to
477 prevent broken BIOSes from treating disk as unbootable */
478 if (!hasActive && !ARG(RDB))
479 SetPartitionAttrsTags(extPartition, PT_ACTIVE, TRUE, TAG_DONE);
481 /* Save to disk and deallocate */
482 WritePartitionTable(diskPart);
483 ClosePartitionTable(diskPart);
485 if (parent == extPartition)
487 WritePartitionTable(extPartition);
488 ClosePartitionTable(extPartition);
491 /* Save to disk and deallocate */
492 WritePartitionTable(root);
493 ClosePartitionTable(root);
496 if (root != NULL)
497 CloseRootPartition(root);
499 if (!ARG(QUIET) && error == 0) Printf("Partitioning completed\n");
501 PrintFault(error, NULL);
502 return (error == 0) ? RETURN_OK : RETURN_FAIL;
505 /* Find the low and high cylinder values for the largest gap on the disk */
506 static VOID FindLargestGap(struct PartitionHandle *root, QUAD *gapLowBlock,
507 QUAD *gapHighBlock)
509 struct PartitionHandle *partition;
510 LONG reservedBlocks = 0;
511 QUAD partLimitBlock;
513 /* Check gap between start of disk and first partition, or until end of
514 disk if there are no partitions */
515 GetPartitionTableAttrsTags(root, PTT_RESERVED, (IPTR) &reservedBlocks,
516 TAG_DONE);
517 partLimitBlock = reservedBlocks;
518 CheckGap(root, partLimitBlock, gapLowBlock, gapHighBlock);
520 /* Check gap between each partition and the next one (or end of disk for
521 the last partition)*/
522 ForeachNode(&root->table->list, partition)
524 partLimitBlock = (partition->de.de_HighCyl + 1)
525 * partition->de.de_Surfaces
526 * partition->de.de_BlocksPerTrack;
527 CheckGap(root, partLimitBlock, gapLowBlock, gapHighBlock);
530 return;
533 /* Check if the gap between the end of the current partition and the start of
534 the next one is bigger than the biggest gap previously found. If so, it is
535 stored as the new biggest gap. */
536 static VOID CheckGap(struct PartitionHandle *root, QUAD partLimitBlock,
537 QUAD *gapLowBlock, QUAD *gapHighBlock)
539 struct PartitionHandle *nextPartition;
540 QUAD lowBlock, nextLowBlock;
542 /* Search partitions for next partition by disk position */
543 nextLowBlock = (root->de.de_HighCyl - root->de.de_LowCyl + 1)
544 * root->de.de_Surfaces * root->de.de_BlocksPerTrack; /* End of disk */
545 ForeachNode(&root->table->list, nextPartition)
547 lowBlock = nextPartition->de.de_LowCyl
548 * nextPartition->de.de_Surfaces
549 * nextPartition->de.de_BlocksPerTrack;
550 if (lowBlock >= partLimitBlock && lowBlock < nextLowBlock)
552 nextLowBlock = lowBlock;
556 /* Check if the gap between the current pair of partitions is the
557 biggest gap so far */
558 if (nextLowBlock - partLimitBlock > *gapHighBlock - *gapLowBlock + 1)
560 *gapLowBlock = partLimitBlock;
561 *gapHighBlock = nextLowBlock - 1;
564 return;
567 static struct PartitionHandle *CreateMBRPartition
569 struct PartitionHandle *parent, ULONG lowcyl, ULONG highcyl, UBYTE id
572 struct DriveGeometry parentDG = {0};
573 struct DosEnvec parentDE = {0},
574 partitionDE = {0};
575 struct PartitionType type = {{id}, 1};
576 struct PartitionHandle *partition;
577 IPTR reserved, leadIn = 0;
578 ULONG maxcyl;
580 GetPartitionAttrsTags
582 parent,
584 PT_DOSENVEC, (IPTR) &parentDE,
585 PT_GEOMETRY, (IPTR) &parentDG,
587 TAG_DONE
590 GetPartitionTableAttrsTags
592 parent,
593 PTT_RESERVED, (IPTR) &reserved,
594 PTT_MAXLEADIN, (IPTR) &leadIn,
595 TAG_DONE
598 if (lowcyl == 0)
600 lowcyl = (reserved - 1) /
601 (parentDG.dg_Heads * parentDG.dg_TrackSectors) + 1;
604 if (leadIn != 0)
606 lowcyl += (leadIn - 1) /
607 (parentDG.dg_Heads * parentDG.dg_TrackSectors) + 1;
610 maxcyl = parentDE.de_HighCyl - parentDE.de_LowCyl;
611 if (highcyl == 0 || highcyl > maxcyl)
613 highcyl = maxcyl;
616 CopyMem(&parentDE, &partitionDE, sizeof(struct DosEnvec));
618 partitionDE.de_SizeBlock = parentDG.dg_SectorSize >> 2;
619 partitionDE.de_Reserved = 2;
620 partitionDE.de_HighCyl = highcyl;
621 partitionDE.de_LowCyl = lowcyl;
623 partition = AddPartitionTags
625 parent,
626 PT_DOSENVEC, (IPTR) &partitionDE,
627 PT_TYPE, (IPTR) &type,
628 TAG_DONE
631 return partition;
634 static struct PartitionHandle *CreateRDBPartition
636 struct PartitionHandle *parent, ULONG lowcyl, ULONG highcyl,
637 CONST_STRPTR name, BOOL bootable, const struct PartitionType *type
640 struct DriveGeometry parentDG = {0};
641 struct DosEnvec parentDE = {0},
642 partitionDE = {0};
643 struct PartitionHandle *partition;
644 ULONG maxcyl;
646 GetPartitionAttrsTags
648 parent,
650 PT_DOSENVEC, (IPTR) &parentDE,
651 PT_GEOMETRY, (IPTR) &parentDG,
653 TAG_DONE
656 if (lowcyl == 0)
658 ULONG reserved;
660 GetPartitionTableAttrsTags
662 parent, PTT_RESERVED, (IPTR) &reserved, TAG_DONE
665 lowcyl = (reserved - 1)
666 / (parentDG.dg_Heads * parentDG.dg_TrackSectors) + 1;
669 maxcyl = parentDE.de_HighCyl - parentDE.de_LowCyl;
670 if (highcyl == 0 || highcyl > maxcyl)
672 highcyl = maxcyl;
675 CopyMem(&parentDE, &partitionDE, sizeof(struct DosEnvec));
677 partitionDE.de_SizeBlock = parentDG.dg_SectorSize >> 2;
678 partitionDE.de_Surfaces = parentDG.dg_Heads;
679 partitionDE.de_BlocksPerTrack = parentDG.dg_TrackSectors;
680 partitionDE.de_BufMemType = parentDG.dg_BufMemType;
681 partitionDE.de_TableSize = DE_DOSTYPE;
682 partitionDE.de_Reserved = 2;
683 partitionDE.de_HighCyl = highcyl;
684 partitionDE.de_LowCyl = lowcyl;
685 partitionDE.de_NumBuffers = 100;
686 partitionDE.de_MaxTransfer = 0xFFFFFF;
687 partitionDE.de_Mask = 0xFFFFFFFE;
689 D(bug("[C:Partition] SizeBlock %ld\n", partitionDE.de_SizeBlock ));
690 D(bug("[C:Partition] Surfaces %ld\n", partitionDE.de_Surfaces));
691 D(bug("[C:Partition] BlocksPerTrack %ld\n", partitionDE.de_BlocksPerTrack));
692 D(bug("[C:Partition] BufMemType %ld\n", partitionDE.de_BufMemType));
693 D(bug("[C:Partition] TableSize %ld\n", partitionDE.de_TableSize));
694 D(bug("[C:Partition] Reserved %ld\n", partitionDE.de_Reserved));
695 D(bug("[C:Partition] HighCyl %ld\n", partitionDE.de_HighCyl));
696 D(bug("[C:Partition] LowCyl %ld\n", partitionDE.de_LowCyl));
698 partition = AddPartitionTags
700 parent,
702 PT_DOSENVEC, (IPTR) &partitionDE,
703 PT_TYPE, (IPTR) type,
704 PT_NAME, (IPTR) name,
705 PT_BOOTABLE, bootable,
706 PT_AUTOMOUNT, TRUE,
708 TAG_DONE
711 return partition;
714 /* Convert a size in megabytes into a cylinder count. The figure returned
715 is rounded down to avoid breaching maximum filesystem sizes. */
716 static ULONG MBsToCylinders(ULONG size, struct DosEnvec *de)
718 UQUAD bytes;
719 ULONG cyls = 0;
721 if (size != 0)
723 bytes = size * MB;
724 cyls = bytes / (UQUAD)(de->de_SizeBlock * sizeof(ULONG))
725 / de->de_BlocksPerTrack / de->de_Surfaces;
727 return cyls;
730 #define ZEROBUFFSIZE 4096
732 /* Go through whole partition tree and WIPE each and every entry */
733 static LONG RecurviseDestroyPartitions(struct PartitionHandle *root)
735 LONG error = 0;
737 if (root->table)
739 struct PartitionHandle *partition;
740 ForeachNode(&root->table->list, partition)
742 if (OpenPartitionTable(partition) == 0)
744 error += RecurviseDestroyPartitions(partition);
746 else
748 APTR buffer = AllocMem(ZEROBUFFSIZE, MEMF_CLEAR);
749 /* Damage first blocks of partition */
750 WritePartitionDataQ(partition, buffer, ZEROBUFFSIZE, 0);
751 FreeMem(buffer, ZEROBUFFSIZE);
756 error += DestroyPartitionTable(root);
758 return error;