|
nwtool
nwtool
/***************************************************************************
*
* Copyright (c) 1998, 1999 Jeff V. Merkey
* 895 West Center Street
* Orem, Utah 84057
* jmerkey@utah-nac.org
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2, or any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You are free to modify and re-distribute this program in accordance
* with the terms specified in the GNU Public License. The copyright
* contained in this code is required to be present in any derivative
* works and you are required to provide the source code for this
* program as part of any commercial or non-commercial distribution.
* You are required to respect the rights of the Copyright holders
* named within this code.
*
* jmerkey@utah-nac.org is the official maintainer of
* this code. You are encouraged to report any bugs, problems, fixes,
* suggestions, and comments about this software to jmerkey@utah-nac.org
* or linux-kernel@vger.kernel.org. New releases, patches, bug fixes, and
* technical documentation can be found at www.kernel.org. We will
* periodically post new releases of this software to www.kernel.org
* that contain bug fixes and enhanced capabilities.
*
* Original Authorship :
* source code written by Jeff V. Merkey
*
* Original Contributors :
* Jeff V. Merkey
* Darren Major
*
*
****************************************************************************
*
*
* AUTHOR : Jeff V. Merkey (jmerkey@utah-nac.org)
* FILE : NWTOOL.C
* DESCRIP : FENRIS NWFS Tools
* DATE : March 27, 2000
*
*
***************************************************************************/
#include "globals.h"
extern ULONG segment_table_count;
extern segment_info_table segment_table[256];
extern ULONG segment_mark_table[256];
extern ULONG hotfix_table_count;
extern hotfix_info_table hotfix_table[256];
extern BYTE NwPartSignature[16];
extern BYTE NetwareBootSector[512];
extern ULONG FirstValidDisk;
extern BYTE *NSDescription(ULONG);
#if (DOS_UTIL | LINUX_UTIL | WINDOWS_NT_UTIL)
void UtilScanVolumes(void)
{
NWFSPrint("\nScanning Disks ... \n");
NWFSVolumeScan();
}
ULONG input_get_number(ULONG *new_value)
{
ULONG hex_value = 0;
ULONG dec_value = 0;
ULONG dec_flag = 1;
BYTE *bptr;
BYTE input_buffer[20] = { "" };
fgets(input_buffer, sizeof(input_buffer), stdin);
bptr = input_buffer;
while (bptr[0] == ' ')
bptr++;
if ((bptr[0] == '0') && ((bptr[1] == 'x') || (bptr[1] == 'X')))
{
bptr += 2;
dec_flag = 0;
}
if (((bptr[0] >= '0') && (bptr[0] <= '9')) ||
((bptr[0] >= 'a') && (bptr[0] <= 'f')) ||
((bptr[0] >= 'A') && (bptr[0] <= 'F')))
{
while ((*bptr != 0) && (*bptr != 0xA) && (*bptr != 0xD))
{
if ((bptr[0] >= '0') && (bptr[0] <= '9'))
{
dec_value = (dec_value * 10) + (bptr[0] - '0');
hex_value = (hex_value * 16) + (bptr[0] - '0');
}
else
if ((bptr[0] >= 'a') && (bptr[0] <= 'f'))
{
dec_value = (dec_value * 10) + (bptr[0] - 'a') + 10;
hex_value = (hex_value * 16) + (bptr[0] - 'a') + 10;
dec_flag = 0;
}
else
if ((bptr[0] >= 'A') && (bptr[0] <= 'F'))
{
dec_value = (dec_value * 10) + (bptr[0] - 'A') + 10;
hex_value = (hex_value * 16) + (bptr[0] - 'A') + 10;
dec_flag = 0;
}
else
{
if (bptr[0] == ' ')
break;
return (-1);
}
bptr ++;
}
*new_value = (dec_flag == 0) ? hex_value : dec_value;
return (0);
}
return (-1);
}
// this function will allocate all available space on all disks as Netware
// partitions. NOTE: this function creates Netware 4.x/5.x style
// partitions.
ULONG NWAllocateUnpartitionedSpace(void)
{
ULONG disk, i, j, vhandle, raw_ids[4];
ULONG TotalSectors, FreeSectors, AdjustedSectors;
ULONG AllocatedSectors, freeSlots;
ULONG LBAStart, Length, LBAWork, LBAEnd;
BYTE *Buffer;
register ULONG retCode;
register PART_SIG *ps;
ULONG SlotCount;
ULONG SlotIndex;
ULONG SlotMask[4];
ULONG SlotLBA[4];
ULONG SlotLength[4];
ULONG FreeCount;
ULONG FreeLBA[4];
ULONG FreeLength[4];
ULONG FreeSlotIndex[4];
nwvp_rpartition_scan_info rlist[5];
nwvp_payload payload;
ULONG logical_capacity;
BYTE workBuffer[20] = {""};
if (FirstValidDisk == (ULONG)-1)
{
NWFSPrint("\nNo fixed disks could be located.\n");
return -1;
}
Buffer = NWFSIOAlloc(IO_BLOCK_SIZE, DISKBUF_TAG);
if (!Buffer)
{
NWFSPrint("could not allocate partition workspace\n");
return -1;
}
NWFSSet(Buffer, 0, IO_BLOCK_SIZE);
UtilScanVolumes();
NWFSPrint("Allocating all unpartitioned space for Netware 4.x/5.x\n");
for (disk=FirstValidDisk; disk < TotalDisks; disk++)
{
if ((SystemDisk[disk]) && (SystemDisk[disk]->PhysicalDiskHandle))
{
#if (VERBOSE)
NWFSPrint("disk found-%d total-%d\n", (int)disk, (int)TotalDisks);
#endif
// init the partition marker fields
for (i=0; i < 4; i++)
SystemDisk[disk]->PartitionFlags[i] = 0;
if (ValidatePartitionExtants(disk))
{
NWFSPrint("disk-(%d) partition table is invalid - reinitializing table\n",
(int)disk);
NWFSPrint("WARNING !!! this operation will erase all data on \nthis drive. Continue? [Y/N]: ");
fgets(workBuffer, sizeof(workBuffer), stdin);
if (toupper(workBuffer[0]) != 'Y')
goto ScanNextDisk;
retCode = ReadDiskSectors(disk, 0, Buffer, 1, 1);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d error reading boot sector\n", (int)disk);
goto ScanNextDisk;
}
NWFSCopy(&SystemDisk[disk]->partitionSignature, &Buffer[0x01FE], 2);
// if there is no valid partition signature, then
// write a new master boot record.
if (SystemDisk[disk]->partitionSignature != 0xAA55)
{
NWFSSet(Buffer, 0, 512);
NWFSCopy(Buffer, NetwareBootSector, sizeof(NetwareBootSector));
SystemDisk[disk]->partitionSignature = 0xAA55;
NWFSCopy(&Buffer[0x01FE], &SystemDisk[disk]->partitionSignature, 2);
}
// zero the partition table and partition signature
NWFSSet(&SystemDisk[disk]->PartitionTable[0].fBootable, 0, 64);
NWFSCopy(&Buffer[0x01BE], &SystemDisk[disk]->PartitionTable[0].fBootable, 64);
// write the partition table to sector 0
retCode = WriteDiskSectors(disk, 0, Buffer, 1, 1);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d error writing boot sector\n", (int)disk);
goto ScanNextDisk;
}
UtilScanVolumes();
}
//
//
//
TotalSectors = (ULONG)((SystemDisk[disk]->Cylinders) *
SystemDisk[disk]->TracksPerCylinder *
SystemDisk[disk]->SectorsPerTrack);
if (TotalSectors < SystemDisk[disk]->SectorsPerTrack)
{
NWFSPrint("nwfs: sector total range error\n");
goto ScanNextDisk;
}
// the first cylinder of all hard drives is reserved.
AdjustedSectors = (TotalSectors - SystemDisk[disk]->SectorsPerTrack);
// scan for free slots and count the total free sectors
// for this drive.
for (freeSlots = AllocatedSectors = 0, i = 0; i < 4; i++)
{
SlotMask[i] = 0;
SlotLBA[i] = 0;
SlotLength[i] = 0;
FreeLBA[i] = 0;
FreeLength[i] = 0;
if (SystemDisk[disk]->PartitionTable[i].SysFlag &&
SystemDisk[disk]->PartitionTable[i].nSectorsTotal &&
SystemDisk[disk]->PartitionTable[i].StartLBA)
{
AllocatedSectors +=
SystemDisk[disk]->PartitionTable[i].nSectorsTotal;
}
else
{
FreeSlotIndex[freeSlots] = i;
freeSlots++;
}
}
// now sort the partition table into ascending order
for (SlotCount = i = 0; i < 4; i++)
{
// look for the lowest starting lba
for (SlotIndex = LBAStart = (ULONG) -1, j = 0; j < 4; j++)
{
if (SystemDisk[disk]->PartitionTable[j].SysFlag &&
!SlotMask[j])
{
if (SystemDisk[disk]->PartitionTable[j].StartLBA < LBAStart)
{
LBAStart = SystemDisk[disk]->PartitionTable[j].StartLBA;
SlotIndex = j;
}
}
}
if (SlotIndex < 4)
{
SlotMask[SlotIndex] = TRUE;
SlotLBA[SlotCount] =
SystemDisk[disk]->PartitionTable[SlotIndex].StartLBA;
SlotLength[SlotCount] =
SystemDisk[disk]->PartitionTable[SlotIndex].nSectorsTotal;
SlotCount++;
}
}
// now determine how many contiguous free data areas are present
// and what their sizes are in sectors. we align the starting
// LBA and size to cylinder boundries.
LBAStart = SystemDisk[disk]->SectorsPerTrack;
for (FreeCount = i = 0; i < SlotCount; i++)
{
if (LBAStart < SlotLBA[i])
{
#if (TRUE_NETWARE_MODE)
// check if we are currently pointing to the
// first track on this device. If so, then
// we begin our first defined partition as SPT.
if (LBAStart == SystemDisk[disk]->SectorsPerTrack)
{
LBAWork = LBAStart;
FreeLBA[FreeCount] = LBAWork;
}
else
{
// round up to the next cylinder boundry
LBAWork = (((LBAStart +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
FreeLBA[FreeCount] = LBAWork;
}
#else
// round up to the next cylinder boundry
LBAWork = (((LBAStart +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
FreeLBA[FreeCount] = LBAWork;
#endif
// adjust length to correspond to cylinder boundries
LBAEnd = (((SlotLBA[i] +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
// if we rounded into the next partition, then adjust
// the ending LBA to the beginning of the next partition.
if (LBAEnd > SlotLBA[i])
LBAEnd = SlotLBA[i];
// if we rounded off the end of the device, then adjust
// the ending LBA to the total sector count for the device.
if (LBAEnd > TotalSectors)
LBAEnd = TotalSectors;
Length = LBAEnd - LBAWork;
FreeLength[FreeCount] = Length;
FreeCount++;
}
LBAStart = (SlotLBA[i] + SlotLength[i]);
}
// determine how much free space exists less that claimed
// by the partition table after we finish scanning. this
// case is the fall through case when the partition table
// is empty.
if (LBAStart < TotalSectors)
{
#if (TRUE_NETWARE_MODE)
// check if we are currently pointing to the
// first track on this device. If so, then
// we begin our first defined partition as SPT.
if (LBAStart == SystemDisk[disk]->SectorsPerTrack)
{
LBAWork = LBAStart;
FreeLBA[FreeCount] = LBAWork;
}
else
{
// round up to the next cylinder boundry
LBAWork = (((LBAStart +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
FreeLBA[FreeCount] = LBAWork;
}
#else
// round up to the next cylinder boundry
LBAWork = (((LBAStart +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
FreeLBA[FreeCount] = LBAWork;
#endif
// adjust length to correspond to cylinder boundries
LBAEnd = (((TotalSectors +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
// if we rounded off the end of the device, then adjust
// the ending LBA to the total sector cout for the device.
if (LBAEnd > TotalSectors)
LBAEnd = TotalSectors;
Length = LBAEnd - LBAWork;
FreeLength[FreeCount] = Length;
FreeCount++;
}
else
if (LBAStart > TotalSectors)
{
// if LBAStart is greater than the TotalSectors for this
// device, then we have an error in the disk geometry
// dimensions and they are invalid.
goto ScanNextDisk;
}
#if (VERBOSE)
NWFSPrint("disk-%d slot_count-%d free_count-%d slot_index-%d\n",
(int)disk, (int)SlotCount, (int)FreeCount,
(int)SlotIndex);
for (i=0; i < SlotCount; i++)
{
NWFSPrint("part-#%d LBA-%08X Length-%08X Mask-%d\n",
(int)i,
(unsigned int)SlotLBA[i],
(unsigned int)SlotLength[i],
(int)SlotMask[i]);
}
for (i=0; i < FreeCount; i++)
{
NWFSPrint("free-#%d LBA-%08X Length-%08X\n",
(int)i,
(unsigned int)FreeLBA[i],
(unsigned int)FreeLength[i]);
}
#endif
// drive geometry range error or partition table data error,
// abort the operation
if (AdjustedSectors < AllocatedSectors)
{
NWFSPrint("nwfs: drive geometry range error\n");
goto ScanNextDisk;
}
// if there are no free sectors, then abort the operation
FreeSectors = (AdjustedSectors - AllocatedSectors);
if (!FreeSectors)
goto ScanNextDisk;
// if there were no free slots, then abort the operation
if (!freeSlots)
goto ScanNextDisk;
// make certain we have at least 10 MB of free space
// available or abort the operation. don't allow the
// creation of a Netware partition that is smaller than
// 10 MB.
if (FreeSectors < 20480)
goto ScanNextDisk;
// now allocate all available free space on this device
// to Netware. if there are multiple contiguous
// free areas on the device, and free slots in
// the partition table, then continue to allocate
// Netware partitions until we have exhausted the
// space on this device, or we have run out of
// free slots in the partition table.
for (i=0; (i < FreeCount) && freeSlots; i++)
{
// get the first free slot available
j = FreeSlotIndex[0];
SetPartitionTableValues(
&SystemDisk[disk]->PartitionTable[j],
NETWARE_386_ID,
FreeLBA[i],
(FreeLBA[i] + FreeLength[i]) - 1,
0,
SystemDisk[disk]->TracksPerCylinder,
SystemDisk[disk]->SectorsPerTrack);
// validate partition extants
if (ValidatePartitionExtants(disk))
{
NWFSPrint("partition table entry (%d) is invalid\n", (int)j);
goto ScanNextDisk;
}
SystemDisk[disk]->PartitionFlags[j] = TRUE;
NWFSPrint("Netware Partition disk-%d:(%d) LBA-%08X size-%08X (%5dMB) Created\n",
(int)disk, (int)j,
(unsigned int)SystemDisk[disk]->PartitionTable[j].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[j].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[j].nSectorsTotal
* (LONGLONG)SystemDisk[disk]->BytesPerSector)
/ (LONGLONG)0x100000));
}
NWFSPrint("Updating BOOT Sector disk-(%d)\n", (int)disk);
retCode = ReadDiskSectors(disk, 0, Buffer, 1, 1);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d error reading boot sector\n", (int)disk);
goto ScanNextDisk;
}
NWFSCopy(&SystemDisk[disk]->partitionSignature, &Buffer[0x01FE], 2);
// if there is no valid partition signature, then
// write a new master boot record
if (SystemDisk[disk]->partitionSignature != 0xAA55)
{
NWFSSet(Buffer, 0, 512);
NWFSCopy(Buffer, NetwareBootSector, sizeof(NetwareBootSector));
SystemDisk[disk]->partitionSignature = 0xAA55;
NWFSCopy(&Buffer[0x01FE], &SystemDisk[disk]->partitionSignature, 2);
}
// copy the partition table and partition signature
NWFSCopy(&Buffer[0x01BE], &SystemDisk[disk]->PartitionTable[0].fBootable, 64);
// write the partition table to sector 0
retCode = WriteDiskSectors(disk, 0, Buffer, 1, 1);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d error writing boot sector\n", (int)disk);
goto ScanNextDisk;
}
// if any of the partitions are being newly created, then
// read in their partition boot sectors and write out a valid
// Netware partition stamp. We create partitions in
// Netware 5.x format.
for (i=0; i < 4; i++)
{
if ((SystemDisk[disk]->PartitionFlags[i]) &&
(SystemDisk[disk]->PartitionTable[i].SysFlag == 0x65) &&
(SystemDisk[disk]->PartitionTable[i].nSectorsTotal) &&
(SystemDisk[disk]->PartitionTable[i].StartLBA))
{
NWFSPrint("Formating Netware Partition disk-%d LBA-%08X size-%08X (%5dMB)\n",
(int)disk,
(unsigned int)SystemDisk[disk]->PartitionTable[i].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[i].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[j].nSectorsTotal
* (LONGLONG)SystemDisk[disk]->BytesPerSector)
/ (LONGLONG)0x100000));
retCode = ReadDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA,
Buffer, 1, 1);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d error reading part sector\n", (int)disk);
goto ScanNextDisk;
}
NWFSSet(Buffer, 0, IO_BLOCK_SIZE);
ps = (PART_SIG *) Buffer;
// create partition sector 0
NWFSCopy(ps->NetwareSignature, NwPartSignature, 16);
ps->PartitionType = TYPE_SIGNATURE;
ps->PartitionSize = SystemDisk[disk]->PartitionTable[i].nSectorsTotal;
ps->CreationDateAndTime = NWFSSystemToNetwareTime(NWFSGetSystemTime());
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA,
Buffer, 1, 1);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
goto ScanNextDisk;
}
// write a netware boot sector to sector 1 on this
// partition along with a complete copy of the
// partition table for this drive.
NWFSSet(Buffer, 0, 512);
// create partition sector 1
NWFSCopy(Buffer, NetwareBootSector, sizeof(NetwareBootSector));
SystemDisk[disk]->partitionSignature = 0xAA55;
NWFSCopy(&Buffer[0x01FE], &SystemDisk[disk]->partitionSignature, 2);
NWFSCopy(&Buffer[0x01BE], &SystemDisk[disk]->PartitionTable[0].fBootable, 64);
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 1,
Buffer, 1, 1);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
goto ScanNextDisk;
}
// zero out the partition hotfix and mirror tables
// hotfix 0
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x20,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
goto ScanNextDisk;
}
// mirror 0
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x21,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
goto ScanNextDisk;
}
// hotfix 1
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x40,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
goto ScanNextDisk;
}
// mirror 1
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x41,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
goto ScanNextDisk;
}
// hotfix 2
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x60,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
goto ScanNextDisk;
}
// mirror 2
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x61,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
goto ScanNextDisk;
}
// hotfix 3
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x80,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
goto ScanNextDisk;
}
// mirror 3
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x81,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
goto ScanNextDisk;
}
}
SystemDisk[disk]->PartitionFlags[i] = 0;
}
UtilScanVolumes();
payload.payload_object_count = 0;
payload.payload_index = 0;
payload.payload_object_size_buffer_size = (sizeof(nwvp_rpartition_scan_info) << 20) + sizeof(rlist);
payload.payload_buffer = (BYTE *) &rlist[0];
do
{
nwvp_rpartition_scan(&payload);
for (j=0; j < payload.payload_object_count; j++)
{
if ((rlist[j].lpart_handle == 0xFFFFFFFF) && ((rlist[j].partition_type == 0x65) || (rlist[j].partition_type ==0x77)))
{
logical_capacity = (rlist[j].physical_block_count & 0xFFFFFF00) - 242;
raw_ids[0] = rlist[j].rpart_handle;
raw_ids[1] = 0xFFFFFFFF;
raw_ids[2] = 0xFFFFFFFF;
raw_ids[3] = 0xFFFFFFFF;
nwvp_lpartition_format(&vhandle, logical_capacity, &raw_ids[0]);
}
}
} while ((payload.payload_index != 0) && (payload.payload_object_count != 0));
}
SyncDevice((ULONG)SystemDisk[disk]->PhysicalDiskHandle);
ScanNextDisk:;
}
NWFSFree(Buffer);
UtilScanVolumes();
WaitForKey();
return 0;
}
void NWEditPartitions(void)
{
ULONG CurrentDisk = 0;
ULONG selected, disk, i, r, j, vhandle, raw_ids[4];
ULONG TotalSectors, FreeSectors, AdjustedSectors;
ULONG AllocatedSectors;
ULONG LBAStart, LBAEnd, Length, freeSlots, targetSize;
BYTE *Buffer;
ULONG retCode;
nwvp_rpartition_scan_info rlist[5];
nwvp_payload payload;
ULONG logical_capacity;
BYTE inputBuffer[20] = { "" };
BYTE workBuffer[20] = { "" };
register PART_SIG *ps;
ULONG SlotCount;
ULONG SlotIndex;
ULONG SlotMask[4];
ULONG SlotLBA[4];
ULONG SlotLength[4];
ULONG FreeCount;
ULONG FreeLBA[4];
ULONG FreeLength[4];
ULONG FreeSlotIndex[4];
ULONG LBAWork;
ULONG MaxLBA;
ULONG MaxLength;
ULONG MaxSlot;
if (FirstValidDisk == (ULONG)-1)
{
NWFSPrint("\nNo fixed disks could be located. press ...\n");
WaitForKey();
return;
}
CurrentDisk = FirstValidDisk;
Buffer = NWFSIOAlloc(IO_BLOCK_SIZE, DISKBUF_TAG);
if (!Buffer)
{
NWFSPrint("could not allocate partition workspace\n");
WaitForKey();
return;
}
NWFSSet(Buffer, 0, IO_BLOCK_SIZE);
UtilScanVolumes();
// init the partition marker field for this device
disk = CurrentDisk;
if ((SystemDisk[disk]) && (SystemDisk[disk]->PhysicalDiskHandle))
{
for (i=0; i < 4; i++)
SystemDisk[disk]->PartitionFlags[i] = 0;
}
while (TRUE)
{
ClearScreen(consoleHandle);
NWFSPrint("NetWare Partition Manager\n");
NWFSPrint("Copyright (c) 1999, 2000 Jeff V. Merkey All Rights Reserved.\n");
disk = CurrentDisk;
if (ValidatePartitionExtants(disk))
{
NWFSPrint("\ndisk-(%d) partition table is invalid\n", (int)disk);
}
if ((SystemDisk[disk]) && (SystemDisk[disk]->PhysicalDiskHandle))
{
#if (LINUX_UTIL)
extern BYTE *PhysicalDiskNames[];
NWFSPrint("\n **** Disk #%d %s (%02X:%02X) Sectors 0x%X ****\n",
(int)disk,
PhysicalDiskNames[disk],
(unsigned)((ULONG)SystemDisk[disk]->PhysicalDiskHandle & 0xFF),
(unsigned)((ULONG)SystemDisk[disk]->PhysicalDiskHandle >> 8),
(unsigned int)((SystemDisk[disk]->Cylinders) *
SystemDisk[disk]->TracksPerCylinder *
SystemDisk[disk]->SectorsPerTrack));
#else
NWFSPrint("\n **** Disk #%d Sectors 0x%X ****\n",
(int)disk,
(unsigned int)((SystemDisk[disk]->Cylinders) *
SystemDisk[disk]->TracksPerCylinder *
SystemDisk[disk]->SectorsPerTrack));
#endif
NWFSPrint("Cylinders : %12u ", (unsigned int)SystemDisk[disk]->Cylinders);
NWFSPrint("Tracks/Cylinder : %12u\n", (unsigned int)SystemDisk[disk]->TracksPerCylinder);
NWFSPrint("SectorsPerTrack : %12u ", (unsigned int)SystemDisk[disk]->SectorsPerTrack);
NWFSPrint("BytesPerSector : %12u\n", (unsigned int)SystemDisk[disk]->BytesPerSector);
NWFSPrint("DriveSize : %12.0f\n", (double)SystemDisk[disk]->driveSize);
NWFSPrint("\n");
if (!ValidatePartitionExtants(disk))
{
for (r=0; r < 4; r++)
{
if ((SystemDisk[disk]->PartitionTable[r].SysFlag) &&
(SystemDisk[disk]->PartitionTable[r].nSectorsTotal))
{
if (SystemDisk[disk]->PartitionTable[r].SysFlag == NETWARE_386_ID)
NWFSPrint("#%d %s LBA: 0x%08X Sectors: 0x%08X %5uMB %s %s\n",
(int)(r + 1),
SystemDisk[disk]->PartitionTable[r].fBootable ? "A" : " ",
(unsigned int)SystemDisk[disk]->PartitionTable[r].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[r].nSectorsTotal,
(unsigned int)
((((LONGLONG)SystemDisk[disk]->PartitionTable[r].nSectorsTotal *
(LONGLONG)SystemDisk[disk]->BytesPerSector)) /
(LONGLONG)0x100000),
get_partition_type(SystemDisk[disk]->PartitionTable[r].SysFlag),
(SystemDisk[disk]->PartitionVersion[r]
? "3.x"
: "4.x/5.x"));
else
NWFSPrint("#%d %s LBA: 0x%08X Sectors: 0x%08X %5uMB %s\n",
(int)(r + 1),
SystemDisk[disk]->PartitionTable[r].fBootable ? "A" : " ",
(unsigned int)SystemDisk[disk]->PartitionTable[r].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[r].nSectorsTotal,
(unsigned int)
((((LONGLONG)SystemDisk[disk]->PartitionTable[r].nSectorsTotal *
(LONGLONG)SystemDisk[disk]->BytesPerSector)) /
(LONGLONG)0x100000),
get_partition_type(SystemDisk[disk]->PartitionTable[r].SysFlag));
}
else
NWFSPrint("#%d ------------- Unused ------------- \n", (int)(r + 1));
}
}
}
NWFSPrint("\n");
NWFSPrint(" 1. Apply Partition Table Changes\n");
NWFSPrint(" 2. Select Fixed Disk\n");
NWFSPrint(" 3. Create Netware 3.x Partition\n");
NWFSPrint(" 4. Create Netware 4.x/5.x Partition\n");
NWFSPrint(" 5. Set Active Partition\n");
NWFSPrint(" 6. Delete Partition\n");
NWFSPrint(" 7. Initialize Partition Table\n");
NWFSPrint(" 8. Assign All Free Space to NetWare\n");
NWFSPrint(" 9. Return\n");
NWFSPrint(" Enter a Menu Option: ");
fgets(inputBuffer, sizeof(inputBuffer), stdin);
switch (inputBuffer[0])
{
case '1':
ClearScreen(consoleHandle);
disk = CurrentDisk;
if ((!SystemDisk[disk]) || (!SystemDisk[disk]->PhysicalDiskHandle))
break;
NWFSPrint("WARNING !!! this operation will overwrite the partition table on \nthis drive.\n");
NWFSPrint("\n **** Disk #%d Total Sectors 0x%X ****\n",
(int)disk,
(unsigned int)((SystemDisk[disk]->Cylinders) *
SystemDisk[disk]->TracksPerCylinder *
SystemDisk[disk]->SectorsPerTrack));
for (r=0; r < 4; r++)
{
if ((SystemDisk[disk]->PartitionTable[r].SysFlag) &&
(SystemDisk[disk]->PartitionTable[r].nSectorsTotal))
{
if (SystemDisk[disk]->PartitionTable[r].SysFlag == NETWARE_386_ID)
NWFSPrint("#%d %s LBA: 0x%08X Sectors: 0x%08X %5uMB %s %s\n",
(int)(r + 1),
SystemDisk[disk]->PartitionTable[r].fBootable ? "A" : " ",
(unsigned int)SystemDisk[disk]->PartitionTable[r].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[r].nSectorsTotal,
(unsigned int)
((((LONGLONG)SystemDisk[disk]->PartitionTable[r].nSectorsTotal *
(LONGLONG)SystemDisk[disk]->BytesPerSector)) /
(LONGLONG)0x100000),
get_partition_type(SystemDisk[disk]->PartitionTable[r].SysFlag),
(SystemDisk[disk]->PartitionVersion[r]
? "3.x"
: "4.x/5.x"));
else
NWFSPrint("#%d %s LBA: 0x%08X Sectors: 0x%08X %5uMB %s\n",
(int)(r + 1),
SystemDisk[disk]->PartitionTable[r].fBootable ? "A" : " ",
(unsigned int)SystemDisk[disk]->PartitionTable[r].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[r].nSectorsTotal,
(unsigned int)
((((LONGLONG)SystemDisk[disk]->PartitionTable[r].nSectorsTotal *
(LONGLONG)SystemDisk[disk]->BytesPerSector)) /
(LONGLONG)0x100000),
get_partition_type(SystemDisk[disk]->PartitionTable[r].SysFlag));
}
else
NWFSPrint("#%d ------------- Unused ------------- \n", (int)(r + 1));
}
NWFSPrint("\nContinue and write this partition table ? [Y/N]: ");
fgets(workBuffer, sizeof(workBuffer), stdin);
if (toupper(workBuffer[0]) != 'Y')
break;
NWFSPrint("Updating BOOT Sector disk-(%d)\n", (int)disk);
retCode = ReadDiskSectors(disk, 0, Buffer, 1, 1);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d error reading boot sector\n", (int)disk);
break;
}
NWFSCopy(&SystemDisk[disk]->partitionSignature, &Buffer[0x01FE], 2);
// if there is no valid partition signature, then
// write a new master boot record
if (SystemDisk[disk]->partitionSignature != 0xAA55)
{
NWFSSet(Buffer, 0, 512);
NWFSCopy(Buffer, NetwareBootSector, sizeof(NetwareBootSector));
SystemDisk[disk]->partitionSignature = 0xAA55;
NWFSCopy(&Buffer[0x01FE], &SystemDisk[disk]->partitionSignature, 2);
}
// copy the partition table and partition signature
NWFSCopy(&Buffer[0x01BE], &SystemDisk[disk]->PartitionTable[0].fBootable, 64);
// write the partition table to sector 0
retCode = WriteDiskSectors(disk, 0, Buffer, 1, 1);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d error writing boot sector\n", (int)disk);
break;
}
// if any of the partitions are being newly created, then
// read in their partition boot sectors and write out a valid
// Netware partition stamp. We create partitions in
// Netware 3.x and 4.x/5.x formats.
for (i=0; i < 4; i++)
{
if ((SystemDisk[disk]->PartitionFlags[i]) &&
(SystemDisk[disk]->PartitionTable[i].SysFlag == 0x65) &&
(SystemDisk[disk]->PartitionTable[i].nSectorsTotal) &&
(SystemDisk[disk]->PartitionTable[i].StartLBA))
{
if (SystemDisk[disk]->PartitionVersion[i] == NW4X_PARTITION)
{
NWFSPrint("Formating Netware 4.x/5.x Partition (%d)-LBA-%08X size-%08X (%5dMB)\n",
(int)disk,
(unsigned int)SystemDisk[disk]->PartitionTable[i].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[i].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[i].nSectorsTotal
* (LONGLONG)SystemDisk[disk]->BytesPerSector)
/ (LONGLONG)0x100000));
retCode = ReadDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA,
Buffer, 1, 1);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d error reading part sector\n", (int)disk);
break;
}
NWFSSet(Buffer, 0, IO_BLOCK_SIZE);
ps = (PART_SIG *) Buffer;
// create partition sector 0
NWFSCopy(ps->NetwareSignature, NwPartSignature, 16);
ps->PartitionType = TYPE_SIGNATURE;
ps->PartitionSize = SystemDisk[disk]->PartitionTable[i].nSectorsTotal;
ps->CreationDateAndTime = NWFSSystemToNetwareTime(NWFSGetSystemTime());
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA,
Buffer, 1, 1);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// write a Netware boot sector to sector 1 on this
// partition along with a complete copy of the
// partition table for this drive.
NWFSSet(Buffer, 0, 512);
// create partition sector 1
NWFSCopy(Buffer, NetwareBootSector, sizeof(NetwareBootSector));
SystemDisk[disk]->partitionSignature = 0xAA55;
NWFSCopy(&Buffer[0x01FE], &SystemDisk[disk]->partitionSignature, 2);
NWFSCopy(&Buffer[0x01BE], &SystemDisk[disk]->PartitionTable[0].fBootable, 64);
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 1,
Buffer, 1, 1);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// zero out the partition hotfix and mirror tables
// hotfix 0
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x20,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// mirror 0
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x21,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// hotfix 1
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x40,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// mirror 1
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x41,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// hotfix 2
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x60,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// mirror 2
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x61,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// hotfix 3
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x80,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// mirror 3
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x81,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
}
else
if (SystemDisk[disk]->PartitionVersion[i] == NW3X_PARTITION)
{
NWFSPrint("Formating Netware 3.x Partition (%d)-LBA-%08X size-%08X (%5dMB)\n",
(int)disk,
(unsigned int)SystemDisk[disk]->PartitionTable[i].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[i].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[i].nSectorsTotal
* (LONGLONG)SystemDisk[disk]->BytesPerSector)
/ (LONGLONG)0x100000));
retCode = ReadDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA,
Buffer, 1, 1);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d error reading part sector\n", (int)disk);
break;
}
// zero 3.x partition sector 0
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA,
ZeroBuffer, 1, 1);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// zero 3.x partition sector 1
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 1,
ZeroBuffer, 1, 1);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// zero out the partition hotfix and mirror tables
// hotfix 0
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x20,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// mirror 0
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x21,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// hotfix 1
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x40,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// mirror 1
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x41,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// hotfix 2
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x60,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// mirror 2
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x61,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// hotfix 3
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x80,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
// mirror 3
retCode = WriteDiskSectors(disk,
SystemDisk[disk]->PartitionTable[i].StartLBA + 0x81,
ZeroBuffer,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector,
IO_BLOCK_SIZE / SystemDisk[disk]->BytesPerSector);
if (!retCode)
{
NWFSPrint("FATAL: disk-%d hotfix/mirror init error\n", (int)disk);
break;
}
}
else
NWFSPrint("FATAL: disk-%d could not determine partition version\n", (int)disk);
}
SystemDisk[disk]->PartitionFlags[i] = 0;
}
UtilScanVolumes();
payload.payload_object_count = 0;
payload.payload_index = 0;
payload.payload_object_size_buffer_size = (sizeof(nwvp_rpartition_scan_info) << 20) + sizeof(rlist);
payload.payload_buffer = (BYTE *) &rlist[0];
do
{
nwvp_rpartition_scan(&payload);
for (j=0; j< payload.payload_object_count; j++)
{
if ((rlist[j].lpart_handle == 0xFFFFFFFF) && ((rlist[j].partition_type == 0x65) || (rlist[j].partition_type == 0x77)))
{
logical_capacity = (rlist[j].physical_block_count & 0xFFFFFF00) - 242;
raw_ids[0] = rlist[j].rpart_handle;
raw_ids[1] = 0xFFFFFFFF;
raw_ids[2] = 0xFFFFFFFF;
raw_ids[3] = 0xFFFFFFFF;
nwvp_lpartition_format(&vhandle, logical_capacity, &raw_ids[0]);
}
}
} while ((payload.payload_index != 0) && (payload.payload_object_count != 0));
SyncDevice((ULONG)SystemDisk[disk]->PhysicalDiskHandle);
WaitForKey();
break;
case '2':
ClearScreen(consoleHandle);
NWFSPrint("Current Disk is Setting is (%d) [", (int)CurrentDisk);
for (i=0; i < MAX_DISKS; i++)
{
if ((SystemDisk[i]) && (SystemDisk[i]->PhysicalDiskHandle))
{
if (!i)
NWFSPrint("%d", (int)i);
else
NWFSPrint(", %d", (int)i);
}
}
NWFSPrint("]\n\n");
NWFSPrint("Enter New Disk Number: ");
fgets(workBuffer, sizeof(workBuffer), stdin);
disk = atoi(workBuffer);
if (disk < MAX_DISKS && SystemDisk[disk] &&
SystemDisk[disk]->PhysicalDiskHandle)
{
NWFSPrint("\nCurrentDisk(%u) Set to (%u)\n",
(unsigned int)CurrentDisk, (unsigned int)disk);
// init the partition marker field for this device
CurrentDisk = disk;
for (i=0; i < 4; i++)
SystemDisk[disk]->PartitionFlags[i] = 0;
WaitForKey();
}
else
{
NWFSPrint("\nInvalid Disk (%u) Specified\n", (unsigned int)disk);
WaitForKey();
}
break;
case '3':
ClearScreen(consoleHandle);
disk = CurrentDisk;
if ((SystemDisk[disk]) && (SystemDisk[disk]->PhysicalDiskHandle))
{
TotalSectors = (ULONG)((SystemDisk[disk]->Cylinders) *
SystemDisk[disk]->TracksPerCylinder *
SystemDisk[disk]->SectorsPerTrack);
if (TotalSectors < SystemDisk[disk]->SectorsPerTrack)
{
NWFSPrint("nwfs: sector total range error\n");
WaitForKey();
break;
}
NWFSPrint("\n*** Disk Device (%d) Sectors %X ***\n",
(int)disk,(unsigned int)TotalSectors);
// assume the first cylinder of all hard drives is reserved.
AdjustedSectors = (TotalSectors - SystemDisk[disk]->SectorsPerTrack);
// scan for free slots and count the total free sectors
// for this drive.
for (freeSlots = AllocatedSectors = 0, i = 0; i < 4; i++)
{
SlotMask[i] = 0;
SlotLBA[i] = 0;
SlotLength[i] = 0;
FreeLBA[i] = 0;
FreeLength[i] = 0;
if (SystemDisk[disk]->PartitionTable[i].SysFlag &&
SystemDisk[disk]->PartitionTable[i].nSectorsTotal &&
SystemDisk[disk]->PartitionTable[i].StartLBA)
{
AllocatedSectors +=
SystemDisk[disk]->PartitionTable[i].nSectorsTotal;
if (SystemDisk[disk]->PartitionTable[i].SysFlag == NETWARE_386_ID)
NWFSPrint("#%d %s LBA: 0x%08X Sectors: 0x%08X %5uMB %s %s\n",
(int) i + 1,
SystemDisk[disk]->PartitionTable[i].fBootable
? "A" : " ",
(unsigned int)SystemDisk[disk]->PartitionTable[i].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[i].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[i].nSectorsTotal *
(LONGLONG)SystemDisk[disk]->BytesPerSector) /
(LONGLONG)0x100000),
get_partition_type(SystemDisk[disk]->PartitionTable[i].SysFlag),
(SystemDisk[disk]->PartitionVersion[i]
? "3.x" : "4.x/5.x"));
else
NWFSPrint("#%d %s LBA: 0x%08X Sectors: 0x%08X %5uMB %s\n",
(int) i + 1,
SystemDisk[disk]->PartitionTable[i].fBootable
? "A" : " ",
(unsigned int)SystemDisk[disk]->PartitionTable[i].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[i].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[i].nSectorsTotal *
(LONGLONG)SystemDisk[disk]->BytesPerSector) /
(LONGLONG)0x100000),
get_partition_type(SystemDisk[disk]->PartitionTable[i].SysFlag));
}
else
{
FreeSlotIndex[freeSlots] = i;
freeSlots++;
NWFSPrint("#%d ------------- Unused ------------- \n", (int) i + 1);
}
}
// now sort the partition table into ascending order
for (SlotCount = i = 0; i < 4; i++)
{
// look for the lowest starting lba
for (SlotIndex = LBAStart = (ULONG) -1, j = 0; j < 4; j++)
{
if (SystemDisk[disk]->PartitionTable[j].SysFlag &&
!SlotMask[j])
{
if (SystemDisk[disk]->PartitionTable[j].StartLBA <
LBAStart)
{
LBAStart = SystemDisk[disk]->PartitionTable[j].StartLBA;
SlotIndex = j;
}
}
}
if (SlotIndex < 4)
{
SlotMask[SlotIndex] = TRUE;
SlotLBA[SlotCount] =
SystemDisk[disk]->PartitionTable[SlotIndex].StartLBA;
SlotLength[SlotCount] =
SystemDisk[disk]->PartitionTable[SlotIndex].nSectorsTotal;
SlotCount++;
}
}
// now determine how many contiguous free data areas are
// present and what their sizes are in sectors. we align
// the starting LBA and size to cylinder boundries.
LBAStart = SystemDisk[disk]->SectorsPerTrack;
for (FreeCount = i = 0; i < SlotCount; i++)
{
if (LBAStart < SlotLBA[i])
{
// check if we are currently pointing to the
// first track on this device. If so, then
// we begin our first defined partition on the
// first track of the device.
if (LBAStart == SystemDisk[disk]->SectorsPerTrack)
{
LBAWork = LBAStart;
FreeLBA[FreeCount] = LBAWork;
}
else
{
// round up to the next cylinder boundry
LBAWork = (((LBAStart +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
FreeLBA[FreeCount] = LBAWork;
}
// adjust length to correspond to cylinder boundries
LBAEnd = (((SlotLBA[i] +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
// if we rounded into the next partition, then adjust
// the ending LBA to the beginning of the next partition.
if (LBAEnd > SlotLBA[i])
LBAEnd = SlotLBA[i];
// if we rounded off the end of the device, then adjust
// the ending LBA to the total sector cout for the device.
if (LBAEnd > TotalSectors)
LBAEnd = TotalSectors;
Length = LBAEnd - LBAWork;
FreeLength[FreeCount] = Length;
FreeCount++;
}
LBAStart = (SlotLBA[i] + SlotLength[i]);
}
// determine how much free space exists less that claimed
// by the partition table after we finish scanning. this
// case is the fall through case when the partition table
// is empty.
if (LBAStart < TotalSectors)
{
#if (TRUE_NETWARE_MODE)
// check if we are currently pointing to the
// first track on this device. If so, then
// we begin our first defined partition as SPT.
if (LBAStart == SystemDisk[disk]->SectorsPerTrack)
{
LBAWork = LBAStart;
FreeLBA[FreeCount] = LBAWork;
}
else
{
// round up to the next cylinder boundry
LBAWork = (((LBAStart +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
FreeLBA[FreeCount] = LBAWork;
}
#else
// round up to the next cylinder boundry
LBAWork = (((LBAStart +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
FreeLBA[FreeCount] = LBAWork;
#endif
// adjust length to correspond to cylinder boundries
LBAEnd = (((TotalSectors +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
// if we rounded off the end of the device, then adjust
// the ending LBA to the total sector cout for the device.
if (LBAEnd > TotalSectors)
LBAEnd = TotalSectors;
Length = LBAEnd - LBAWork;
FreeLength[FreeCount] = Length;
FreeCount++;
}
else
if (LBAStart > TotalSectors)
{
// if LBAStart is greater than the TotalSectors for this
// device, then we have an error in the disk geometry
// dimensions and they are invalid.
WaitForKey();
break;
}
#if (VERBOSE)
NWFSPrint("disk-%d slot_count-%d free_count-%d slot_index-%d\n",
(int)disk, (int)SlotCount, (int)FreeCount,
(int)SlotIndex);
for (i=0; i < SlotCount; i++)
{
NWFSPrint("part-#%d LBA-%08X Length-%08X Mask-%d\n",
(int)i,
(unsigned int)SlotLBA[i],
(unsigned int)SlotLength[i],
(int)SlotMask[i]);
}
for (i=0; i < FreeCount; i++)
{
NWFSPrint("free-#%d LBA-%08X Length-%08X\n",
(int)i,
(unsigned int)FreeLBA[i],
(unsigned int)FreeLength[i]);
}
#endif
// drive geometry range error or partition table data error,
// abort the operation
if (AdjustedSectors < AllocatedSectors)
{
NWFSPrint("\n *** drive geometry range error ***\n");
WaitForKey();
break;
}
// if there are no free sectors, then abort the operation
FreeSectors = (AdjustedSectors - AllocatedSectors);
NWFSPrint("\ndata sectors : %12.0f bytes (%08X sectors)\n",
(double) ((LONGLONG)SystemDisk[disk]->BytesPerSector *
(LONGLONG)AdjustedSectors),
(unsigned int) AdjustedSectors);
NWFSPrint("reserved sectors : %12.0f bytes (%08X sectors)\n",
(double) ((LONGLONG)SystemDisk[disk]->BytesPerSector *
(LONGLONG)SystemDisk[disk]->SectorsPerTrack),
(unsigned int) SystemDisk[disk]->SectorsPerTrack);
NWFSPrint("%12.0f bytes (%X sectors) are currently free\n",
(double) ((LONGLONG)SystemDisk[disk]->BytesPerSector *
(LONGLONG)FreeSectors),
(unsigned int) FreeSectors);
if (!FreeSectors)
{
NWFSPrint("\n *** No logical space left on device ***\n");
WaitForKey();
break;
}
// if there were no free slots, then abort the operation
if (!freeSlots)
{
NWFSPrint("\n *** No partition table entries available on device ***\n");
WaitForKey();
break;
}
// make certain we have at least 10 MB of free space
// available or abort the operation. don't allow the
// creation of a Netware partition that is smaller than
// 10 MB.
if (FreeSectors < 20480)
{
NWFSPrint("\n *** you must have at least 10 MB of free space ***\n");
WaitForKey();
break;
}
// determine which entry has the single largest area of
// contiguous setors for this device.
for (MaxSlot = MaxLBA = MaxLength = i = 0;
i < FreeCount; i++)
{
if (FreeLength[i] > MaxLength)
{
MaxLBA = FreeLBA[i];
MaxLength = FreeLength[i];
}
}
NWFSPrint("\nAllocate all contiguous free space for NetWare 3.x? (%5uMB) [Y/N]: ",
(unsigned int)
(((LONGLONG)SystemDisk[disk]->BytesPerSector *
(LONGLONG)MaxLength) /
(LONGLONG)0x100000));
fgets(workBuffer, sizeof(workBuffer), stdin);
if (toupper(workBuffer[0]) == 'Y')
{
// get the first free slot available
j = FreeSlotIndex[0];
SetPartitionTableValues(
&SystemDisk[disk]->PartitionTable[j],
NETWARE_386_ID,
MaxLBA,
(MaxLBA + MaxLength) - 1,
0,
SystemDisk[disk]->TracksPerCylinder,
SystemDisk[disk]->SectorsPerTrack);
// validate partition extants
if (ValidatePartitionExtants(disk))
{
NWFSPrint("partition table entry (%d) is invalid\n", (int)j);
WaitForKey();
break;
}
SystemDisk[disk]->PartitionFlags[j] = TRUE;
SystemDisk[disk]->PartitionVersion[j] = NW3X_PARTITION;
NWFSPrint("Netware 3.x Partition (%d:%d) LBA-%08X size-%08X (%5dMB) Created\n",
(int)disk, (int)j,
(unsigned int)SystemDisk[disk]->PartitionTable[j].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[j].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[j].nSectorsTotal
* (LONGLONG)SystemDisk[disk]->BytesPerSector)
/ (LONGLONG)0x100000));
WaitForKey();
break;
}
while (TRUE)
{
NWFSPrint("\nEnter NetWare 3.x Partition Size in MB (up to %uMB): ",
(unsigned int)
(((LONGLONG)SystemDisk[disk]->BytesPerSector *
(LONGLONG)MaxLength) /
(LONGLONG)0x100000));
fgets(workBuffer, sizeof(workBuffer), stdin);
targetSize = atol(workBuffer);
if (!targetSize)
break;
if ((targetSize <= (ULONG)
(((LONGLONG)SystemDisk[disk]->BytesPerSector *
(LONGLONG)MaxLength) /
(LONGLONG)0x100000))
&& (targetSize >= 10))
break;
}
if (targetSize)
{
// convert bytes to sectors
MaxLength = (ULONG)(((LONGLONG)targetSize *
(LONGLONG)0x100000) /
(LONGLONG)SystemDisk[disk]->BytesPerSector);
// cylinder align the requested size
MaxLength = (((MaxLength +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
// get the first free slot available
j = FreeSlotIndex[0];
SetPartitionTableValues(
&SystemDisk[disk]->PartitionTable[j],
NETWARE_386_ID,
MaxLBA,
(MaxLBA + MaxLength) - 1,
0,
SystemDisk[disk]->TracksPerCylinder,
SystemDisk[disk]->SectorsPerTrack);
SystemDisk[disk]->PartitionFlags[j] = TRUE;
SystemDisk[disk]->PartitionVersion[j] = NW3X_PARTITION;
NWFSPrint("Netware 3.x Partition (%d:%d) LBA-%08X size-%08X (%5dMB) Created\n",
(int)disk, (int)j,
(unsigned int)SystemDisk[disk]->PartitionTable[j].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[j].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[j].nSectorsTotal
* (LONGLONG)SystemDisk[disk]->BytesPerSector)
/ (LONGLONG)0x100000));
}
}
WaitForKey();
break;
case '4':
ClearScreen(consoleHandle);
disk = CurrentDisk;
if ((SystemDisk[disk]) && (SystemDisk[disk]->PhysicalDiskHandle))
{
TotalSectors = (ULONG)((SystemDisk[disk]->Cylinders) *
SystemDisk[disk]->TracksPerCylinder *
SystemDisk[disk]->SectorsPerTrack);
if (TotalSectors < SystemDisk[disk]->SectorsPerTrack)
{
NWFSPrint("nwfs: sector total range error\n");
WaitForKey();
break;
}
NWFSPrint("\n*** Disk Device (%d) Sectors %X ***\n",
(int)disk,(unsigned int)TotalSectors);
// assume the first cylinder of all hard drives is reserved.
AdjustedSectors = (TotalSectors - SystemDisk[disk]->SectorsPerTrack);
// scan for free slots and count the total free sectors
// for this drive.
for (freeSlots = AllocatedSectors = 0, i = 0; i < 4; i++)
{
SlotMask[i] = 0;
SlotLBA[i] = 0;
SlotLength[i] = 0;
FreeLBA[i] = 0;
FreeLength[i] = 0;
if (SystemDisk[disk]->PartitionTable[i].SysFlag &&
SystemDisk[disk]->PartitionTable[i].nSectorsTotal &&
SystemDisk[disk]->PartitionTable[i].StartLBA)
{
AllocatedSectors +=
SystemDisk[disk]->PartitionTable[i].nSectorsTotal;
if (SystemDisk[disk]->PartitionTable[i].SysFlag == NETWARE_386_ID)
NWFSPrint("#%d %s LBA: 0x%08X Sectors: 0x%08X %5uMB %s %s\n",
(int) i + 1,
SystemDisk[disk]->PartitionTable[i].fBootable
? "A" : " ",
(unsigned int)SystemDisk[disk]->PartitionTable[i].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[i].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[i].nSectorsTotal *
(LONGLONG)SystemDisk[disk]->BytesPerSector) /
(LONGLONG)0x100000),
get_partition_type(SystemDisk[disk]->PartitionTable[i].SysFlag),
(SystemDisk[disk]->PartitionVersion[i]
? "3.x" : "4.x/5.x"));
else
NWFSPrint("#%d %s LBA: 0x%08X Sectors: 0x%08X %5uMB %s\n",
(int) i + 1,
SystemDisk[disk]->PartitionTable[i].fBootable
? "A" : " ",
(unsigned int)SystemDisk[disk]->PartitionTable[i].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[i].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[i].nSectorsTotal *
(LONGLONG)SystemDisk[disk]->BytesPerSector) /
(LONGLONG)0x100000),
get_partition_type(SystemDisk[disk]->PartitionTable[i].SysFlag));
}
else
{
FreeSlotIndex[freeSlots] = i;
freeSlots++;
NWFSPrint("#%d ------------- Unused ------------- \n", (int) i + 1);
}
}
// now sort the partition table into ascending order
for (SlotCount = i = 0; i < 4; i++)
{
// look for the lowest starting lba
for (SlotIndex = LBAStart = (ULONG) -1, j = 0; j < 4; j++)
{
if (SystemDisk[disk]->PartitionTable[j].SysFlag &&
!SlotMask[j])
{
if (SystemDisk[disk]->PartitionTable[j].StartLBA <
LBAStart)
{
LBAStart = SystemDisk[disk]->PartitionTable[j].StartLBA;
SlotIndex = j;
}
}
}
if (SlotIndex < 4)
{
SlotMask[SlotIndex] = TRUE;
SlotLBA[SlotCount] =
SystemDisk[disk]->PartitionTable[SlotIndex].StartLBA;
SlotLength[SlotCount] =
SystemDisk[disk]->PartitionTable[SlotIndex].nSectorsTotal;
SlotCount++;
}
}
// now determine how many contiguous free data areas are
// present and what their sizes are in sectors. we align
// the starting LBA and size to cylinder boundries.
LBAStart = SystemDisk[disk]->SectorsPerTrack;
for (FreeCount = i = 0; i < SlotCount; i++)
{
if (LBAStart < SlotLBA[i])
{
// check if we are currently pointing to the
// first track on this device. If so, then
// we begin our first defined partition on
// the first track of this device.
if (LBAStart == SystemDisk[disk]->SectorsPerTrack)
{
LBAWork = LBAStart;
FreeLBA[FreeCount] = LBAWork;
}
else
{
// round up to the next cylinder boundry
LBAWork = (((LBAStart +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
FreeLBA[FreeCount] = LBAWork;
}
// adjust length to correspond to cylinder boundries
LBAEnd = (((SlotLBA[i] +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
// if we rounded into the next partition, then adjust
// the ending LBA to the beginning of the next partition.
if (LBAEnd > SlotLBA[i])
LBAEnd = SlotLBA[i];
// if we rounded off the end of the device, then adjust
// the ending LBA to the total sector cout for the device.
if (LBAEnd > TotalSectors)
LBAEnd = TotalSectors;
Length = LBAEnd - LBAWork;
FreeLength[FreeCount] = Length;
FreeCount++;
}
LBAStart = (SlotLBA[i] + SlotLength[i]);
}
// determine how much free space exists less that claimed
// by the partition table after we finish scanning. this
// case is the fall through case when the partition table
// is empty.
if (LBAStart < TotalSectors)
{
#if (TRUE_NETWARE_MODE)
// check if we are currently pointing to the
// first track on this device. If so, then
// we begin our first defined partition as SPT.
if (LBAStart == SystemDisk[disk]->SectorsPerTrack)
{
LBAWork = LBAStart;
FreeLBA[FreeCount] = LBAWork;
}
else
{
// round up to the next cylinder boundry
LBAWork = (((LBAStart +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
FreeLBA[FreeCount] = LBAWork;
}
#else
// round up to the next cylinder boundry
LBAWork = (((LBAStart +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
FreeLBA[FreeCount] = LBAWork;
#endif
// adjust length to correspond to cylinder boundries
LBAEnd = (((TotalSectors +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
// if we rounded off the end of the device, then adjust
// the ending LBA to the total sector cout for the device.
if (LBAEnd > TotalSectors)
LBAEnd = TotalSectors;
Length = LBAEnd - LBAWork;
FreeLength[FreeCount] = Length;
FreeCount++;
}
else
if (LBAStart > TotalSectors)
{
// if LBAStart is greater than the TotalSectors for this
// device, then we have an error in the disk geometry
// dimensions and they are invalid.
WaitForKey();
break;
}
#if (VERBOSE)
NWFSPrint("disk-%d slot_count-%d free_count-%d slot_index-%d\n",
(int)disk, (int)SlotCount, (int)FreeCount,
(int)SlotIndex);
for (i=0; i < SlotCount; i++)
{
NWFSPrint("part-#%d LBA-%08X Length-%08X Mask-%d\n",
(int)i,
(unsigned int)SlotLBA[i],
(unsigned int)SlotLength[i],
(int)SlotMask[i]);
}
for (i=0; i < FreeCount; i++)
{
NWFSPrint("free-#%d LBA-%08X Length-%08X\n",
(int)i,
(unsigned int)FreeLBA[i],
(unsigned int)FreeLength[i]);
}
#endif
// drive geometry range error or partition table data error,
// abort the operation
if (AdjustedSectors < AllocatedSectors)
{
NWFSPrint("\n *** drive geometry range error ***\n");
WaitForKey();
break;
}
// if there are no free sectors, then abort the operation
FreeSectors = (AdjustedSectors - AllocatedSectors);
NWFSPrint("\ndata sectors : %12.0f bytes (%08X sectors)\n",
(double) ((LONGLONG)SystemDisk[disk]->BytesPerSector *
(LONGLONG)AdjustedSectors),
(unsigned int) AdjustedSectors);
NWFSPrint("reserved sectors : %12.0f bytes (%08X sectors)\n",
(double) ((LONGLONG)SystemDisk[disk]->BytesPerSector *
(LONGLONG)SystemDisk[disk]->SectorsPerTrack),
(unsigned int) SystemDisk[disk]->SectorsPerTrack);
NWFSPrint("%12.0f bytes (%X sectors) are currently free\n",
(double) ((LONGLONG)SystemDisk[disk]->BytesPerSector *
(LONGLONG)FreeSectors),
(unsigned int) FreeSectors);
if (!FreeSectors)
{
NWFSPrint("\n *** No logical space left on device ***\n");
WaitForKey();
break;
}
// if there were no free slots, then abort the operation
if (!freeSlots)
{
NWFSPrint("\n *** No partition table entries available on device ***\n");
WaitForKey();
break;
}
// make certain we have at least 10 MB of free space
// available or abort the operation. don't allow the
// creation of a Netware partition that is smaller than
// 10 MB.
if (FreeSectors < 20480)
{
NWFSPrint("\n *** you must have at least 10 MB of free space ***\n");
WaitForKey();
break;
}
// determine which entry has the single largest area of
// contiguous setors for this device.
for (MaxSlot = MaxLBA = MaxLength = i = 0;
i < FreeCount; i++)
{
if (FreeLength[i] > MaxLength)
{
MaxLBA = FreeLBA[i];
MaxLength = FreeLength[i];
}
}
NWFSPrint("\nAllocate all contiguous free space for NetWare 4.x/5.x? (%uMB) [Y/N]: ",
(unsigned int)
(((LONGLONG)SystemDisk[disk]->BytesPerSector *
(LONGLONG)MaxLength) /
(LONGLONG)0x100000));
fgets(workBuffer, sizeof(workBuffer), stdin);
if (toupper(workBuffer[0]) == 'Y')
{
// get the first free slot available
j = FreeSlotIndex[0];
SetPartitionTableValues(
&SystemDisk[disk]->PartitionTable[j],
NETWARE_386_ID,
MaxLBA,
(MaxLBA + MaxLength) - 1,
0,
SystemDisk[disk]->TracksPerCylinder,
SystemDisk[disk]->SectorsPerTrack);
// validate partition extants
if (ValidatePartitionExtants(disk))
{
NWFSPrint("partition table entry (%d) is invalid\n", (int)j);
WaitForKey();
break;
}
SystemDisk[disk]->PartitionFlags[j] = TRUE;
SystemDisk[disk]->PartitionVersion[j] = NW4X_PARTITION;
NWFSPrint("Netware 4.x/5.x Partition (%d:%d) LBA-%08X size-%08X (%5dMB) Created\n",
(int)disk, (int)j,
(unsigned int)SystemDisk[disk]->PartitionTable[j].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[j].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[j].nSectorsTotal
* (LONGLONG)SystemDisk[disk]->BytesPerSector)
/ (LONGLONG)0x100000));
WaitForKey();
break;
}
while (TRUE)
{
NWFSPrint("\nEnter NetWare 4.x/5.x Partition Size in MB (up to %uMB): ",
(unsigned int)
(((LONGLONG)SystemDisk[disk]->BytesPerSector *
(LONGLONG)MaxLength) /
(LONGLONG)0x100000));
fgets(workBuffer, sizeof(workBuffer), stdin);
targetSize = atol(workBuffer);
if (!targetSize)
break;
if ((targetSize <= (ULONG)
(((LONGLONG)SystemDisk[disk]->BytesPerSector *
(LONGLONG)MaxLength) /
(LONGLONG)0x100000))
&& (targetSize >= 10))
break;
}
if (targetSize)
{
// convert bytes to sectors
MaxLength = (ULONG)(((LONGLONG)targetSize *
(LONGLONG)0x100000) /
(LONGLONG)SystemDisk[disk]->BytesPerSector);
// cylinder align the requested size
MaxLength = (((MaxLength +
((SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder) - 1))
/ (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder))
* (SystemDisk[disk]->SectorsPerTrack *
SystemDisk[disk]->TracksPerCylinder));
// get the first free slot available
j = FreeSlotIndex[0];
SetPartitionTableValues(
&SystemDisk[disk]->PartitionTable[j],
NETWARE_386_ID,
MaxLBA,
(MaxLBA + MaxLength) - 1,
0,
SystemDisk[disk]->TracksPerCylinder,
SystemDisk[disk]->SectorsPerTrack);
SystemDisk[disk]->PartitionFlags[j] = TRUE;
SystemDisk[disk]->PartitionVersion[j] = NW4X_PARTITION;
NWFSPrint("Netware 4.x/5.x Partition (%d:%d) LBA-%08X size-%08X (%5dMB) Created\n",
(int)disk, (int)j,
(unsigned int)SystemDisk[disk]->PartitionTable[j].StartLBA,
(unsigned int)SystemDisk[disk]->PartitionTable[j].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[j].nSectorsTotal
* (LONGLONG)SystemDisk[disk]->BytesPerSector)
/ (LONGLONG)0x100000));
}
}
WaitForKey();
break;
case '5':
ClearScreen(consoleHandle);
disk = CurrentDisk;
if ((SystemDisk[disk]) && (SystemDisk[disk]->PhysicalDiskHandle))
{
NWFSPrint("\n*** Disk Device (%d) Sectors %X ***\n", (int) disk,
(unsigned int) ((SystemDisk[disk]->Cylinders) *
SystemDisk[disk]->TracksPerCylinder *
SystemDisk[disk]->SectorsPerTrack));
for (r=0; r < 4; r++)
{
if (SystemDisk[disk]->PartitionTable[r].nSectorsTotal)
{
if (SystemDisk[disk]->PartitionTable[r].SysFlag == NETWARE_386_ID)
NWFSPrint("#%d %s LBA: 0x%08X Sectors: 0x%08X %5uMB %s %s\n",
(int) (r + 1),
(SystemDisk[disk]->PartitionTable[r].fBootable
? "A" : " "),
(int) SystemDisk[disk]->PartitionTable[r].StartLBA,
(int) SystemDisk[disk]->PartitionTable[r].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[r].nSectorsTotal *
(LONGLONG)SystemDisk[disk]->BytesPerSector) /
(LONGLONG)0x100000),
get_partition_type(SystemDisk[disk]->PartitionTable[r].SysFlag),
(SystemDisk[disk]->PartitionVersion[r]
? "3.x" : "4.x/5.x"));
else
NWFSPrint("#%d %s LBA: 0x%08X Sectors: 0x%08X %5uMB %s\n",
(int) (r + 1),
(SystemDisk[disk]->PartitionTable[r].fBootable
? "A" : " "),
(int) SystemDisk[disk]->PartitionTable[r].StartLBA,
(int) SystemDisk[disk]->PartitionTable[r].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[r].nSectorsTotal *
(LONGLONG)SystemDisk[disk]->BytesPerSector) /
(LONGLONG)0x100000),
get_partition_type(SystemDisk[disk]->PartitionTable[r].SysFlag));
}
else
NWFSPrint("#%d ------------- Unused ------------- \n", (int) r + 1);
}
NWFSPrint("\n Enter Partition to Make Active (1-4): ");
fgets(workBuffer, sizeof(workBuffer), stdin);
selected = atoi(workBuffer);
if (selected && selected <= 4)
{
register ULONG cl;
for (r = 0; r < 4; r++)
{
if (SystemDisk[disk]->PartitionTable[r].nSectorsTotal)
{
if (r + 1 == selected)
{
for (cl = 0; cl < 4; cl ++)
{
if (cl + 1 != selected)
SystemDisk[disk]->PartitionTable[cl].fBootable = 0;
}
NWFSPrint("\nPartition (%d) Set Active\n", (int) selected);
SystemDisk[disk]->PartitionTable[r].fBootable = 1;
}
}
else
if (r + 1 == selected)
NWFSPrint("#%d is not a valid partition entry\n", (int) selected);
}
}
else
NWFSPrint("#%d is not a valid partition number\n", (int) selected);
}
WaitForKey();
break;
case '6':
ClearScreen(consoleHandle);
disk = CurrentDisk;
if ((SystemDisk[disk]) && (SystemDisk[disk]->PhysicalDiskHandle))
{
NWFSPrint("\n*** Disk Device (%d) Sectors %X ***\n", (int) disk,
(unsigned int) ((SystemDisk[disk]->Cylinders) *
SystemDisk[disk]->TracksPerCylinder *
SystemDisk[disk]->SectorsPerTrack));
for (r=0; r < 4; r++)
{
if (SystemDisk[disk]->PartitionTable[r].nSectorsTotal)
{
if (SystemDisk[disk]->PartitionTable[r].SysFlag == NETWARE_386_ID)
NWFSPrint("#%d %s LBA: 0x%08X Sectors: 0x%08X %5uMB %s %s\n",
(int) (r + 1),
(SystemDisk[disk]->PartitionTable[r].fBootable
? "A" : " "),
(int) SystemDisk[disk]->PartitionTable[r].StartLBA,
(int) SystemDisk[disk]->PartitionTable[r].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[r].nSectorsTotal *
(LONGLONG)SystemDisk[disk]->BytesPerSector) /
(LONGLONG)0x100000),
get_partition_type(SystemDisk[disk]->PartitionTable[r].SysFlag),
(SystemDisk[disk]->PartitionVersion[r]
? "3.x" : "4.x/5.x"));
else
NWFSPrint("#%d %s LBA: 0x%08X Sectors: 0x%08X %5uMB %s\n",
(int) (r + 1),
(SystemDisk[disk]->PartitionTable[r].fBootable
? "A" : " "),
(int) SystemDisk[disk]->PartitionTable[r].StartLBA,
(int) SystemDisk[disk]->PartitionTable[r].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[r].nSectorsTotal *
(LONGLONG)SystemDisk[disk]->BytesPerSector) /
(LONGLONG)0x100000),
get_partition_type(SystemDisk[disk]->PartitionTable[r].SysFlag));
}
else
NWFSPrint("#%d ------------- Unused ------------- \n", (int) r + 1);
}
NWFSPrint("\n Enter Partition to Delete (1-4): ");
fgets(workBuffer, sizeof(workBuffer), stdin);
selected = atoi(workBuffer);
if (selected && selected <= 4)
{
for (r = 0; r < 4; r++)
{
if (SystemDisk[disk]->PartitionTable[r].nSectorsTotal)
{
if (r + 1 == selected)
{
NWFSPrint("\nPartition (%d) Deleted\n", (int) selected);
NWFSSet(&SystemDisk[disk]->PartitionTable[r], 0,
sizeof(struct PartitionTableEntry));
}
}
else
if (r + 1 == selected)
NWFSPrint("#%d is not a valid partition entry\n", (int) selected);
}
}
else
NWFSPrint("#%d is not a valid partition number\n", (int) selected);
}
WaitForKey();
break;
case '7':
ClearScreen(consoleHandle);
disk = CurrentDisk;
if ((SystemDisk[disk]) && (SystemDisk[disk]->PhysicalDiskHandle))
{
NWFSPrint("WARNING !!! this operation will erase all data on \nthis drive. Continue? [Y/N]: ");
fgets(workBuffer, sizeof(workBuffer), stdin);
if (toupper(workBuffer[0]) != 'Y')
break;
NWFSPrint("\n*** Disk Device (%d) Sectors %X ***\n", (int) disk,
(unsigned int) ((SystemDisk[disk]->Cylinders) *
SystemDisk[disk]->TracksPerCylinder *
SystemDisk[disk]->SectorsPerTrack));
for (r=0; r < 4; r++)
{
if (SystemDisk[disk]->PartitionTable[r].nSectorsTotal)
{
if (SystemDisk[disk]->PartitionTable[r].SysFlag == NETWARE_386_ID)
NWFSPrint("#%d %s LBA: 0x%08X Sectors: 0x%08X %5uMB %s %s\n",
(int) (r + 1),
(SystemDisk[disk]->PartitionTable[r].fBootable
? "A" : " "),
(int) SystemDisk[disk]->PartitionTable[r].StartLBA,
(int) SystemDisk[disk]->PartitionTable[r].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[r].nSectorsTotal *
(LONGLONG)SystemDisk[disk]->BytesPerSector) /
(LONGLONG)0x100000),
get_partition_type(SystemDisk[disk]->PartitionTable[r].SysFlag),
(SystemDisk[disk]->PartitionVersion[r]
? "3.x" : "4.x/5.x"));
else
NWFSPrint("#%d %s LBA: 0x%08X Sectors: 0x%08X %5uMB %s\n",
(int) (r + 1),
(SystemDisk[disk]->PartitionTable[r].fBootable
? "A" : " "),
(int) SystemDisk[disk]->PartitionTable[r].StartLBA,
(int) SystemDisk[disk]->PartitionTable[r].nSectorsTotal,
(unsigned int)
(((LONGLONG)SystemDisk[disk]->PartitionTable[r].nSectorsTotal *
(LONGLONG)SystemDisk[disk]->BytesPerSector) /
(LONGLONG)0x100000),
get_partition_type(SystemDisk[disk]->PartitionTable[r].SysFlag));
}
else
NWFSPrint("#%d ------------- Unused ------------- \n", (int) r + 1);
}
NWFSPrint("\nWARNING !!! Are you certain you want to erase all data and partitions on \nthis drive? [Y/N]: ");
fgets(workBuffer, sizeof(workBuffer), stdin);
if (toupper(workBuffer[0]) != 'Y')
break;
// zero the partition table and partition signature
NWFSSet(&SystemDisk[disk]->PartitionTable[0].fBootable, 0, 64);
}
break;
case '8':
ClearScreen(0);
NWFSPrint("WARNING !!! this operation will assign all free space on this drive \nto Netware Partition(s)\n");
NWFSPrint("\nContinue to assign all free space to Netware Partition(s) ? [Y/N]: ");
fgets(workBuffer, sizeof(workBuffer), stdin);
if (toupper(workBuffer[0]) != 'Y')
break;
NWAllocateUnpartitionedSpace();
break;
case '9':
NWFSFree(Buffer);
SyncDevice((ULONG)SystemDisk[disk]->PhysicalDiskHandle);
UtilScanVolumes();
return;
}
}
}
ULONG convert_volume_name_to_handle(
BYTE *volume_name,
ULONG *vpart_handle)
{
ULONG j, i;
ULONG handles[7];
nwvp_vpartition_info vpinfo;
nwvp_payload payload;
payload.payload_object_count = 0;
payload.payload_index = 0;
payload.payload_object_size_buffer_size = (4 << 20) + sizeof(handles);
payload.payload_buffer = (BYTE *) &handles[0];
do
{
nwvp_vpartition_scan(&payload);
for (j=0; j < payload.payload_object_count; j++)
{
if (nwvp_vpartition_return_info(handles[j], &vpinfo) == 0)
{
for (i=0; i < (ULONG)(vpinfo.volume_name[0] + 1); i++)
{
if (volume_name[i] != vpinfo.volume_name[i])
break;
}
if (i== (ULONG)(vpinfo.volume_name[0] + 1))
{
*vpart_handle = handles[j];
return (0);
}
}
}
} while ((payload.payload_index != 0) && (payload.payload_object_count != 0));
return (-1);
}
void build_hotfix_tables(void)
{
ULONG j, i;
ULONG group_number = 0;
ULONG vhandle;
ULONG logical_capacity;
ULONG raw_ids[4];
nwvp_payload payload;
nwvp_rpartition_scan_info rlist[5];
nwvp_rpartition_info rpart_info;
nwvp_lpartition_scan_info llist[5];
nwvp_lpartition_info lpart_info;
UtilScanVolumes();
payload.payload_object_count = 0;
payload.payload_index = 0;
payload.payload_object_size_buffer_size = (sizeof(nwvp_rpartition_scan_info) << 20) + sizeof(rlist);
payload.payload_buffer = (BYTE *) &rlist[0];
do
{
nwvp_rpartition_scan(&payload);
for (j=0; j< payload.payload_object_count; j++)
{
nwvp_rpartition_return_info(rlist[j].rpart_handle, &rpart_info);
if ((rpart_info.partition_type == 0x65) || (rpart_info.partition_type == 0x77))
{
if (rpart_info.lpart_handle == 0xFFFFFFFF)
{
logical_capacity = (rpart_info.physical_block_count & 0xFFFFFF00) - 242;
raw_ids[0] = rpart_info.rpart_handle;
raw_ids[1] = 0xFFFFFFFF;
raw_ids[2] = 0xFFFFFFFF;
raw_ids[3] = 0xFFFFFFFF;
nwvp_lpartition_format(&vhandle, logical_capacity, &raw_ids[0]);
}
}
}
} while ((payload.payload_index != 0) && (payload.payload_object_count != 0));
hotfix_table_count = 0;
payload.payload_object_count = 0;
payload.payload_index = 0;
payload.payload_object_size_buffer_size = (sizeof(nwvp_lpartition_scan_info) << 20) + sizeof(llist);
payload.payload_buffer = (BYTE *) &llist[0];
do
{
nwvp_lpartition_scan(&payload);
for (j=0; j< payload.payload_object_count; j++)
{
if (nwvp_lpartition_return_info(llist[j].lpart_handle, &lpart_info) == 0)
{
for (i=0; i
{
if (hotfix_table_count <= 256)
{
hotfix_table[hotfix_table_count].group_number = group_number;
hotfix_table[hotfix_table_count].rpart_handle = lpart_info.m[i].rpart_handle;
hotfix_table[hotfix_table_count].lpart_handle = llist[j].lpart_handle;
hotfix_table[hotfix_table_count].physical_block_count = lpart_info.logical_block_count + lpart_info.m[i].hotfix_block_count;
hotfix_table[hotfix_table_count].logical_block_count = lpart_info.logical_block_count;
hotfix_table[hotfix_table_count].segment_count = lpart_info.segment_count;
hotfix_table[hotfix_table_count].mirror_count = lpart_info.mirror_count;
hotfix_table[hotfix_table_count].hotfix_block_count = ((lpart_info.m[i].status & MIRROR_PRESENT_BIT) == 0) ? 0 : lpart_info.m[i].hotfix_block_count;
hotfix_table[hotfix_table_count].insynch_flag = ((lpart_info.m[i].status & MIRROR_INSYNCH_BIT) == 0) ? 0 : 0xFFFFFFFF;
hotfix_table[hotfix_table_count].active_flag = ((lpart_info.lpartition_status & MIRROR_GROUP_ACTIVE_BIT) == 0) ? 0 : 0xFFFFFFFF;
hotfix_table_count ++;
}
}
group_number ++;
}
}
} while ((payload.payload_index != 0) && (payload.payload_object_count != 0));
}
void NWEditHotFix(void)
{
ULONG i;
ULONG index;
ULONG index1;
ULONG block_count;
ULONG raw_ids[4];
ULONG display_base = 0;
BYTE input_buffer[20] = { "" };
BYTE workBuffer[20] = { "" };
build_hotfix_tables();
while (TRUE)
{
SyncDisks();
ClearScreen(consoleHandle);
NWFSPrint("NetWare Mirroring Manager\n");
NWFSPrint("Copyright (c) 1999, 2000 Jeff V. Merkey All Rights Reserved.\n");
NWFSPrint("\n Mirror Vol Data Hotfix Partition Synch/ ");
NWFSPrint("\n # Grp Cnt Segs Size Size Size Active Disk:Partition\n");
for (i=0; i < 8; i++)
{
if ((index = display_base + i) < hotfix_table_count)
{
LONGLONG size;
nwvp_rpartition_info rpart_info;
#if (LINUX_UTIL)
extern ULONG MaxHandlesSupported;
extern BYTE *PhysicalDiskNames[MAX_DISKS];
#endif
NWFSPrint("%2d %2d %2d %2d ",
(int) index,
(int) hotfix_table[index].group_number,
(int) hotfix_table[index].mirror_count,
(int) hotfix_table[index].segment_count);
size = (LONGLONG)((LONGLONG)hotfix_table[index].logical_block_count *
(LONGLONG)IO_BLOCK_SIZE);
if (size < 0x100000)
NWFSPrint("%8uK ", (unsigned)(size / (LONGLONG)1024));
else
NWFSPrint("%8uMB", (unsigned)(size / (LONGLONG)0x100000));
size = (LONGLONG)((LONGLONG)hotfix_table[index].hotfix_block_count *
(LONGLONG)IO_BLOCK_SIZE);
if (hotfix_table[index].hotfix_block_count != 0)
{
if (size < 0x100000)
NWFSPrint("%8uK ", (unsigned)(size / (LONGLONG)1024));
else
NWFSPrint("%8uMB", (unsigned)(size / (LONGLONG)0x100000));
size = (LONGLONG)((LONGLONG)hotfix_table[index].physical_block_count *
(LONGLONG)IO_BLOCK_SIZE);
if (size < 0x100000)
NWFSPrint("%8uK ", (unsigned)(size / (LONGLONG)1024));
else
NWFSPrint("%8uMB ", (unsigned)(size / (LONGLONG)0x100000));
NWFSPrint((hotfix_table[index].insynch_flag != 0) ? " IN/" : "OUT/");
NWFSPrint((hotfix_table[index].active_flag != 0) ? "YES " : "NO ");
nwvp_rpartition_return_info(hotfix_table[index].rpart_handle, &rpart_info);
if ((rpart_info.partition_type == 0x65) || (rpart_info.partition_type == 0x77))
{
#if (LINUX_UTIL)
NWFSPrint("%d:%d %s\n",
(int)rpart_info.physical_disk_number,
(int)rpart_info.partition_number + 1,
PhysicalDiskNames[rpart_info.physical_disk_number %
MaxHandlesSupported]);
#else
NWFSPrint("%d:%d\n",
(int)rpart_info.physical_disk_number,
(int)rpart_info.partition_number + 1);
#endif
}
}
else
{
NWFSPrint(" PARTITION NOT PRESENT ");
}
}
else
NWFSPrint("\n");
}
NWFSPrint("\n");
NWFSPrint(" 1. Add Mirror \n");
NWFSPrint(" 2. Delete Mirror\n");
NWFSPrint(" 3. Activate Incomplete Mirror Group\n");
NWFSPrint(" 4. Resize Hotfix\n");
NWFSPrint(" 5. Scroll Hotfix List\n");
NWFSPrint(" 6. Exit Menu\n");
NWFSPrint(" Enter a Menu Option: ");
fgets(input_buffer, sizeof(input_buffer), stdin);
switch (input_buffer[0])
{
case '1':
NWFSPrint(" Enter Primary Partition Number: ");
if (input_get_number(&index) == 0)
{
if (index < hotfix_table_count)
{
NWFSPrint(" Enter Secondary Partition Number: ");
if (input_get_number(&index1) == 0)
{
if (index1 < hotfix_table_count)
{
if (hotfix_table[index1].mirror_count == 1)
{
if (hotfix_table[index1].segment_count == 0)
{
if ((hotfix_table[index1].physical_block_count + 65) >= hotfix_table[index].logical_block_count)
{
nwvp_lpartition_unformat(hotfix_table[index1].lpart_handle);
nwvp_partition_add_mirror(hotfix_table[index].lpart_handle, hotfix_table[index1].rpart_handle);
build_hotfix_tables();
break;
}
NWFSPrint(" ********* Secondary Partition Too Small **********\n");
WaitForKey();
break;
}
NWFSPrint(" ********* Secondary Partition Has Volume Segments **********\n");
WaitForKey();
break;
}
NWFSPrint(" ********* Secondary Partition Is Already Mirrored **********\n");
WaitForKey();
break;
}
}
NWFSPrint(" ********* Invalid Secondary Partition Number **********\n");
WaitForKey();
break;
}
}
NWFSPrint(" ********* Invalid Primary Partition Number **********\n");
WaitForKey();
break;
case '2':
NWFSPrint(" Enter Partition Number: ");
if (input_get_number(&index) == 0)
{
if ((index < hotfix_table_count) && (hotfix_table[index].mirror_count > 1))
{
i = 0;
if (hotfix_table[index].insynch_flag != 0)
{
for (i=0; i
{
if ((i != index) &&
(hotfix_table[i].lpart_handle == hotfix_table[index].lpart_handle) &&
(hotfix_table[i].insynch_flag != 0))
break;
}
}
if (i != hotfix_table_count)
{
if (nwvp_partition_del_mirror(hotfix_table[index].lpart_handle, hotfix_table[index].rpart_handle) == 0)
{
build_hotfix_tables();
WaitForKey();
break;
}
}
NWFSPrint(" ********* Can not delete last valid mirror member **********\n");
WaitForKey();
break;
}
}
NWFSPrint(" ********* Invalid Primary Partition Number **********\n");
WaitForKey();
break;
case '3':
NWFSPrint(" Enter Partition Number: ");
if (input_get_number(&index) == 0)
{
if (index < hotfix_table_count)
{
if (hotfix_table[index].active_flag == 0)
{
if (nwvp_lpartition_activate(hotfix_table[index].lpart_handle) == 0)
{
build_hotfix_tables();
break;
}
NWFSPrint(" ********* Can not Activate Logical Partition **********\n");
WaitForKey();
break;
}
NWFSPrint(" ********* Logical Partition Already Actuve **********\n");
WaitForKey();
break;
}
}
NWFSPrint(" ********* Invalid Partition Number **********\n");
WaitForKey();
break;
case '4':
NWFSPrint(" Enter Partition Number: ");
if (input_get_number(&index) == 0)
{
if (index < hotfix_table_count)
{
if ((hotfix_table[index].segment_count== 0) && (hotfix_table[index].mirror_count == 1))
{
register ULONG DataSize;
if (hotfix_table[index].physical_block_count < 101)
{
NWFSPrint(" ********* Invalid Size **********\n");
WaitForKey();
break;
}
NWFSPrint(" Enter Logical Data Area Size in MB (up to %5uMB): ",
(unsigned int)
(((LONGLONG)(hotfix_table[index].physical_block_count - 100) *
(LONGLONG)IO_BLOCK_SIZE) /
(LONGLONG)0x100000));
fgets(workBuffer, sizeof(workBuffer), stdin);
DataSize = atol(workBuffer);
block_count = (ULONG)(((LONGLONG)DataSize *
(LONGLONG)0x100000) /
(LONGLONG)IO_BLOCK_SIZE);
if (block_count)
{
if ((block_count + 100) < hotfix_table[index].physical_block_count)
{
raw_ids[0] = hotfix_table[index].rpart_handle;
raw_ids[1] = 0xFFFFFFFF;
raw_ids[2] = 0xFFFFFFFF;
raw_ids[3] = 0xFFFFFFFF;
nwvp_lpartition_unformat(hotfix_table[index].lpart_handle);
nwvp_lpartition_format(&hotfix_table[index].lpart_handle,
block_count, &raw_ids[0]);
build_hotfix_tables();
break;
}
}
NWFSPrint(" ********* Invalid Size **********\n");
WaitForKey();
break;
}
NWFSPrint(" ********* Cannot Resize Partition With NetWare Volumes **********\n");
WaitForKey();
break;
}
}
NWFSPrint(" ********* Invalid Partition Number **********\n");
WaitForKey();
break;
case '5':
display_base += 8;
if (display_base >= hotfix_table_count)
display_base = 0;
break;
case '6':
SyncDisks();
return;
}
}
}
void build_segment_tables(void)
{
ULONG j, i, k, l;
ULONG block_count;
ULONG handles[7];
nwvp_vpartition_info vpinfo;
nwvp_lpartition_space_return_info slist[5];
nwvp_lpartition_scan_info llist[5];
nwvp_payload payload;
nwvp_payload payload1;
segment_table_count = 0;
payload1.payload_object_count = 0;
payload1.payload_index = 0;
payload1.payload_object_size_buffer_size = (sizeof(nwvp_lpartition_scan_info) << 20) + sizeof(llist);
payload1.payload_buffer = (BYTE *) &llist[0];
do
{
nwvp_lpartition_scan(&payload1);
for (l=0; l < payload1.payload_object_count; l++)
{
payload.payload_object_count = 0;
payload.payload_index = 0;
payload.payload_object_size_buffer_size = (sizeof(nwvp_lpartition_space_return_info) << 20) + sizeof(slist);
payload.payload_buffer = (BYTE *) &slist[0];
do
{
nwvp_lpartition_return_space_info(llist[l].lpart_handle, &payload);
for (j=0; j < payload.payload_object_count; j++)
{
if (segment_table_count <= 256)
{
segment_table[segment_table_count].lpart_handle = slist[j].lpart_handle;
segment_table[segment_table_count].segment_offset = slist[j].segment_offset;
segment_table[segment_table_count].segment_count = slist[j].segment_count;
segment_table[segment_table_count].free_flag = ((slist[j].status_bits & INUSE_BIT) == 0) ? 0xFFFFFFFF : 0;
segment_mark_table[segment_table_count] = 0;
segment_table_count ++;
}
}
} while ((payload.payload_index != 0) && (payload.payload_object_count != 0));
}
} while ((payload1.payload_index != 0) && (payload1.payload_object_count != 0));
payload.payload_object_count = 0;
payload.payload_index = 0;
payload.payload_object_size_buffer_size = (7 << 20) + sizeof(handles);
payload.payload_buffer = (BYTE *) &handles[0];
do
{
nwvp_vpartition_scan(&payload);
for (j=0; j < payload.payload_object_count; j++)
{
if (nwvp_vpartition_return_info(handles[j], &vpinfo) == 0)
{
for (i=0; i < vpinfo.segment_count; i++)
{
for (k=0; k < segment_table_count; k++)
{
block_count = (segment_table[k].segment_count / vpinfo.blocks_per_cluster) * vpinfo.blocks_per_cluster;
if ((vpinfo.segments[i].lpart_handle == segment_table[k].lpart_handle) &&
(vpinfo.segments[i].partition_block_offset == segment_table[k].segment_offset) &&
(vpinfo.segments[i].segment_block_count == block_count))
{
nwvp_memmove(&segment_table[k].VolumeName[0], &vpinfo.volume_name[0], 16);
segment_table[k].segment_number = i + 1;
segment_table[k].total_segments = vpinfo.segment_count;
break;
}
}
}
}
}
} while ((payload.payload_index != 0) && (payload.payload_object_count != 0));
}
void ChangeVolumeFlags(VOLUME *volume)
{
ULONG ccode, WorkFlags;
BYTE input_buffer[20] = { "" };
ROOT3X *root3x;
ROOT *root;
BYTE *WorkBuffer;
WorkBuffer = NWFSAlloc(IO_BLOCK_SIZE, DISKBUF_TAG);
if (!WorkBuffer)
{
NWFSPrint("*** could not allocate workbuffer ***\n");
return;
}
NWFSSet(WorkBuffer, 0, IO_BLOCK_SIZE);
root = (ROOT *) WorkBuffer;
root3x = (ROOT3X *) root;
WorkFlags = volume->VolumeFlags;
while (TRUE)
{
SyncDisks();
ClearScreen(0);
NWFSPrint("NetWare Volume Settings Manager\n");
NWFSPrint("Copyright (c) 1999, 2000 Jeff V. Merkey All Rights Reserved.\n");
NWFSPrint(" Volume Name : [%-15s]\n",
volume->VolumeName);
NWFSPrint(" Volume Type : %s\n",
((WorkFlags & NDS_FLAG) ||
(WorkFlags & NEW_TRUSTEE_COUNT))
? "4.x/5.x" : "3.x");
NWFSPrint(" Suballocation : %s\n",
(WorkFlags & SUB_ALLOCATION_ON) ? "ON" : "OFF");
NWFSPrint(" File Compression : %s\n",
(WorkFlags & FILE_COMPRESSION_ON) ? "ON" : "OFF");
NWFSPrint(" Data Migration : %s\n",
(WorkFlags & DATA_MIGRATION_ON) ? "ON" : "OFF");
NWFSPrint(" Auditing : %s\n",
(WorkFlags & AUDITING_ON) ? "ON" : "OFF");
NWFSPrint(" Netware Directory Services : %s\n",
(WorkFlags & NDS_FLAG) ? "PRESENT" : "NONE");
NWFSPrint("\n");
NWFSPrint(" 1. Apply Volume Setting Changes\n");
NWFSPrint(" 2. Toggle Suballocation Flag\n");
NWFSPrint(" 3. Toggle File Compression Flag\n");
NWFSPrint(" 4. Toggle Data Migration Flag\n");
NWFSPrint(" 5. Toggle Auditing Flag\n");
NWFSPrint(" 6. Toggle Netware Directory Service Flag\n");
NWFSPrint(" 7. Return\n\n");
NWFSPrint(" Enter a Menu Option: ");
fgets(input_buffer, sizeof(input_buffer), stdin);
switch (input_buffer[0])
{
case '1':
nwvp_vpartition_open(volume->nwvp_handle);
ccode = nwvp_vpartition_block_read(volume->nwvp_handle,
(volume->FirstDirectory * volume->BlocksPerCluster),
1, WorkBuffer);
if (ccode)
{
NWFSPrint("error reading volume [%s] root entry\n", volume->VolumeName);
nwvp_vpartition_close(volume->nwvp_handle);
WaitForKey();
break;
}
volume->VolumeFlags = WorkFlags;
if (volume->VolumeFlags & NEW_TRUSTEE_COUNT)
root->VolumeFlags = (BYTE)volume->VolumeFlags;
else
root3x->VolumeFlags = (BYTE)volume->VolumeFlags;
NWFSPrint("Writing volume [%s] root entry\n", volume->VolumeName);
ccode |