📄 fcbfns.c
字号:
/****************************************************************//* *//* 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 "portab.h"#include "globals.h"#ifdef VERSION_STRINGSstatic BYTE *RcsId = "$Id: fcbfns.c,v 1.47 2004/07/25 08:04:54 bartoldeman Exp $";#endif#define FCB_SUCCESS 0#define FCB_ERR_NODATA 1#define FCB_ERR_SEGMENT_WRAP 2#define FCB_ERR_EOF 3#define FCB_ERROR 0xffSTATIC fcb FAR *ExtFcbToFcb(xfcb FAR * lpExtFcb);STATIC fcb FAR *CommonFcbInit(xfcb FAR * lpExtFcb, BYTE * pszBuffer, COUNT * pCurDrive);STATIC void FcbNameInit(fcb FAR * lpFcb, BYTE * pszBuffer, COUNT * pCurDrive);STATIC void FcbNextRecord(fcb FAR * lpFcb);STATIC void FcbCalcRec(xfcb FAR * lpXfcb);#define TestCmnSeps(lpFileName) (*lpFileName && strchr(":<|>+=,", *lpFileName) != NULL)#define TestFieldSeps(lpFileName) ((unsigned char)*lpFileName <= ' ' || strchr("/\"[]<>|.", *lpFileName) != NULL)static dmatch Dmatch;BYTE FAR *FatGetDrvData(UBYTE drive, UBYTE * pspc, UWORD * bps, UWORD * nc){ static BYTE mdb; UWORD spc; /* get the data available from dpb */ spc = DosGetFree(drive, NULL, bps, nc); if (spc != 0xffff) { struct dpb FAR *dpbp = get_dpb(drive == 0 ? default_drive : drive - 1); /* Point to the media desctriptor for this drive */ *pspc = (UBYTE)spc; if (dpbp == NULL) { mdb = spc >> 8; spc &= 0xff; return &mdb; } else { return (BYTE FAR *) & (dpbp->dpb_mdb); } } return NULL;}#define PARSE_SEP_STOP 0x01#define PARSE_DFLT_DRIVE 0x02#define PARSE_BLNK_FNAME 0x04#define PARSE_BLNK_FEXT 0x08#define PARSE_RET_NOWILD 0#define PARSE_RET_WILD 1#define PARSE_RET_BADDRIVE 0xff#ifndef IPLUWORD FcbParseFname(UBYTE *wTestMode, const BYTE FAR * lpFileName, fcb FAR * lpFcb){ WORD wRetCodeName = FALSE, wRetCodeExt = FALSE; /* 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)) { fmemset(lpFcb->fcb_fname, ' ', FNAME_SIZE); } if (!(*wTestMode & PARSE_BLNK_FEXT)) { fmemset(lpFcb->fcb_fext, ' ', FEXT_SIZE); } /* Undocumented behavior, set record number & record size to 0 */ lpFcb->fcb_cublock = 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) == ':') { /* non-portable construct to be changed */ REG UBYTE Drive = DosUpFChar(*lpFileName) - 'A'; if (Drive >= lastdrive) { *wTestMode = PARSE_RET_BADDRIVE; return FP_OFF(lpFileName); } lpFcb->fcb_drive = Drive + 1; lpFileName += 2; } /* special cases: '.' and '..' */ if (*lpFileName == '.') { lpFcb->fcb_fname[0] = '.'; ++lpFileName; if (*lpFileName == '.') { lpFcb->fcb_fname[1] = '.'; ++lpFileName; } *wTestMode = PARSE_RET_NOWILD; return FP_OFF(lpFileName); } /* Now to format the file name into the string */ lpFileName = GetNameField(lpFileName, (BYTE FAR *) lpFcb->fcb_fname, FNAME_SIZE, (BOOL *) & wRetCodeName); /* Do we have an extension? If do, format it else return */ if (*lpFileName == '.') lpFileName = GetNameField(++lpFileName, (BYTE FAR *) lpFcb->fcb_fext, FEXT_SIZE, (BOOL *) & wRetCodeExt); *wTestMode = (wRetCodeName | wRetCodeExt) ? PARSE_RET_WILD : PARSE_RET_NOWILD; return FP_OFF(lpFileName);}const BYTE FAR * ParseSkipWh(const BYTE FAR * lpFileName){ while (*lpFileName == ' ' || *lpFileName == '\t') ++lpFileName; return lpFileName;}#if 0 /* defined above */BOOL TestCmnSeps(BYTE FAR * lpFileName){ BYTE *pszTest, *pszCmnSeps = ":<|>+=,"; for (pszTest = pszCmnSeps; *pszTest != '\0'; ++pszTest) if (*lpFileName == *pszTest) return TRUE; return FALSE;}#endif#if 0BOOL TestFieldSeps(BYTE FAR * lpFileName){ BYTE *pszTest, *pszCmnSeps = "/\"[]<>|."; /* Another non-portable construct */ if (*lpFileName <= ' ') return TRUE; for (pszTest = pszCmnSeps; *pszTest != '\0'; ++pszTest) if (*lpFileName == *pszTest) return TRUE; return FALSE;}#endifconst BYTE FAR * GetNameField(const BYTE FAR * lpFileName, BYTE FAR * lpDestField, COUNT nFieldSize, BOOL * pbWildCard){ COUNT nIndex = 0; BYTE cFill = ' '; while (*lpFileName != '\0' && !TestFieldSeps(lpFileName) && nIndex < nFieldSize) { if (*lpFileName == ' ') break; if (*lpFileName == '*') { *pbWildCard = TRUE; cFill = '?'; ++lpFileName; break; } if (*lpFileName == '?') *pbWildCard = TRUE; *lpDestField++ = DosUpFChar(*lpFileName++); ++nIndex; } /* Blank out remainder of field on exit */ fmemset(lpDestField, cFill, nFieldSize - nIndex); return lpFileName;}STATIC VOID FcbNextRecord(fcb FAR * lpFcb){ if (++lpFcb->fcb_curec >= 128) { lpFcb->fcb_curec = 0; ++lpFcb->fcb_cublock; }}STATIC ULONG FcbRec(fcb FAR *lpFcb){ return ((ULONG) lpFcb->fcb_cublock * 128) + lpFcb->fcb_curec;}UBYTE FcbReadWrite(xfcb FAR * lpXfcb, UCOUNT recno, int mode){ ULONG lPosit; long nTransfer; fcb FAR *lpFcb; unsigned size; unsigned long bigsize; unsigned recsiz; /* Convert to fcb if necessary */ lpFcb = ExtFcbToFcb(lpXfcb); recsiz = lpFcb->fcb_recsiz; bigsize = (ULONG)recsiz * recno; if (bigsize > 0xffff) return FCB_ERR_SEGMENT_WRAP; size = (unsigned)bigsize; if (FP_OFF(dta) + size < FP_OFF(dta)) return FCB_ERR_SEGMENT_WRAP; /* Now update the fcb and compute where we need to position */ /* to. */ lPosit = FcbRec(lpFcb) * recsiz; if ((CritErrCode = -SftSeek(lpFcb->fcb_sftno, lPosit, 0)) != SUCCESS) return FCB_ERR_NODATA; /* Do the read */ nTransfer = DosRWSft(lpFcb->fcb_sftno, size, dta, mode & ~XFR_FCB_RANDOM); if (nTransfer < 0) CritErrCode = -(int)nTransfer; /* Now find out how we will return and do it. */ if (mode & XFR_WRITE) lpFcb->fcb_fsize = SftGetFsize(lpFcb->fcb_sftno); /* if end-of-file, then partial read should count last record */ if (mode & XFR_FCB_RANDOM && recsiz > 0) lpFcb->fcb_rndm += ((unsigned)nTransfer + recsiz - 1) / recsiz; size -= (unsigned)nTransfer; if (size == 0) { FcbNextRecord(lpFcb); return FCB_SUCCESS; } size %= lpFcb->fcb_recsiz; if (mode & XFR_READ && size > 0) { fmemset((char FAR *)dta + (unsigned)nTransfer, 0, size); FcbNextRecord(lpFcb); return FCB_ERR_EOF; } return FCB_ERR_NODATA;}UBYTE FcbGetFileSize(xfcb FAR * lpXfcb){ int FcbDrive, sft_idx; unsigned recsiz; /* Build a traditional DOS file name */ fcb FAR *lpFcb = CommonFcbInit(lpXfcb, SecPathName, &FcbDrive); recsiz = lpFcb->fcb_recsiz; /* check for a device */ if (!lpFcb || IsDevice(SecPathName) || (recsiz == 0)) return FCB_ERROR; sft_idx = (short)DosOpenSft(SecPathName, O_LEGACY | O_RDONLY | O_OPEN, 0); if (sft_idx >= 0) { ULONG fsize; /* Get the size */ fsize = SftGetFsize(sft_idx); /* compute the size and update the fcb */ lpFcb->fcb_rndm = (fsize + (recsiz - 1)) / recsiz; /* close the file and leave */ if ((CritErrCode = -DosCloseSft(sft_idx, FALSE)) == SUCCESS) return FCB_SUCCESS; } else CritErrCode = -sft_idx; return FCB_ERROR;}void FcbSetRandom(xfcb FAR * lpXfcb){ /* Convert to fcb if necessary */ fcb FAR *lpFcb = ExtFcbToFcb(lpXfcb); /* Now update the fcb and compute where we need to position */ /* to. */ lpFcb->fcb_rndm = FcbRec(lpFcb);}void FcbCalcRec(xfcb FAR * lpXfcb){ /* Convert to fcb if necessary */ fcb FAR *lpFcb = ExtFcbToFcb(lpXfcb); /* Now update the fcb and compute where we need to position */ /* to. */ lpFcb->fcb_cublock = (UWORD)(lpFcb->fcb_rndm / 128);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -