1
0
Files
irix-657m-src/eoe/cmd/mediad/fmt_dos.C
2022-09-29 17:59:04 +03:00

280 lines
9.1 KiB
C

#include <bstring.h>
#include <mntent.h>
#include <string.h>
#include "Device.H"
#include "Log.H"
#include "Partition.H"
#include "SimpleVolume.H"
#include "fmt_dos.H"
/*
*-----------------------------------------------------------------------------
* A Note on DOS partitions:
* =========================
* - Partitions with index = 1, 2, 3, 4 refer to primary partitions. These have
* partition table entries that reside in the very first sector on disk.
* - Partitions with index = 5, 6, 7... refer to logical partitions. These are
* part of an extended partition. There can be only one extended partition.
* - Partitions with index = 0 imply partitions that occupy entire devices.
* Typical examples of these are floppies and flopticals; They have boot
* sectors in the very first sector.
*-----------------------------------------------------------------------------
*/
class FormatDSO;
/*
*-----------------------------------------------------------------------------
* create_dos_volume()
* This routine instantiates a SimpleVolume
* for a single mountable dos partition.
*-----------------------------------------------------------------------------
*/
static void create_dos_volume(Partition *part, char *label)
{
char *opts;
char optbuf[12];
int index = part->address().partition();
const char *fsname = part->device()->dev_name(FMT_DOS, index);
if (index >= 1){
(void) sprintf(optbuf, "partition=%d", index);
opts = optbuf;
}
else opts = NULL;
mntent mnt = { (char *) fsname, NULL, "dos", opts, 0, 0 };
Log::debug("DOS volume label is \"%s\"", label);
(void) SimpleVolume::create(part, mnt, label);
return;
}
/*
*-----------------------------------------------------------------------------
* trim_label()
* This routine takes a 11 char string representing a label and converts it
* into a null-terminated string, without trailing spaces.
*-----------------------------------------------------------------------------
*/
static char *trim_label(char *label)
{
char *t;
static char trimmed[12];
strncpy(trimmed, label, 11);
for (t = trimmed+10; t >= trimmed; t--){
if (*t != ' '){
*++t = '\0';
return (trimmed);
}
}
*trimmed = '\0';
return (trimmed);
}
/*
*-----------------------------------------------------------------------------
* read_label()
* This routine is used to read in a dos label.
*-----------------------------------------------------------------------------
*/
static void read_label(Device &device, int start_sect, char *bootsect,
int secsize, char *label)
{
int error;
u_char fatcount;
u_short fatsize;
u_short reservecount;
u_int label_sect;
dfile_t fentry;
char buff[2048], *lptr = label;
strcpy(lptr, "");
fatsize = FAT_SIZE(bootsect);
fatcount = FAT_COUNT(bootsect);
reservecount = RESERVE_COUNT(bootsect);
label_sect = (start_sect+reservecount+fatcount*fatsize);
error = device.read_data(buff, label_sect, 1, secsize);
if (error == 0){
memcpy(&fentry, buff, sizeof fentry);
if (fentry.df_attribute == (ATTRIB_ARCHIVE | ATTRIB_LABEL)){
strncpy(lptr, fentry.df_name, FILE_LEN);
strncpy(lptr+FILE_LEN, fentry.df_ext, EXTN_LEN);
strcpy(label, trim_label(label));
return;
}
}
return;
}
/*
*-----------------------------------------------------------------------------
* read_logical_partn()
* This routine looks at all the logical partitions that are within an extended
* partition and creates a dos volume for each one of them.
*-----------------------------------------------------------------------------
*/
static void read_logical_partn(Device &device, int secsize, u_int extnd_sect)
{
int partn;
int error;
pte_t *p1, *p2;
char label[27];
char buf[2048];
char bootsect[2048];
u_int numbr_sect;
u_int data_sect;
u_int this_sect;
u_int part_sect;
u_int next_sect = 0;
Partition *part;
partn = 5;
part_sect = extnd_sect;
do {
error = device.read_data(buf, part_sect, 1, secsize);
if (error == 0){
p1 = offset(buf, 0);
p2 = offset(buf, 1);
next_sect = PARTN_START_SECT(p2);
this_sect = PARTN_START_SECT(p1);
numbr_sect= PARTN_NUMBR_SECT(p1);
data_sect = part_sect+this_sect;
part_sect = extnd_sect+next_sect;
/*
* We've found a logical partition.
* We need to check if it's a dos volume.
* We need to create a dos volume for it.
*/
error = device.read_data(bootsect, data_sect,
1, secsize);
if (error == 0){
if (MAGIC_DOS(bootsect)){
read_label(device, data_sect, bootsect,
secsize,label);
PartitionAddress paddr(device.address(), FMT_DOS, partn);
part = Partition::create(paddr,
&device,
secsize,
data_sect,
numbr_sect,
"dos");
create_dos_volume(part, label);
}
}
}
partn++;
} while (next_sect);
return;
}
/*
*-----------------------------------------------------------------------------
* read_primary_partn()
* This routine looks at all the partitions within a device (primary/logical)
* and creates a SimpleVolume for each mountable dos partition.
*-----------------------------------------------------------------------------
*/
static void read_primary_partn(Device &device, int secsize, char *buf)
{
int partn;
pte_t *p;
int error;
u_int start_sect;
u_int numbr_sect;
u_int extnd_sect;
char label[27];
char bootsect[2048];
Partition *part;
for (partn = 1; partn <= 4; partn++){
/*
* Look at each primary partition.
* If primary partition is non-extended, create dos volume.
* If primary partition is extended, call read_logical_partn.
*/
p = offset(buf, partn-1);
if (p->type != EXTENDED_PARTITION){
/*
* We've found a non-extended partition.
* We need to check if it's a dos volume.
*/
start_sect = PARTN_START_SECT(p);
numbr_sect = PARTN_NUMBR_SECT(p);
error = device.read_data(bootsect, start_sect, 1, secsize);
if (error == 0){
if (MAGIC_DOS(bootsect)){
read_label(device, start_sect,
bootsect, secsize,label);
PartitionAddress paddr(device.address(),
FMT_DOS, partn);
part = Partition::create(paddr,
&device,
secsize,
start_sect,
numbr_sect,
"dos");
create_dos_volume(part, label);
}
}
}
else {
/*
* This is an extended partition.
* Look through this for logical partitions.
*/
extnd_sect = PARTN_START_SECT(p);
read_logical_partn(device, secsize, extnd_sect);
}
}
return;
}
extern "C"
void inspect(FormatDSO *, Device *device)
{
// Does this device support this format?
if (!device->filesys_dos())
return;
int error;
int nsectors;
int secsize = device->sector_size(FMT_DOS);
char label[27];
char buf[2048];
Partition *part;
error = device->read_data(buf, 0, 1, secsize);
if (error == 0){
if (MAGIC_DOS(buf)){
/*
* This is an unpartitioned DOS device
* Such devices are floppies and flopticals.
* Their sector count is stored at offset: 0x13.
*
*/
read_label(*device, 0, buf, secsize,label);
nsectors = SECTOR_COUNT(buf);
PartitionAddress paddr(device->address(), FMT_DOS,
PartitionAddress::WholeDisk);
part = Partition::create(paddr, device, secsize,
0, nsectors, "dos");
create_dos_volume(part, label);
}
else if (MAGIC_PART(buf)){
/*
* This is a partitioned DOS device
*/
read_primary_partn(*device, secsize, buf);
}
}
return;
}