/****************************************************************/
/* */
/* fcbfns.c */
/* */
/* Old CP/M Style Function Handlers for Kernel */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C 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; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C 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 should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#include "../../hdr/portab.h"
#include "globals.h"
/* $Logfile: D:/dos-c/src/fs/fcbfns.c_v $ */
#ifndef IPL
static BYTE *RcsId = "$Header: D:/dos-c/src/fs/fcbfns.c_v 1.3 29 May 1996 21:15:14 patv $";
#endif
/*
* $Log: D:/dos-c/src/fs/fcbfns.c_v $
*
* Rev 1.3 29 May 1996 21:15:14 patv
* bug fixes for v0.91a
*
* Rev 1.2 01 Sep 1995 17:48:44 patv
* First GPL release.
*
* Rev 1.1 30 Jul 1995 20:50:26 patv
* Eliminated version strings in ipl
*
* Rev 1.0 02 Jul 1995 8:06:06 patv
* Initial revision.
*/
#define FCB_SUCCESS 0
#define FCB_ERR_NODATA 1
#define FCB_ERR_EOF 3
#define FCB_ERR_WRITE 1
#define D_ALL D_NORMAL | D_RDONLY | D_HIDDEN | D_SYSTEM | D_DIR | D_ARCHIVE
#ifdef PROTO
fcb FAR *ExtFcbToFcb(xfcb FAR *lpExtFcb);
fcb FAR *CommonFcbInit(xfcb FAR *lpExtFcb, BYTE *pszBuffer, COUNT *pCurDrive);
void FcbNameInit(fcb FAR *lpFcb, BYTE *pszBuffer, COUNT *pCurDrive);
sft FAR *FcbGetSft(COUNT SftIndex);
VOID FcbNextRecord(fcb FAR *lpFcb);
sft FAR *FcbGetFreeSft(WORD FAR *sft_idx);
BOOL FcbFnameMatch(BYTE FAR *s, BYTE FAR *d, COUNT n, COUNT mode);
BOOL FcbCharMatch(COUNT s, COUNT d, COUNT mode);
BOOL FcbCalcRec(xfcb FAR *lpXfcb);
VOID MoveDirInfo(dmatch FAR *lpDmatch, struct dirent FAR *lpDir);
#else
fcb FAR *ExtFcbToFcb();
fcb FAR *CommonFcbInit();
void FcbNameInit();
sft FAR *FcbGetSft();
VOID FcbNextRecord();
sft FAR *FcbGetFreeSft();
BOOL FcbFnameMatch();
BOOL FcbCharMatch();
BOOL FcbCalcRec();
VOID MoveDirInfo();
#endif
VOID DosOutputString(BYTE FAR *s)
{
while(*s != '$')
DosCharOutput(*s++);
}
static BYTE *con_name = "CON";
int DosCharInputEcho(VOID)
{
BYTE cb;
request rq;
rq.r_length = sizeof(request);
rq.r_command = C_INPUT;
rq.r_count = 1;
rq.r_trans = (VOID FAR *)&cb;
rq.r_status = 0;
execrh((request FAR *)&rq, syscon);
if(rq.r_status & S_ERROR)
return char_error(&rq, con_name);
DosCharOutput(cb);
return cb;
}
int DosCharInput(VOID)
{
BYTE cb;
request rq;
rq.r_length = sizeof(request);
rq.r_command = C_INPUT;
rq.r_count = 1;
rq.r_trans = (VOID FAR *)&cb;
rq.r_status = 0;
execrh((request FAR *)&rq, syscon);
if(rq.r_status & S_ERROR)
return char_error(&rq, con_name);
return cb;
}
VOID DosDirectConsoleIO(iregs FAR *r)
{
request rq;
BYTE buf;
if(r -> DL == 0xff)
{
r -> FLAGS &= ~FLG_ZERO;
rq.r_length = sizeof(request);
rq.r_command = C_ISTAT;
rq.r_status = 0;
execrh((request FAR *)&rq, syscon);
if(rq.r_status & S_ERROR)
{
char_error(&rq, con_name);
return;
}
if(rq.r_status & S_BUSY)
{
rq.r_length = sizeof(request);
rq.r_command = C_INPUT;
rq.r_count = 1;
rq.r_trans = (VOID FAR *)&buf;
rq.r_status = 0;
execrh((request FAR *)&rq, syscon);
if(rq.r_status & S_ERROR)
{
char_error(&rq, con_name);
return;
}
r -> AL = buf;
r -> FLAGS |= FLG_ZERO;
}
}
else
{
rq.r_length = sizeof(request);
rq.r_command = C_OUTPUT;
rq.r_count = 1;
rq.r_trans = (VOID FAR *)(&buf);
rq.r_status = 0;
execrh((request FAR *)&rq, syscon);
if(rq.r_status & S_ERROR)
char_error(&rq, con_name);
}
}
/* Console output with printer echo */
VOID DosCharOutput(COUNT c)
{
request rq;
BYTE buf = c;
/* Test for break first */
if(con_break())
return;
/* Now do an output directly to the console */
rq.r_length = sizeof(request);
rq.r_command = C_OUTPUT;
rq.r_count = 1;
rq.r_trans = (VOID FAR *)(&buf);
rq.r_status = 0;
execrh((request FAR *)&rq, syscon);
if(rq.r_status & S_ERROR)
char_error(&rq, con_name);
++scr_pos;
/* printer echo stuff */
}
VOID DosDisplayOutput(COUNT c)
{
/* Non-portable construct */
if(c < ' ' || c == 0x7f)
{
switch(c)
{
case '\r':
scr_pos = 0;
break;
case 0x7f:
++scr_pos;
break;
case '\b':
if(scr_pos > 0)
--scr_pos;
break;
case '\t':
do
DosCharOutput(' ');
while(scr_pos & 7);
return;
default:
break;
}
DosCharOutput(c);
}
else
{
DosCharOutput(c);
}
}
VOID
FatGetDrvData (COUNT drive, COUNT FAR *spc, COUNT FAR *bps, COUNT FAR *nc, BYTE FAR **mdp)
{
struct dpb *dpbp;
/* first check for valid drive */
if(drive < 0 || drive > NDEVS)
{
*spc = -1;
return;
}
/* next - "log" in the drive */
drive = (drive == 0 ? default_drive : drive - 1);
dpbp = &blk_devices[drive];
++(dpbp -> dpb_count);
dpbp -> dpb_flags = -1;
if((media_check(dpbp) < 0) || (dpbp -> dpb_count <= 0))
{
*spc = -1;
return;
}
/* get the data vailable from dpb */
*nc = (dpbp -> dpb_size - dpbp -> dpb_data + 1) / dpbp -> dpb_clssize;
*spc = dpbp -> dpb_clssize;
*bps = dpbp -> dpb_secsize;
/* Point to the media desctriptor fotr this drive */
*mdp = &(dpbp -> dpb_mdb);
--(dpbp -> dpb_count);
}
#ifndef IPL
WORD FcbParseFname(wTestMode, lpFileName, lpFcb)
REG WORD wTestMode;
BYTE FAR **lpFileName;
fcb FAR *lpFcb;
{
COUNT nIndex;
WORD wRetCode = PARSE_RET_NOWILD;
/* pjv -- ExtFcbToFcb? */
/* Start out with some simple stuff first. Check if we are */
/* going to use a default drive specificaton. */
if(!(wTestMode & PARSE_DFLT_DRIVE))
lpFcb -> fcb_drive = FDFLT_DRIVE;
if(!(wTestMode & PARSE_BLNK_FNAME))
{
for(nIndex = 0; nIndex < FNAME_SIZE; ++nIndex)
lpFcb -> fcb_fname[nIndex] = ' ';
}
if(!(wTestMode & PARSE_BLNK_FEXT))
{
for(nIndex = 0; nIndex < FEXT_SIZE; ++nIndex)
lpFcb -> fcb_fext[nIndex] = ' ';
}
/* Undocumented behavior, set record number & record size to 0 */
lpFcb -> fcb_curec = lpFcb -> fcb_recsiz = 0;
if(!(wTestMode & PARSE_SEP_STOP))
{
*lpFileName = ParseSkipWh(*lpFileName);
if(TestCmnSeps(*lpFileName))
++*lpFileName;
}
/* Undocumented "feature," we skip white space anyway */
*lpFileName = ParseSkipWh(*lpFileName);
/* Now check for drive specification */
if(*(*lpFileName + 1) == ':')
{
REG BYTE Drive = **lpFileName;
/* non-portable construct to be changed */
if(Drive < 'A' || Drive > 'Z')
return PARSE_RET_BADDRIVE;
Drive -= ('A' - 1);
if(Drive > nblkdev)
return PARSE_RET_BADDRIVE;
else
lpFcb -> fcb_drive = Drive;
*lpFileName += 2;
}
/* Now to format the file name into the string */
*lpFileName = GetNameField(*lpFileName, (BYTE FAR *)lpFcb -> fcb_fname, FNAME_SIZE, (BOOL *)&wRetCode);
/* Do we have an extension? If do, format it else return */
if(**lpFileName == '.')
*lpFileName = GetNameField(++*lpFileName, (BYTE FAR *)lpFcb -> fcb_fext, FEXT_SIZE, (BOOL *)&wRetCode);
return wRetCode ? PARSE_RET_WILD : PARSE_RET_NOWILD;
}
BYTE FAR *
ParseSkipWh (BYTE FAR *lpFileName)
{
while(*lpFileName == ' ' || *lpFileName == '\t')
++lpFileName;
return lpFileName;
}
BOOL
TestCmnSeps (BYTE FAR *lpFileName)
{
BYTE *pszTest, *pszCmnSeps = ":<|>+=,";
for(pszTest = pszCmnSeps; *pszTest != '\0'; ++pszTest)
if(*lpFileName == *pszTest)
return TRUE;
return FALSE;
}
BOOL
TestFieldSeps (BYTE FAR *lpFileName)
{
BYTE *pszTest, *pszCmnSeps = "/\"[]<>|.";
/* Another non-portable construct */
if(*lpFileName < ' ')
return FALSE;
for(pszTest = pszCmnSeps; *pszTest != '\0'; ++pszTest)
if(*lpFileName == *pszTest)
return TRUE;
return FALSE;
}
BYTE FAR *
GetNameField (BYTE FAR *lpFileName, BYTE FAR *lpDestField, COUNT nFieldSize, BOOL *pbWildCard)
{
COUNT nIndex = 0;
BYTE cFill = ' ';
*pbWildCard = FALSE;
while(*lpFileName != '\0' && !TestFieldSeps(lpFileName) && nIndex< nFieldSize)
{
if(*lpFileName == ' ')
break;
if(*lpFileName == '*')
{
*pbWildCard = TRUE;
cFill = '?';
++lpFileName;
break;
}
if(*lpFileName == '?')
*pbWildCard = TRUE;
*lpDestField++ = *lpFileName++;
++nIndex;
}
/* Blank out remainder of field on exit */
for( ; nIndex < nFieldSize; ++nIndex)
*lpDestField++ = cFill;
return lpFileName;
}
static sft FAR *FcbGetSft(SftIndex)
COUNT SftIndex;
{
sfttbl FAR *lpSftEntry;
/* Get the SFT block that contains the SFT */
for(lpSftEntry = sfthead; lpSftEntry != (sfttbl FAR *)-1;
lpSftEntry = lpSftEntry -> sftt_next)
{
if(SftIndex < lpSftEntry -> sftt_count)
break;
else
SftIndex -= lpSftEntry -> sftt_count;
}
/* If not found, return an error */
if(lpSftEntry == (sfttbl FAR *)-1)
return (sft FAR *)-1;
/* finally, point to the right entry */
return (sft FAR *)&(lpSftEntry -> sftt_table[SftIndex]);
}
static VOID FcbNextRecord(lpFcb)
fcb FAR *lpFcb;
{
if(++lpFcb -> fcb_curec > 128)
{
lpFcb -> fcb_curec = 0;
++lpFcb -> fcb_cublock;
}
}
BOOL FcbRead(lpXfcb, nErrorCode)
xfcb FAR *lpXfcb;
COUNT *nErrorCode;
{
sft FAR *s;
fcb FAR *lpFcb;
LONG lPosit;
COUNT nRead;
psp FAR *p = MK_FP(cu_psp,0);
/* Convert to fcb if necessary */
lpFcb = ExtFcbToFcb(lpXfcb);
/* Get the SFT block that contains the SFT */
if((s = FcbGetSft(lpFcb -> fcb_sftno)) == (sft FAR *)-1)
return FALSE;
/* If this is not opened another error */
if(s -> sft_count == 0)
return FALSE;
/* Now update the fcb and compute where we need to position */
/* to. */
lPosit = ((lpFcb -> fcb_cublock * 128) + lpFcb -> fcb_curec)
* lpFcb -> fcb_recsiz;
if(dos_lseek(s -> sft_status, lPosit, 0) < 0)
{
*nErrorCode = FCB_ERR_EOF;
return FALSE;
}
/* Do the read */
nRead = dos_read(s -> sft_status,
p -> ps_dta, lpFcb -> fcb_recsiz);
/* Now find out how we will return and do it. */
if(nRead == lpFcb -> fcb_recsiz)
{
*nErrorCode = FCB_SUCCESS;
FcbNextRecord(lpFcb);
return TRUE;
}
else if(nRead < 0)
{
*nErrorCode = FCB_ERR_EOF;
return TRUE;
}
else if(nRead == 0)
{
*nErrorCode = FCB_ERR_NODATA;
return FALSE;
}
else
{
COUNT nIdx, nCount;
BYTE FAR *lpDta;
nCount = lpFcb -> fcb_recsiz - nRead;
lpDta = (BYTE FAR *)&(p -> ps_dta[nRead]);
for(nIdx = 0; nIdx < nCount; nIdx++)
*lpDta++ = 0;
*nErrorCode = FCB_ERR_EOF;
FcbNextRecord(lpFcb);
return FALSE;
}
}
BOOL FcbWrite(lpXfcb, nErrorCode)
xfcb FAR *lpXfcb;
COUNT *nErrorCode;
{
sft FAR *s;
fcb FAR *lpFcb;
LONG lPosit;
COUNT nWritten;
psp FAR *p = MK_FP(cu_psp,0);
/* Convert to fcb if necessary */
lpFcb = ExtFcbToFcb(lpXfcb);
/* Get the SFT block that contains the SFT */
if((s = FcbGetSft(lpFcb -> fcb_sftno)) == (sft FAR *)-1)
return FALSE;
/* If this is not opened another error */
if(s -> sft_count == 0)
return FALSE;
/* Now update the fcb and compute where we need to position */
/* to. */
lPosit = ((lpFcb -> fcb_cublock * 128) + lpFcb -> fcb_curec)
* lpFcb -> fcb_recsiz;
if(dos_lseek(s -> sft_status, lPosit, 0) < 0)
{
*nErrorCode = FCB_ERR_EOF;
return FALSE;
}
/* Do the read */
nWritten = dos_write(s -> sft_status,
p -> ps_dta, lpFcb -> fcb_recsiz);
/* Now find out how we will return and do it. */
if(nWritten == lpFcb -> fcb_recsiz)
{
lpFcb -> fcb_fsize = dos_getcufsize(s -> sft_status);
FcbNextRecord(lpFcb);
*nErrorCode = FCB_SUCCESS;
return TRUE;
}
else if(nWritten <= 0)
{
*nErrorCode = FCB_ERR_WRITE;
return TRUE;
}
*nErrorCode = FCB_ERR_WRITE;
return FALSE;
}
BOOL FcbGetFileSize(lpXfcb)
xfcb FAR *lpXfcb;
{
BYTE buff[FNAME_SIZE+FEXT_SIZE + 3];
fcb FAR *lpFcb;
COUNT FcbDrive, FileNum;
/* Build a traditional DOS file name */
lpFcb = CommonFcbInit(lpXfcb, buff, &FcbDrive);
/* check for a device */
/* if we have an extension, can't be a device */
if(IsDevice(buff) || (lpFcb -> fcb_recsiz == 0))
{
return FALSE;
}
FileNum = dos_open(buff, O_RDONLY);
if(FileNum >= 0)
{
LONG fsize;
/* Get the size */
fsize = dos_getfsize(FileNum);
/* compute the size and update the fcb */
lpFcb -> fcb_rndm = fsize / lpFcb -> fcb_recsiz;
if((fsize % lpFcb -> fcb_recsiz) != 0)
++lpFcb -> fcb_rndm;
/* close the file and leave */
return dos_close(FileNum) == SUCCESS;
}
else
return FALSE;
}
BOOL FcbSetRandom(lpXfcb)
xfcb FAR *lpXfcb;
{
fcb FAR *lpFcb;
LONG lPosit;
/* Convert to fcb if necessary */
lpFcb = ExtFcbToFcb(lpXfcb);
/* Now update the fcb and compute where we need to position */
/* to. */
lpFcb -> fcb_rndm = (lpFcb -> fcb_cublock * 128)
+ lpFcb -> fcb_curec;
return TRUE;
}
BOOL FcbCalcRec(lpXfcb)
xfcb FAR *lpXfcb;
{
fcb FAR *lpFcb;
LONG lPosit;
/* Convert to fcb if necessary */
lpFcb = ExtFcbToFcb(lpXfcb);
/* Now update the fcb and compute where we need to position */
/* to. */
lpFcb -> fcb_cublock = lpFcb -> fcb_rndm / 128;
lpFcb -> fcb_curec = lpFcb -> fcb_rndm % 128;
return TRUE;
}
BOOL FcbRandomBlockRead(lpXfcb, nRecords, nErrorCode)
xfcb FAR *lpXfcb;
COUNT nRecords;
COUNT *nErrorCode;
{
fcb FAR *lpFcb;
FcbCalcRec(lpXfcb);
/* Convert to fcb if necessary */
lpFcb = ExtFcbToFcb(lpXfcb);
do
FcbRead(lpXfcb, nErrorCode);
while ((--nRecords > 0) && (*nErrorCode == 0));
/* Now update the fcb */
lpFcb -> fcb_rndm = lpFcb -> fcb_cublock * 128 + lpFcb -> fcb_curec;
return TRUE;
}
BOOL FcbRandomBlockWrite(lpXfcb, nRecords, nErrorCode)
xfcb FAR *lpXfcb;
COUNT nRecords;
COUNT *nErrorCode;
{
fcb FAR *lpFcb;
FcbCalcRec(lpXfcb);
/* Convert to fcb if necessary */
lpFcb = ExtFcbToFcb(lpXfcb);
do
FcbWrite(lpXfcb, nErrorCode);
while ((--nRecords > 0) && (*nErrorCode == 0));
/* Now update the fcb */
lpFcb -> fcb_rndm = lpFcb -> fcb_cublock * 128 + lpFcb -> fcb_curec;
return TRUE;
}
BOOL FcbRandomRead(lpXfcb, nErrorCode)
xfcb FAR *lpXfcb;
COUNT *nErrorCode;
{
UWORD uwCurrentBlock;
UBYTE ucCurrentRecord;
fcb FAR *lpFcb;
FcbCalcRec(lpXfcb);
/* Convert to fcb if necessary */
lpFcb = ExtFcbToFcb(lpXfcb);
uwCurrentBlock = lpFcb -> fcb_cublock;
ucCurrentRecord = lpFcb -> fcb_curec;
FcbRead(lpXfcb, nErrorCode);
lpFcb -> fcb_cublock = uwCurrentBlock;
lpFcb -> fcb_curec = ucCurrentRecord;
return TRUE;
}
BOOL FcbRandomWrite(lpXfcb, nErrorCode)
xfcb FAR *lpXfcb;
COUNT *nErrorCode;
{
UWORD uwCurrentBlock;
UBYTE ucCurrentRecord;
fcb FAR *lpFcb;
FcbCalcRec(lpXfcb);
/* Convert to fcb if necessary */
lpFcb = ExtFcbToFcb(lpXfcb);
uwCurrentBlock = lpFcb -> fcb_cublock;
ucCurrentRecord = lpFcb -> fcb_curec;
FcbWrite(lpXfcb, nErrorCode);
lpFcb -> fcb_cublock = uwCurrentBlock;
lpFcb -> fcb_curec = ucCurrentRecord;
return TRUE;
}
static sft FAR *FcbGetFreeSft(sft_idx)
WORD FAR *sft_idx;
{
WORD sys_idx = 0;
sfttbl FAR *sp;
/* Get the SFT block that contains the SFT */
for(sp = sfthead; sp != (sfttbl FAR *)-1; sp = sp -> sftt_next)
{
REG WORD i;
for(i = 0; i < sp -> sftt_count; i++)
{
if(sp -> sftt_table[i].sft_count == 0)
{
*sft_idx = sys_idx + i;
return (sft FAR *)&sp -> sftt_table[sys_idx + i];
}
}
sys_idx += i;
}
/* If not found, return an error */
return (sft FAR *)-1;
}
BOOL FcbCreate(lpXfcb)
xfcb FAR *lpXfcb;
{
WORD sft_idx;
sft FAR *sftp;
struct dhdr FAR *dhp;
BYTE buff[FNAME_SIZE+FEXT_SIZE + 3];
fcb FAR *lpFcb;
COUNT FcbDrive;
/* get a free system file table entry */
if((sftp = FcbGetFreeSft((WORD FAR *)&sft_idx)) == (sft FAR *)-1)
return DE_TOOMANY;
/* Build a traditional DOS file name */
lpFcb = CommonFcbInit(lpXfcb, buff, &FcbDrive);
/* check for a device */
/* if we have an extension, can't be a device */
if(IsDevice(buff))
{
for(dhp = (struct dhdr FAR *)&nul_dev; dhp != (struct dhdr FAR *)-1; dhp = dhp -> dh_next)
{
if(FcbFnameMatch((BYTE FAR *)buff, (BYTE FAR *)dhp -> dh_name, FNAME_SIZE, FALSE))
{
sftp -> sft_count += 1;
sftp -> sft_mode = O_RDWR;
sftp -> sft_attrib = 0;
sftp -> sft_flags =
(dhp -> dh_attr & ~SFT_MASK) | SFT_FDEVICE | SFT_FEOF;
sftp -> sft_psp = cu_psp;
fbcopy(lpFcb -> fcb_fname, sftp -> sft_name, FNAME_SIZE+FEXT_SIZE);
sftp -> sft_dev = dhp;
lpFcb -> fcb_sftno = sft_idx;
lpFcb -> fcb_curec = 0;
lpFcb -> fcb_recsiz = 0;
lpFcb -> fcb_fsize = 0;
lpFcb -> fcb_date = dos_getdate();
lpFcb -> fcb_time = dos_gettime();
lpFcb -> fcb_rndm = 0;
return TRUE;
}
}
}
sftp -> sft_status = dos_creat(buff, 0);
if(sftp -> sft_status >= 0)
{
lpFcb -> fcb_drive = FcbDrive;
lpFcb -> fcb_sftno = sft_idx;
lpFcb -> fcb_curec = 0;
lpFcb -> fcb_recsiz = 128;
lpFcb -> fcb_fsize = 0;
lpFcb -> fcb_date = dos_getdate();
lpFcb -> fcb_time = dos_gettime();
lpFcb -> fcb_rndm = 0;
sftp -> sft_count += 1;
sftp -> sft_mode = O_RDWR;
sftp -> sft_attrib = 0;
sftp -> sft_flags = 0;
sftp -> sft_psp = cu_psp;
fbcopy((BYTE FAR *)&lpFcb -> fcb_fname, (BYTE FAR *)&sftp -> sft_name, FNAME_SIZE+FEXT_SIZE);
return TRUE;
}
else
return FALSE;
}
static fcb FAR *ExtFcbToFcb(xfcb FAR *lpExtFcb)
{
if(*((UBYTE FAR *)lpExtFcb) == 0xff)
return &lpExtFcb -> xfcb_fcb;
else
return (fcb FAR *)lpExtFcb;
}
static fcb FAR *CommonFcbInit(lpExtFcb, pszBuffer, pCurDrive)
xfcb FAR *lpExtFcb;
BYTE *pszBuffer;
COUNT *pCurDrive;
{
BYTE FAR *lpszFcbFname, *lpszFcbFext;
BYTE buff[FNAME_SIZE+FEXT_SIZE + 3];
COUNT nDrvIdx, nFnameIdx, nFextIdx;
fcb FAR *lpFcb;
/* convert to fcb if needed first */
lpFcb = ExtFcbToFcb(lpExtFcb);
/* Build a traditional DOS file name */
FcbNameInit(lpFcb, pszBuffer, pCurDrive);
/* and return the fcb pointer */
return lpFcb;
}
void FcbNameInit(lpFcb, pszBuffer, pCurDrive)
fcb FAR *lpFcb;
BYTE *pszBuffer;
COUNT *pCurDrive;
{
BYTE FAR *lpszFcbFname, FAR *lpszFcbFext;
BYTE buff[FNAME_SIZE+FEXT_SIZE+4]; /* "a:" + '.' + 0 */
COUNT nDrvIdx, nFnameIdx, nFextIdx;
/* Build a traditional DOS file name */
lpszFcbFname = (BYTE FAR *)lpFcb -> fcb_fname;
if(lpFcb -> fcb_drive != 0)
{
*pCurDrive = lpFcb -> fcb_drive;
pszBuffer[0] = 'A' + lpFcb -> fcb_drive - 1;
pszBuffer[1] = ':';
nDrvIdx = 2;
}
else
{
*pCurDrive = default_drive + 1;
nDrvIdx = 0;
}
for(nFnameIdx = 0; nFnameIdx < FNAME_SIZE; nFnameIdx++)
{
if(*lpszFcbFname != ' ')
pszBuffer[nDrvIdx + nFnameIdx] = *lpszFcbFname++;
else
break;
}
lpszFcbFext = (BYTE FAR *)lpFcb -> fcb_fext;
if(*lpszFcbFext != ' ')
{
pszBuffer[nDrvIdx + nFnameIdx++] = '.';
for(nFextIdx = 0; nFextIdx < FEXT_SIZE; nFextIdx++)
{
if(*lpszFcbFext != ' ')
pszBuffer[nDrvIdx + nFnameIdx + nFextIdx] =
*lpszFcbFext++;
else
break;
}
}
else
nFextIdx = 0;
pszBuffer[nDrvIdx + nFnameIdx + nFextIdx] = '\0';
}
/* Ascii only file name match routines */
static BOOL
FcbCharMatch (COUNT s, COUNT d, COUNT mode)
{
if(s >= 'a' && s <= 'z')
s -= 'a' - 'A';
if(d >= 'a' && d <= 'z')
d -= 'a' - 'A';
if(mode && s == '?' && (d >= 'A' && s <= 'Z'))
return TRUE;
return s == d;
}
static BOOL
FcbFnameMatch (BYTE FAR *s, BYTE FAR *d, COUNT n, COUNT mode)
{
while(n--)
{
if(!FcbCharMatch(*s++, *d++, mode))
return FALSE;
}
return TRUE;
}
BOOL FcbOpen(lpXfcb)
xfcb FAR *lpXfcb;
{
WORD sft_idx;
sft FAR *sftp;
struct dhdr FAR *dhp;
BYTE buff[FNAME_SIZE+FEXT_SIZE + 3];
fcb FAR *lpFcb;
COUNT FcbDrive;
/* get a free system file table entry */
if((sftp = FcbGetFreeSft((WORD FAR *)&sft_idx)) == (sft FAR *)-1)
return DE_TOOMANY;
/* Build a traditional DOS file name */
lpFcb = CommonFcbInit(lpXfcb, buff, &FcbDrive);
/* check for a device */
/* if we have an extension, can't be a device */
if(IsDevice(buff))
{
for(dhp = (struct dhdr FAR *)&nul_dev; dhp != (struct dhdr FAR *)-1; dhp = dhp -> dh_next)
{
if(FcbFnameMatch((BYTE FAR *)buff, (BYTE FAR *)dhp -> dh_name, FNAME_SIZE, FALSE))
{
sftp -> sft_count += 1;
sftp -> sft_mode = O_RDWR;
sftp -> sft_attrib = 0;
sftp -> sft_flags =
(dhp -> dh_attr & ~SFT_MASK) | SFT_FDEVICE | SFT_FEOF;
sftp -> sft_psp = cu_psp;
fbcopy(lpFcb -> fcb_fname, sftp -> sft_name, FNAME_SIZE+FEXT_SIZE);
sftp -> sft_dev = dhp;
lpFcb -> fcb_sftno = sft_idx;
lpFcb -> fcb_curec = 0;
lpFcb -> fcb_recsiz = 0;
lpFcb -> fcb_fsize = 0;
lpFcb -> fcb_date = dos_getdate();
lpFcb -> fcb_time = dos_gettime();
lpFcb -> fcb_rndm = 0;
return TRUE;
}
}
}
sftp -> sft_status = dos_open(buff, O_RDWR);
if(sftp -> sft_status >= 0)
{
lpFcb -> fcb_drive = FcbDrive;
lpFcb -> fcb_sftno = sft_idx;
lpFcb -> fcb_curec = 0;
lpFcb -> fcb_recsiz = 128;
lpFcb -> fcb_fsize = dos_getfsize(sftp -> sft_status);
dos_getftime(sftp -> sft_status,
(date FAR *)&lpFcb -> fcb_date,
(time FAR *)&lpFcb -> fcb_time);
lpFcb -> fcb_rndm = 0;
sftp -> sft_count += 1;
sftp -> sft_mode = O_RDWR;
sftp -> sft_attrib = 0;
sftp -> sft_flags = 0;
sftp -> sft_psp = cu_psp;
fbcopy((BYTE FAR *)&lpFcb -> fcb_fname, (BYTE FAR *)&sftp -> sft_name, FNAME_SIZE+FEXT_SIZE);
return TRUE;
}
else
return FALSE;
}
BOOL FcbDelete(lpXfcb)
xfcb FAR *lpXfcb;
{
BYTE buff[FNAME_SIZE+FEXT_SIZE + 3];
COUNT FcbDrive;
/* Build a traditional DOS file name */
CommonFcbInit(lpXfcb, buff, &FcbDrive);
/* check for a device */
/* if we have an extension, can't be a device */
if(IsDevice(buff))
{
return FALSE;
}
else
{
BYTE FAR *lpOldDta = dta;
dmatch Dmatch;
dta = (BYTE FAR *)&Dmatch;
if(dos_findfirst(D_ALL, buff[1] == ':' ? &buff[2] : buff) != SUCCESS)
{
dta = lpOldDta;
return FALSE;
}
do
{
if(dos_delete(Dmatch.dm_name) != SUCCESS)
{
dta = lpOldDta;
return FALSE;
}
}
while(dos_findnext() == SUCCESS);
dta = lpOldDta;
return TRUE;
}
}
BOOL FcbRename(lpXfcb)
xfcb FAR *lpXfcb;
{
BYTE buff[FNAME_SIZE+FEXT_SIZE+4];
rfcb FAR *lpRenameFcb;
COUNT FcbDrive;
/* Build a traditional DOS file name */
lpRenameFcb = (rfcb FAR *)CommonFcbInit(lpXfcb, buff, &FcbDrive);
/* check for a device */
/* if we have an extension, can't be a device */
if(IsDevice(buff))
{
return FALSE;
}
else
{
BYTE FAR *lpOldDta = dta;
dmatch Dmatch;
dta = (BYTE FAR *)&Dmatch;
if(dos_findfirst(D_ALL, buff[1] == ':' ? &buff[2] : buff) != SUCCESS)
{
dta = lpOldDta;
return FALSE;
}
do
{
BYTE ToName[FNAME_SIZE + FEXT_SIZE + 2]; /* '.' & 0 */
fcb LocalFcb;
BYTE *pToName, *pszFrom;
BYTE FAR *pFromPattern;
COUNT nIndex;
/* First, expand the find match into fcb style */
/* file name entry */
/* Fill with blanks first */
for(pToName = LocalFcb.fcb_fname, nIndex = 0;
nIndex < FNAME_SIZE; nIndex++)
{
*pToName++ = ' ';
}
for(pToName = LocalFcb.fcb_fext, nIndex = 0;
nIndex < FEXT_SIZE; nIndex++)
{
*pToName++ = ' ';
}
/* next move in the file name while overwriting */
/* the filler blanks */
pszFrom = Dmatch.dm_name;
pToName = LocalFcb.fcb_fname;
for(nIndex = 0; nIndex < FNAME_SIZE; nIndex++)
{
if(*pszFrom != 0 && *pszFrom != '.')
*pToName++ = *pszFrom++;
else if(*pszFrom == '.')
{
++pszFrom;
break;
}
else
break;
}
if(*pszFrom != '\0')
{
pToName = LocalFcb.fcb_fext;
for(nIndex = 0; nIndex < FEXT_SIZE; nIndex++)
{
if(*pszFrom != '\0')
*pToName++ = *pszFrom++;
else
break;
}
}
/* Overlay the pattern, skipping '?' */
/* I'm cheating because this assumes that the */
/* struct alignments are on byte boundaries */
pToName = LocalFcb.fcb_fname;
for(pFromPattern = lpRenameFcb -> renNewName,
nIndex = 0; nIndex < FNAME_SIZE + FEXT_SIZE; nIndex++)
{
if(*pFromPattern != '?')
*pToName++ = *pFromPattern++;
else
++pFromPattern;
}
/* now to build a dos name again */
LocalFcb.fcb_drive = 0;
FcbNameInit((fcb FAR *)&LocalFcb, buff, &FcbDrive);
if(dos_rename(Dmatch.dm_name,
buff[1] == ':' ? &buff[2] : buff) != SUCCESS)
{
dta = lpOldDta;
return FALSE;
}
}
while(dos_findnext() == SUCCESS);
dta = lpOldDta;
return TRUE;
}
}
void MoveDirInfo(lpDmatch, lpDir)
dmatch FAR *lpDmatch;
struct dirent FAR *lpDir;
{
BYTE FAR *lpToName, FAR *lpszFrom;
COUNT nIndex;
/* First, expand the find match into dir style */
/* file name entry */
/* Fill with blanks first */
for(lpToName = lpDir -> dir_name, nIndex = 0;
nIndex < FNAME_SIZE; nIndex++)
{
*lpToName++ = ' ';
}
for(lpToName = lpDir -> dir_ext, nIndex = 0;
nIndex < FEXT_SIZE; nIndex++)
{
*lpToName++ = ' ';
}
/* next move in the file name while overwriting */
/* the filler blanks */
lpszFrom = lpDmatch -> dm_name;
lpToName = lpDir -> dir_name;
for(nIndex = 0; nIndex < FNAME_SIZE; nIndex++)
{
if(*lpszFrom != 0 && *lpszFrom != '.')
*lpToName++ = *lpszFrom++;
else
break;
}
if(*lpszFrom != '\0')
{
if(*lpszFrom == '.')
++lpszFrom;
lpToName = lpDir -> dir_ext;
for(nIndex = 0; nIndex < FEXT_SIZE; nIndex++)
{
if(*lpszFrom != '\0')
*lpToName++ = *lpszFrom++;
else
break;
}
}
for(nIndex = 0; nIndex < 10; nIndex++)
lpDir -> dir_reserved[nIndex] = 0;
lpDir -> dir_attrib = lpDmatch ->dm_attr_fnd;
lpDir -> dir_time = lpDmatch ->dm_time;
lpDir -> dir_date = lpDmatch ->dm_date;
lpDir -> dir_start = lpDmatch ->dm_cluster;
lpDir -> dir_size = lpDmatch ->dm_size;
}
BOOL FcbClose(lpXfcb)
xfcb FAR *lpXfcb;
{
sft FAR *s;
fcb FAR *lpFcb;
/* Convert to fcb if necessary */
lpFcb = ExtFcbToFcb(lpXfcb);
/* Get the SFT block that contains the SFT */
if((s = FcbGetSft(lpFcb -> fcb_sftno)) == (sft FAR *)-1)
return FALSE;
/* If this is not opened another error */
if(s -> sft_count == 0)
return FALSE;
/* now just drop the count if a device, else */
/* call file system handler */
if(s -> sft_flags & SFT_FDEVICE)
{
s -> sft_count -= 1;
return TRUE;
}
else
{
s -> sft_count -= 1;
if(s -> sft_count > 0)
return SUCCESS;
else
{
/* change time and set file size */
dos_setftime(s -> sft_status,
(date FAR *)&lpFcb -> fcb_date,
(time FAR *)&lpFcb -> fcb_time);
dos_setfsize(s -> sft_status,
lpFcb -> fcb_fsize);
return dos_close(s -> sft_status) == SUCCESS;
}
}
}
BOOL FcbFindFirst(lpXfcb)
xfcb FAR *lpXfcb;
{
BYTE FAR *lpOldDta;
dmatch Dmatch;
struct dirent FAR *lpDir;
COUNT nIdx, FcbDrive;
fcb FAR *lpFcb;
BYTE Buffer[FNAME_SIZE+FEXT_SIZE+4];
WORD wAttr;
psp FAR *lpPsp = MK_FP(cu_psp,0);
/* First, move the dta to a local and change it around to match */
/* our functions. */
lpDir = (struct dirent FAR *)dta;
dta = (BYTE FAR *)&Dmatch;
/* Next initialze local variables by moving them from the fcb */
lpFcb = CommonFcbInit(lpXfcb, Buffer, &FcbDrive);
if(lpXfcb -> xfcb_flag == 0xff)
wAttr = lpXfcb -> xfcb_attrib;
else
wAttr = D_ALL;
if(dos_findfirst(wAttr, Buffer[1] == ':' ? &Buffer[2] : Buffer) != SUCCESS)
{
dta = lpPsp -> ps_dta;
return FALSE;
}
MoveDirInfo((dmatch FAR *)&Dmatch, lpDir);
lpFcb -> fcb_dirclst = Dmatch.dm_cluster;
lpFcb -> fcb_diroff = Dmatch.dm_entry;
dta = lpPsp -> ps_dta;
return TRUE;
}
BOOL FcbFindNext(lpXfcb)
xfcb FAR *lpXfcb;
{
BYTE FAR *lpOldDta;
dmatch Dmatch;
struct dirent FAR *lpDir;
COUNT nIdx, FcbDrive;
fcb FAR *lpFcb;
BYTE Buffer[FNAME_SIZE+FEXT_SIZE+4];
WORD wAttr;
psp FAR *lpPsp = MK_FP(cu_psp,0);
/* First, move the dta to a local and change it around to match */
/* our functions. */
lpDir = (struct dirent FAR *)dta;
dta = (BYTE FAR *)&Dmatch;
/* Next initialze local variables by moving them from the fcb */
lpFcb = CommonFcbInit(lpXfcb, Buffer, &FcbDrive);
if((xfcb FAR *)lpFcb != lpXfcb)
wAttr = lpXfcb -> xfcb_attrib;
else
wAttr = D_ALL;
/* Reconstrct the dirmatch structure from the fcb */
Dmatch.dm_drive = FcbDrive;
fbcopy(lpFcb -> fcb_fname, (BYTE FAR *)Dmatch.dm_name_pat, FNAME_SIZE+FEXT_SIZE);
upMem((BYTE FAR *)Dmatch.dm_name_pat, FNAME_SIZE+FEXT_SIZE);
Dmatch.dm_attr_srch = wAttr;
Dmatch.dm_entry = lpFcb -> fcb_diroff;
Dmatch.dm_cluster = lpFcb -> fcb_dirclst;
if(dos_findnext() != SUCCESS)
{
dta = lpPsp -> ps_dta;
return FALSE;
}
MoveDirInfo((dmatch FAR *)&Dmatch, lpDir);
lpFcb -> fcb_dirclst = Dmatch.dm_cluster;
lpFcb -> fcb_diroff = Dmatch.dm_entry;
dta = lpPsp -> ps_dta;
return TRUE;
}
#endif