2 Copyright © 2003-2013, The AROS Development Team. All rights reserved.
6 /******************************************************************************
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
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
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
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.
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
83 Standard DOS error codes.
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.
93 Partition ata.device 1 SYSSIZE 200 MAXWORK
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>
112 #include <aros/debug.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.7 (17.10.2013)";
124 static const struct PartitionType dos3
= { "DOS\3", 4 };
126 static const struct PartitionType sfs0
= { "SFS\0", 4 };
128 /* atm, SFS is BE on AROS */
129 static const struct PartitionType sfs0
= { "SFS\0", 4 };
133 /*** Prototypes *************************************************************/
134 static VOID
FindLargestGap(struct PartitionHandle
*root
, QUAD
*gapLowBlock
,
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 **************************************************************/
149 struct PartitionHandle
*diskPart
= NULL
, *sysPart
, *workPart
,
150 *root
= NULL
, *partition
, *extPartition
= NULL
, *parent
= NULL
;
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
;
160 /* Read and check arguments */
161 if (!ReadArguments())
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
;
203 /* Get DOSType for each partition */
204 if (ARG(SYSTYPE
) == (IPTR
)NULL
||
205 Stricmp((CONST_STRPTR
)ARG(SYSTYPE
), "SFS") != 0)
210 if (ARG(WORKTYPE
) == (IPTR
)NULL
||
211 Stricmp((CONST_STRPTR
)ARG(WORKTYPE
), "FFSIntl") != 0)
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
));
227 Printf("About to partition %s unit %d.\n", device
, unit
);
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);
239 if (choice
!= 'y' && choice
!= 'Y') return RETURN_WARN
;
243 Printf("Partitioning drive...");
247 D(bug("[C:Partition] Partitioning drive...\n"));
252 D(bug("[C:Partition] Open root partition\n"));
253 if ((root
= OpenRootPartition(device
, unit
)) == NULL
)
255 error
= ERROR_UNKNOWN
;
256 Printf("*** Could not open root partition of device %s, unit %d!\n", device
, unit
);
257 PutStr("Make sure that you provided correct device name and unit number.\n");
258 PutStr("For example primary master IDE device will most likely map to\n");
259 PutStr("ata.device, unit 0 and secondary slave to ata.device, unit 3\n");
263 /* Destroy any existing partition table if requested */
264 if (error
== 0 && ARG(WIPE
))
266 if (OpenPartitionTable(root
) == 0)
268 D(bug("[C:Partition] WIPE partitions\n"));
269 error
= RecurviseDestroyPartitions(root
);
275 /* Open the existing partition table, or create it if none exists */
276 D(bug("[C:Partition] Opening existing root partition table..."));
277 if (OpenPartitionTable(root
) != 0)
279 D(bug("failed\n[C:Partition] Creating %s root partition table\n",
280 ARG(RDB
) ? "RDB" : "MBR"));
282 ULONG type
= ARG(RDB
) ? PHPTT_RDB
: PHPTT_MBR
;
283 /* Create a root partition table */
284 if (CreatePartitionTable(root
, type
) != 0)
286 error
= ERROR_UNKNOWN
;
287 PutStr("*** ERROR: Creating root partition table failed.\n");
288 CloseRootPartition(root
);
298 /* Find largest gap in root partition */
299 FindLargestGap(root
, &rootLowBlock
, &rootHighBlock
);
303 /* Look for extended partition and count partitions */
304 ForeachNode(&root
->table
->list
, partition
)
306 if (OpenPartitionTable(partition
) == 0)
308 if (partition
->table
->type
== PHPTT_EBR
)
309 extPartition
= partition
;
311 ClosePartitionTable(partition
);
315 GetPartitionAttrsTags(partition
,
316 PT_ACTIVE
, (IPTR
) &hasActive
, TAG_DONE
);
321 /* Create extended partition if it doesn't exist */
322 if (extPartition
== NULL
)
324 D(bug("[C:Partition] Creating EBR partition\n"));
325 lowCyl
= (rootLowBlock
- 1)
326 / (LONG
)(root
->de
.de_Surfaces
* root
->de
.de_BlocksPerTrack
)
328 highCyl
= (rootHighBlock
+ 1)
329 / (root
->de
.de_Surfaces
* root
->de
.de_BlocksPerTrack
) - 1;
331 CreateMBRPartition(root
, lowCyl
, highCyl
, 0x5);
332 if (extPartition
!= NULL
)
334 if (CreatePartitionTable(extPartition
, PHPTT_EBR
) != 0)
336 PutStr("*** ERROR: Creating extended partition table failed.\n");
349 /* Find largest gap in extended partition */
350 if (extPartition
!= NULL
)
352 FindLargestGap(extPartition
, &extLowBlock
, &extHighBlock
);
355 /* Choose whether to create primary or logical partition */
356 rootBlocks
= rootHighBlock
- rootLowBlock
+ 1;
357 extBlocks
= extHighBlock
- extLowBlock
+ 1;
358 if (extBlocks
> rootBlocks
|| partCount
== 4)
360 parent
= extPartition
;
361 lowBlock
= extLowBlock
;
362 highBlock
= extHighBlock
;
367 lowBlock
= rootLowBlock
;
368 highBlock
= rootHighBlock
;
371 /* Convert block range to cylinders */
372 lowCyl
= (lowBlock
- 1)
373 / (LONG
)(parent
->de
.de_Surfaces
* parent
->de
.de_BlocksPerTrack
) + 1;
374 highCyl
= (highBlock
+ 1)
375 / (LONG
)(parent
->de
.de_Surfaces
* parent
->de
.de_BlocksPerTrack
) - 1;
377 /* Ensure neither partition is too large for its filesystem */
379 highCyl
- lowCyl
+ 1 >
380 MBsToCylinders(MAX_SIZE(sysType
), &parent
->de
)) ||
381 sysSize
> MAX_SIZE(sysType
))
382 sysSize
= MAX_SIZE(sysType
);
384 (highCyl
- lowCyl
+ 1)
385 - MBsToCylinders(sysSize
, &parent
->de
) + 1 >
386 MBsToCylinders(MAX_SIZE(workType
), &parent
->de
)) ||
387 workSize
> MAX_SIZE(workType
))
388 workSize
= MAX_SIZE(workType
);
390 /* Decide geometry for RDB virtual disk */
391 reqHighCyl
= lowCyl
+ MBsToCylinders(sysSize
, &parent
->de
)
392 + MBsToCylinders(workSize
, &parent
->de
);
393 if (sysSize
!= 0 && (workSize
!= 0 || !ARG(MAXWORK
))
394 && reqHighCyl
< highCyl
)
395 highCyl
= reqHighCyl
;
396 if (reqHighCyl
> highCyl
397 || (highCyl
- lowCyl
+ 1 < MBsToCylinders(MIN_SIZE
, &parent
->de
)
399 error
= ERROR_DISK_FULL
;
402 if (error
== 0 && !ARG(RDB
))
404 /* Create RDB virtual disk */
405 D(bug("[C:Partition] Creating RDB virtual disk\n"));
406 diskPart
= CreateMBRPartition(parent
, lowCyl
, highCyl
, 0x30);
407 if (diskPart
== NULL
)
409 PutStr("*** ERROR: Not enough disk space.\n");
410 error
= ERROR_UNKNOWN
;
414 if (error
== 0 && !ARG(RDB
))
416 /* Create RDB partition table inside virtual-disk partition */
417 D(bug("[C:Partition] Creating RDB partition table\n"));
418 error
= CreatePartitionTable(diskPart
, PHPTT_RDB
);
422 "*** ERROR: Creating RDB partition table failed. Aborting.\n");
432 /* Create partitions in the RDB table */
433 sysHighCyl
= sysSize
!= 0
434 ? lowCyl
+ MBsToCylinders(sysSize
, &diskPart
->de
)
437 /* Create System partition (defaults to FFSIntl) */
438 sysPart
= CreateRDBPartition(diskPart
, lowCyl
, sysHighCyl
, (APTR
)ARG(SYSNAME
),
441 error
= ERROR_UNKNOWN
;
445 && sysHighCyl
< diskPart
->de
.de_HighCyl
- diskPart
->de
.de_LowCyl
)
447 /* Create Work partition (defaults to SFS) */
448 workPart
= CreateRDBPartition(diskPart
, sysHighCyl
+ 1, highCyl
,
449 (APTR
)ARG(WORKNAME
), FALSE
, workType
);
450 if (workPart
== NULL
)
451 error
= ERROR_UNKNOWN
;
456 /* Create partitions in the RDB table */
457 sysHighCyl
= MBsToCylinders(sysSize
, &diskPart
->de
);
459 /* Create System partition (defaults to FFSIntl) */
460 sysPart
= CreateRDBPartition(diskPart
, 0, sysHighCyl
, (APTR
)ARG(SYSNAME
),
463 error
= ERROR_UNKNOWN
;
466 && sysHighCyl
< diskPart
->de
.de_HighCyl
- diskPart
->de
.de_LowCyl
)
468 /* Create Work partition (defaults to SFS) */
469 workPart
= CreateRDBPartition(diskPart
, sysHighCyl
+ 1, 0,
470 (APTR
)ARG(WORKNAME
), FALSE
, workType
);
471 if (workPart
== NULL
)
472 error
= ERROR_UNKNOWN
;
479 /* If MBR has no active partition, make extended partition active to
480 prevent broken BIOSes from treating disk as unbootable */
481 if (!hasActive
&& !ARG(RDB
))
482 SetPartitionAttrsTags(extPartition
, PT_ACTIVE
, TRUE
, TAG_DONE
);
484 /* Save to disk and deallocate */
485 WritePartitionTable(diskPart
);
486 ClosePartitionTable(diskPart
);
488 if (parent
== extPartition
)
490 WritePartitionTable(extPartition
);
491 ClosePartitionTable(extPartition
);
494 /* Save to disk and deallocate */
495 WritePartitionTable(root
);
496 ClosePartitionTable(root
);
500 CloseRootPartition(root
);
502 if (!ARG(QUIET
) && error
== 0) Printf("Partitioning completed\n");
504 PrintFault(error
, NULL
);
505 return (error
== 0) ? RETURN_OK
: RETURN_FAIL
;
508 /* Find the low and high cylinder values for the largest gap on the disk */
509 static VOID
FindLargestGap(struct PartitionHandle
*root
, QUAD
*gapLowBlock
,
512 struct PartitionHandle
*partition
;
513 LONG reservedBlocks
= 0;
516 /* Check gap between start of disk and first partition, or until end of
517 disk if there are no partitions */
518 GetPartitionTableAttrsTags(root
, PTT_RESERVED
, (IPTR
) &reservedBlocks
,
520 partLimitBlock
= reservedBlocks
;
521 CheckGap(root
, partLimitBlock
, gapLowBlock
, gapHighBlock
);
523 /* Check gap between each partition and the next one (or end of disk for
524 the last partition)*/
525 ForeachNode(&root
->table
->list
, partition
)
527 partLimitBlock
= (partition
->de
.de_HighCyl
+ 1)
528 * partition
->de
.de_Surfaces
529 * partition
->de
.de_BlocksPerTrack
;
530 CheckGap(root
, partLimitBlock
, gapLowBlock
, gapHighBlock
);
536 /* Check if the gap between the end of the current partition and the start of
537 the next one is bigger than the biggest gap previously found. If so, it is
538 stored as the new biggest gap. */
539 static VOID
CheckGap(struct PartitionHandle
*root
, QUAD partLimitBlock
,
540 QUAD
*gapLowBlock
, QUAD
*gapHighBlock
)
542 struct PartitionHandle
*nextPartition
;
543 QUAD lowBlock
, nextLowBlock
;
545 /* Search partitions for next partition by disk position */
546 nextLowBlock
= (root
->de
.de_HighCyl
- root
->de
.de_LowCyl
+ 1)
547 * root
->de
.de_Surfaces
* root
->de
.de_BlocksPerTrack
; /* End of disk */
548 ForeachNode(&root
->table
->list
, nextPartition
)
550 lowBlock
= nextPartition
->de
.de_LowCyl
551 * nextPartition
->de
.de_Surfaces
552 * nextPartition
->de
.de_BlocksPerTrack
;
553 if (lowBlock
>= partLimitBlock
&& lowBlock
< nextLowBlock
)
555 nextLowBlock
= lowBlock
;
559 /* Check if the gap between the current pair of partitions is the
560 biggest gap so far */
561 if (nextLowBlock
- partLimitBlock
> *gapHighBlock
- *gapLowBlock
+ 1)
563 *gapLowBlock
= partLimitBlock
;
564 *gapHighBlock
= nextLowBlock
- 1;
570 static struct PartitionHandle
*CreateMBRPartition
572 struct PartitionHandle
*parent
, ULONG lowcyl
, ULONG highcyl
, UBYTE id
575 struct DriveGeometry parentDG
= {0};
576 struct DosEnvec parentDE
= {0},
578 struct PartitionType type
= {{id
}, 1};
579 struct PartitionHandle
*partition
;
580 IPTR reserved
, leadIn
= 0;
583 GetPartitionAttrsTags
587 PT_DOSENVEC
, (IPTR
) &parentDE
,
588 PT_GEOMETRY
, (IPTR
) &parentDG
,
593 GetPartitionTableAttrsTags
596 PTT_RESERVED
, (IPTR
) &reserved
,
597 PTT_MAXLEADIN
, (IPTR
) &leadIn
,
603 lowcyl
= (reserved
- 1) /
604 (parentDG
.dg_Heads
* parentDG
.dg_TrackSectors
) + 1;
609 lowcyl
+= (leadIn
- 1) /
610 (parentDG
.dg_Heads
* parentDG
.dg_TrackSectors
) + 1;
613 maxcyl
= parentDE
.de_HighCyl
- parentDE
.de_LowCyl
;
614 if (highcyl
== 0 || highcyl
> maxcyl
)
619 CopyMem(&parentDE
, &partitionDE
, sizeof(struct DosEnvec
));
621 partitionDE
.de_SizeBlock
= parentDG
.dg_SectorSize
>> 2;
622 partitionDE
.de_Reserved
= 2;
623 partitionDE
.de_HighCyl
= highcyl
;
624 partitionDE
.de_LowCyl
= lowcyl
;
626 partition
= AddPartitionTags
629 PT_DOSENVEC
, (IPTR
) &partitionDE
,
630 PT_TYPE
, (IPTR
) &type
,
637 static struct PartitionHandle
*CreateRDBPartition
639 struct PartitionHandle
*parent
, ULONG lowcyl
, ULONG highcyl
,
640 CONST_STRPTR name
, BOOL bootable
, const struct PartitionType
*type
643 struct DriveGeometry parentDG
= {0};
644 struct DosEnvec parentDE
= {0},
646 struct PartitionHandle
*partition
;
649 GetPartitionAttrsTags
653 PT_DOSENVEC
, (IPTR
) &parentDE
,
654 PT_GEOMETRY
, (IPTR
) &parentDG
,
663 GetPartitionTableAttrsTags
665 parent
, PTT_RESERVED
, (IPTR
) &reserved
, TAG_DONE
668 lowcyl
= (reserved
- 1)
669 / (parentDG
.dg_Heads
* parentDG
.dg_TrackSectors
) + 1;
672 maxcyl
= parentDE
.de_HighCyl
- parentDE
.de_LowCyl
;
673 if (highcyl
== 0 || highcyl
> maxcyl
)
678 CopyMem(&parentDE
, &partitionDE
, sizeof(struct DosEnvec
));
680 partitionDE
.de_SizeBlock
= parentDG
.dg_SectorSize
>> 2;
681 partitionDE
.de_Surfaces
= parentDG
.dg_Heads
;
682 partitionDE
.de_BlocksPerTrack
= parentDG
.dg_TrackSectors
;
683 partitionDE
.de_BufMemType
= parentDG
.dg_BufMemType
;
684 partitionDE
.de_TableSize
= DE_DOSTYPE
;
685 partitionDE
.de_Reserved
= 2;
686 partitionDE
.de_HighCyl
= highcyl
;
687 partitionDE
.de_LowCyl
= lowcyl
;
688 partitionDE
.de_NumBuffers
= 100;
689 partitionDE
.de_MaxTransfer
= 0xFFFFFF;
690 partitionDE
.de_Mask
= 0xFFFFFFFE;
692 D(bug("[C:Partition] SizeBlock %ld\n", partitionDE
.de_SizeBlock
));
693 D(bug("[C:Partition] Surfaces %ld\n", partitionDE
.de_Surfaces
));
694 D(bug("[C:Partition] BlocksPerTrack %ld\n", partitionDE
.de_BlocksPerTrack
));
695 D(bug("[C:Partition] BufMemType %ld\n", partitionDE
.de_BufMemType
));
696 D(bug("[C:Partition] TableSize %ld\n", partitionDE
.de_TableSize
));
697 D(bug("[C:Partition] Reserved %ld\n", partitionDE
.de_Reserved
));
698 D(bug("[C:Partition] HighCyl %ld\n", partitionDE
.de_HighCyl
));
699 D(bug("[C:Partition] LowCyl %ld\n", partitionDE
.de_LowCyl
));
701 partition
= AddPartitionTags
705 PT_DOSENVEC
, (IPTR
) &partitionDE
,
706 PT_TYPE
, (IPTR
) type
,
707 PT_NAME
, (IPTR
) name
,
708 PT_BOOTABLE
, bootable
,
717 /* Convert a size in megabytes into a cylinder count. The figure returned
718 is rounded down to avoid breaching maximum filesystem sizes. */
719 static ULONG
MBsToCylinders(ULONG size
, struct DosEnvec
*de
)
727 cyls
= bytes
/ (UQUAD
)(de
->de_SizeBlock
* sizeof(ULONG
))
728 / de
->de_BlocksPerTrack
/ de
->de_Surfaces
;
733 #define ZEROBUFFSIZE 4096
735 /* Go through whole partition tree and WIPE each and every entry */
736 static LONG
RecurviseDestroyPartitions(struct PartitionHandle
*root
)
742 struct PartitionHandle
*partition
;
743 ForeachNode(&root
->table
->list
, partition
)
745 if (OpenPartitionTable(partition
) == 0)
747 error
+= RecurviseDestroyPartitions(partition
);
751 APTR buffer
= AllocMem(ZEROBUFFSIZE
, MEMF_CLEAR
);
752 /* Damage first blocks of partition */
753 WritePartitionDataQ(partition
, buffer
, ZEROBUFFSIZE
, 0);
754 FreeMem(buffer
, ZEROBUFFSIZE
);
759 error
+= DestroyPartitionTable(root
);