1
0
Files
irix-657m-src/eoe/cmd/fp/dos.c
2022-09-29 17:59:04 +03:00

440 lines
15 KiB
C

/*
*=============================================================================
* File: dos.c
* Purpose: This file has code for creating the
* actual filing system within a partn.
*=============================================================================
*/
#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include "dos.h"
#include "misc.h"
/*
*-----------------------------------------------------------------------------
* Extern variables
*-----------------------------------------------------------------------------
*/
extern int fd; /* Device descr. */
extern u_int heads; /* Disk Geometry */
extern u_int sectors; /* Disk Geometry */
/*
*-----------------------------------------------------------------------------
* Global variables
*-----------------------------------------------------------------------------
*/
static dfs_t *dos_dfs;
/*
*-----------------------------------------------------------------------------
* Function Prototypes
*-----------------------------------------------------------------------------
*/
void dos_mkfs(u_long daddr, u_long dsize, char *dlabel);
void dos_create_incore(dfs_t **dfs, u_long daddr, u_long dsize);
void dos_write_incore(dfs_t *dfs, char *dlabel);
void dos_pack_boot(dfs_t *dfs, bp_t *bootp);
void dos_init_fat(dfs_t *dfs);
void dos_init_root(dfs_t *dfs);
void dos_print_bootp(dfs_t *dfs, bp_t *bootp);
void dos_time(u_char *d_date, u_char *d_time);
void dos_check_label(char *outlabel, char *inlabel);
void dos_write_label(char *label, u_long label_addr);
u_int compute_sectorspercluster(u_int size);
u_int compute_fatsize(u_int sect_count, u_int sect_reserved,
u_int sect_percluster, u_int dos_rootsize);
/*
*-----------------------------------------------------------------------------
* dos_mkfs()
* This routine is the external interface to the rest of the program.
*-----------------------------------------------------------------------------
*/
void dos_mkfs(u_long daddr, u_long dsize, char *dlabel)
{
dos_create_incore(&dos_dfs, daddr, dsize);
dos_write_incore(dos_dfs, dlabel);
return;
}
/*
*-----------------------------------------------------------------------------
* dos_create_incore()
* This routine is used to create the incore data structures for the new
* file system that is being created.
*-----------------------------------------------------------------------------
*/
void dos_create_incore(dfs_t **dfs, u_long daddr, u_long dsize)
{
bp_t dos_bootp;
u_char *dos_boot;
u_char *dos_fat;
u_char *dos_root;
u_char dos_sectorspercluster;
u_short dos_fatsize;
u_int dos_numsectors;
u_long dos_rootsize;
*dfs = gmalloc(sizeof(dfs_t));
dos_rootsize = DOS_ROOTSIZE(DOS_ROOTENTRIES);
dos_numsectors = dsize/SECTOR_SIZE;
dos_sectorspercluster = compute_sectorspercluster(dsize);
dos_fatsize = compute_fatsize(dos_numsectors, DOS_RESERVECOUNT,
dos_sectorspercluster, dos_rootsize);
strncpy((char *) dos_bootp.bp_oem, "IBM PNCI", OEM_LEN);
dos_bootp.bp_magic[VH_MAGIC0] = DOS_MAGIC1;
dos_bootp.bp_magic[VH_MAGIC1] = DOS_MAGIC2;
dos_bootp.bp_magic[VH_MAGIC2] = DOS_MAGIC3;
dos_bootp.bp_sectorsize = SECTOR_SIZE;
dos_bootp.bp_reservecount = DOS_RESERVECOUNT;
dos_bootp.bp_fatcount = DOS_FATCOUNT;
dos_bootp.bp_rootentries = DOS_ROOTENTRIES;
dos_bootp.bp_sectorcount = 0;
dos_bootp.bp_mediatype = DOS_MEDIA_TYPE;
dos_bootp.bp_sectorspertrack = sectors;
dos_bootp.bp_headcount = heads;
dos_bootp.bp_hiddensectors = sectors;
dos_bootp.bp_numsectors = dos_numsectors;
dos_bootp.bp_fatsize = dos_fatsize;
dos_bootp.bp_sectorspercluster= dos_sectorspercluster;
(*dfs)->dfs_fd = fd;
(*dfs)->dfs_boot = gmalloc(SECTOR_SIZE);
(*dfs)->dfs_fat = gmalloc(dos_fatsize*SECTOR_SIZE);
(*dfs)->dfs_root = gmalloc(dos_rootsize*SECTOR_SIZE);
(*dfs)->dfs_partaddr = daddr;
(*dfs)->dfs_fataddr1 = (*dfs)->dfs_partaddr+SECTOR_SIZE;
(*dfs)->dfs_fataddr2 = (*dfs)->dfs_fataddr1+dos_fatsize*SECTOR_SIZE;
(*dfs)->dfs_rootaddr = (*dfs)->dfs_fataddr2+dos_fatsize*SECTOR_SIZE;
(*dfs)->dfs_fileaddr = (*dfs)->dfs_rootaddr+dos_rootsize*SECTOR_SIZE;
(*dfs)->dfs_fatsize = dos_fatsize;
(*dfs)->dfs_rootsize = dos_rootsize;
dos_pack_boot(*dfs, &dos_bootp);
#ifdef DOS_PRINT
dos_print_bootp(*dfs,&dos_bootp);
#endif
dos_init_fat(*dfs);
dos_init_root(*dfs);
return;
}
/*
*-----------------------------------------------------------------------------
* dos_write_incore()
* This routine is used to write out the in-core data structures to disk.
*-----------------------------------------------------------------------------
*/
void dos_write_incore(dfs_t *dfs, char *dlabel)
{
#ifdef DOS_PRINT
printf(" PART_ADDR = %d\n", dfs->dfs_partaddr);
printf(" FAT1_ADDR = %d\n", dfs->dfs_fataddr1);
printf(" FAT1_SIZE = %d\n", dfs->dfs_fatsize*SECTOR_SIZE);
printf(" FAT2_ADDR = %d\n", dfs->dfs_fataddr2);
printf(" FAT2_SIZE = %d\n", dfs->dfs_fatsize*SECTOR_SIZE);
printf(" ROOT_ADDR = %d\n", dfs->dfs_rootaddr);
printf(" ROOT_SIZE = %d\n", dfs->dfs_rootsize*SECTOR_SIZE);
printf(" FILE_ADDR = %d\n", dfs->dfs_fileaddr);
#endif
gseek(dfs->dfs_partaddr);
gwrite(dfs->dfs_boot, SECTOR_SIZE);
gseek(dfs->dfs_fataddr1);
gwrite(dfs->dfs_fat, SECTOR_SIZE*dfs->dfs_fatsize);
gseek(dfs->dfs_fataddr2);
gwrite(dfs->dfs_fat, SECTOR_SIZE*dfs->dfs_fatsize);
gseek(dfs->dfs_rootaddr);
gwrite(dfs->dfs_root, SECTOR_SIZE*dfs->dfs_rootsize);
dos_write_label(dlabel, dfs->dfs_rootaddr);
return;
}
/*
*-----------------------------------------------------------------------------
* dos_pack_boot()
* This routine is used to align the boot sector.
*-----------------------------------------------------------------------------
*/
void dos_pack_boot(dfs_t *dfs, bp_t *bootp)
{
u_int tmpint;
u_short tmpshort;
u_char *ptr = dfs->dfs_boot;
u_char *cbpptr = dfs->dfs_boot;
memcpy(cbpptr, bootp->bp_magic, MAGIC_LEN);
cbpptr += sizeof(u_char) * 3;
memcpy(cbpptr, bootp->bp_oem, OEM_LEN);
cbpptr += sizeof(u_char) * 8;
tmpshort = align_short(bootp->bp_sectorsize);
memcpy(cbpptr, &tmpshort, sizeof(u_short));
cbpptr += sizeof(u_short);
memcpy(cbpptr, &bootp->bp_sectorspercluster, sizeof(u_char));
cbpptr += sizeof(u_char);
tmpshort = align_short(bootp->bp_reservecount);
memcpy(cbpptr, &tmpshort, sizeof(u_short));
cbpptr += sizeof(u_short);
memcpy(cbpptr, &bootp->bp_fatcount, sizeof(u_char));
cbpptr += sizeof(u_char);
tmpshort = align_short(bootp->bp_rootentries);
memcpy(cbpptr, &tmpshort, sizeof(u_short));
cbpptr += sizeof(u_short);
tmpshort = align_short(bootp->bp_sectorcount);
memcpy(cbpptr, &tmpshort, sizeof(u_short));
cbpptr += sizeof(u_short);
memcpy(cbpptr, &bootp->bp_mediatype, sizeof(u_char));
cbpptr += sizeof(u_char);
tmpshort = align_short(bootp->bp_fatsize);
memcpy(cbpptr, &tmpshort, sizeof(u_short));
cbpptr += sizeof(u_short);
tmpshort = align_short(bootp->bp_sectorspertrack);
memcpy(cbpptr, &tmpshort, sizeof(u_short));
cbpptr += sizeof(u_short);
tmpshort = align_short(bootp->bp_headcount);
memcpy(cbpptr, &tmpshort, sizeof(u_short));
cbpptr += sizeof(u_short);
tmpint = bootp->bp_hiddensectors;
ptr[VH_HSLLO] = (tmpint & 0x000000FF);
ptr[VH_HSLHI] = (tmpint & 0x0000FF00) >> 8;
ptr[VH_HSHLO] = (tmpint & 0x00FF0000) >> 16;
ptr[VH_HSHHI] = (tmpint & 0xFF000000) >> 24;
cbpptr += sizeof(u_int);
tmpint = bootp->bp_numsectors;
ptr[VH_SCLLO] = (tmpint & 0x000000FF);
ptr[VH_SCLHI] = (tmpint & 0x0000FF00) >> 8;
ptr[VH_SCHLO] = (tmpint & 0x00FF0000) >> 16;
ptr[VH_SCHHI] = (tmpint & 0xFF000000) >> 24;
cbpptr += sizeof(u_int);
return;
}
/*
*-----------------------------------------------------------------------------
* dos_init_fat()
* This routine is used to initialize the in-core fat.
*-----------------------------------------------------------------------------
*/
void dos_init_fat(dfs_t *dfs)
{
dfs->dfs_fat[0] = DOS_FATID;
dfs->dfs_fat[1] = 0xFF;
dfs->dfs_fat[2] = 0xFF;
dfs->dfs_fat[3] = 0xFF;
return;
}
/*
*-----------------------------------------------------------------------------
* dos_init_root()
* This routine is used to initialize the in-core root.
*-----------------------------------------------------------------------------
*/
void dos_init_root(dfs_t *dfs)
{
/* Duh, nothing to be done ?! */
return;
}
/*
*-----------------------------------------------------------------------------
* dos_print_bootp()
* This routine is used to print out the boot sector parameters.
*-----------------------------------------------------------------------------
*/
void dos_print_bootp(dfs_t *dfs, bp_t *bootp)
{
printf(" ----------------------------------------------------------\n");
printf(" BOOT SECTOR \n");
printf(" ----------------------------------------------------------\n");
printf(" dos_partaddr = %d\n", dfs->dfs_partaddr);
printf(" dos_fataddr1 = %d\n", dfs->dfs_fataddr1);
printf(" dos_fataddr2 = %d\n", dfs->dfs_fataddr2);
printf(" dos_fatsize = %d\n", dfs->dfs_fatsize);
printf(" dos_rootaddr = %d\n", dfs->dfs_rootaddr);
printf(" dos_rootsize = %d\n", dfs->dfs_rootsize);
printf(" dos_fileaddr = %d\n", dfs->dfs_fileaddr);
printf(" bp_magic[1] = %x\n", bootp->bp_magic[0]);
printf(" bp_magic[2] = %x\n", bootp->bp_magic[1]);
printf(" bp_magic[3] = %x\n", bootp->bp_magic[2]);
printf(" bp_oem = %s\n", bootp->bp_oem);
printf(" bp_sectorsize = %d\n", bootp->bp_sectorsize);
printf(" bp_sectorspercluster = %d\n", bootp->bp_sectorspercluster);
printf(" bp_reservecount = %d\n", bootp->bp_reservecount);
printf(" bp_fatcount = %d\n", bootp->bp_fatcount);
printf(" bp_rootentries = %d\n", bootp->bp_rootentries);
printf(" bp_sectorcount = %d\n", bootp->bp_sectorcount);
printf(" bp_mediatype = %d\n", bootp->bp_mediatype);
printf(" bp_fatsize = %d\n", bootp->bp_fatsize);
printf(" bp_sectorspertrack = %d\n", bootp->bp_sectorspertrack);
printf(" bp_headcount = %d\n", bootp->bp_headcount);
printf(" bp_hiddensectors = %d\n", bootp->bp_hiddensectors);
printf(" bp_numbrsectors = %d\n", bootp->bp_numsectors);
printf(" ----------------------------------------------------------\n");
return;
}
/*
*-----------------------------------------------------------------------------
* dos_time()
*-----------------------------------------------------------------------------
*/
void dos_time(u_char *d_date, u_char *d_time)
{
struct tm tm;
time_t mtime;
mtime = time(NULL);
tm = *localtime(&mtime);
d_date[0] = tm.tm_mday | (((tm.tm_mon + 1) & 0x7) << 5);
d_date[1] = ((tm.tm_mon + 1) >> 3) | ((tm.tm_year - 80) << 1);
d_time[0] = (tm.tm_sec / 2) | ((tm.tm_min & 0x7) << 5);
d_time[1] = (tm.tm_min >> 3) | (tm.tm_hour << 3);
return;
}
/*
*-----------------------------------------------------------------------------
* dos_check_label()
*-----------------------------------------------------------------------------
*/
void dos_check_label(char *outlabel, char *inlabel)
{
int retval = 0;
int count;
char vlabel[MAX_DOS_VOL_NAME];
char *strp;
/* blank the label with space character */
memset (vlabel, ' ', MAX_DOS_VOL_NAME);
/* check the illegal printable chars in the volume label */
if (strpbrk(inlabel, "*?/\\|.,;:+=<>[]()&^")){
strcpy(outlabel, "");
return;
}
count = 0;
while (*inlabel && count < MAX_DOS_VOL_NAME) {
if (!isprint(*inlabel)){
if (retval == 0){
strcpy(outlabel, "");
return;
}
}
else if (isspace(*inlabel) || *inlabel == '\t') {
vlabel[count++] = ' ';
inlabel = spaceskip(inlabel);
}
else vlabel[count++] = *inlabel++;
}
strncpy(outlabel, vlabel, MAX_DOS_VOL_NAME);
for (count = 0; count < MAX_DOS_VOL_NAME; count++)
outlabel[count] = toupper(outlabel[count]);
return;
}
/*
*-----------------------------------------------------------------------------
* dos_write_label()
* This routine is used to write out the volume label to disk.
*-----------------------------------------------------------------------------
*/
void dos_write_label(char *label, u_long label_addr)
{
u_char *buff;
dfile_t fentry;
char vlabel[MAX_DOS_VOL_NAME+1];
dos_check_label(vlabel, label);
if (!strcmp(vlabel, ""))
return;
buff = (u_char *) gmalloc(SECTOR_SIZE);
bzero(buff, SECTOR_SIZE);
bzero(&fentry, sizeof(fentry));
strncpy(fentry.df_name, vlabel, FILE_LEN);
if (strlen(vlabel) > FILE_LEN)
strncpy(fentry.df_ext, vlabel+FILE_LEN, EXTN_LEN);
fentry.df_attribute = ATTRIB_ARCHIVE | ATTRIB_LABEL;
dos_time(fentry.df_date, fentry.df_time);
memcpy(buff, &fentry, sizeof(fentry));
gseek(label_addr);
gwrite(buff, SECTOR_SIZE);
return;
}
/*
*-----------------------------------------------------------------------------
* compute_fatsize()
* This routine is used to compute the number of sectors that are to be
* reserved for the FAT.
*-----------------------------------------------------------------------------
*/
u_int compute_fatsize(u_int sect_count, u_int sect_reserved,
u_int sect_percluster, u_int dos_rootsize)
{
u_int dos_fatsize;
u_int num, den;
num = (sect_count-sect_reserved-dos_rootsize+2*sect_percluster);
den = (256*sect_percluster+2);
dos_fatsize = ceiling(num, den);
return (dos_fatsize);
}
/*
*-----------------------------------------------------------------------------
* compute_sectorspercluster()
* This routine is used to compute the number of sectors per cluster.
*-----------------------------------------------------------------------------
*/
u_int compute_sectorspercluster(u_int size)
{
u_int sect_count;
u_int sect_percluster;
sect_count = size/SECTOR_SIZE;
if (sect_count <= 64*K*4)
sect_percluster = 4;
else if (sect_count <= 64*K*8)
sect_percluster = 8;
else if (sect_count <= 64*K*16)
sect_percluster = 16;
else if (sect_count <= 64*K*32)
sect_percluster = 32;
else if (sect_count <= 64*K*64)
sect_percluster = 64;
else sect_percluster = 128;
return (sect_percluster);
}