📄 fstask.c
字号:
/* *---------------------------------------------------------------------- * T-Kernel / Standard Extension * * Copyright (C) 2006 by Ken Sakamura. All rights reserved. * T-Kernel / Standard Extension is distributed * under the T-License for T-Kernel / Standard Extension. *---------------------------------------------------------------------- * * Version: 1.00.00 * Released by T-Engine Forum(http://www.t-engine.org) at 2006/8/11. * *---------------------------------------------------------------------- *//* * fstask.c (file) * * File management * File system task (Individual section task) */#include "fsinfo.h"#include "filesys.h"#include "fileio.h"#include "others.h"#include "diskio.h"LOCAL ER fmpGetFileSystemInfo( FsInfo *fsinfo );LOCAL void fmpAttachFileSystem( FmCmdPkt *pkt, FsInfo *fsinfo );LOCAL void fmpChangeFileSystemMode( FmCmdPkt *pkt, FsInfo *fsinfo );LOCAL void fmpDetachFileSystem( FmCmdPkt *pkt, FsInfo *fsinfo );LOCAL void fmpFinish( FmCmdPkt *pkt, FsInfo *fsinfo );LOCAL void fmpBreak( FmCmdPkt *pkt, FsInfo *fsinfo );LOCAL FwdID fdEntry( FmCmdPkt *pkt, FsInfo *fsinfo );LOCAL FwdID linkEntry( FmCmdPkt *pkt, FsInfo *fsinfo );LOCAL FwdID createEntry( FmCmdPkt *pkt, FsInfo *fsinfo );LOCAL FwdID deleteEntry( FmCmdPkt *pkt, FsInfo *fsinfo );LOCAL FwdID fmpEntry( FmCmdPkt *pkt, FsInfo *fsinfo );#define TSD_FAF_MSK_0X0003 0x0003U#define TSD_FGF_CNT_4 4/* * Obtain the file system information. */LOCAL ER fmpGetFileSystemInfo( FsInfo *fsinfo ){ static const UW bootsz[] = StdBootBlkSizeList;#define N_BOOTSZ ( sizeof(bootsz)/sizeof(UW) ) DfSystemHeader *syshd = NULL; DskAdrS dskadr; UH ssys, sfidt; BOOL bigEndian; ID mid; W i; FsSpec fsspec; ER err; /* * Retrieve the boot block size. * Try some sizes. */ fsinfo->pbadj = 0; /* Because fmpMapDskAdrS() is used. */ for ( i = 0; i < (W)N_BOOTSZ; ++i ) { if ( (UW)fsinfo->dskInfo.blocksize > bootsz[i] ) { continue; } /* Map the system header. */ syshd = fmpMapDskAdrS((DskAdrS)bootsz[i], sizeof(DfSystemHeader), MAP_SYS(fsinfo), &mid, fsinfo); if ( syshd == NULL ) { err = (ER)mid; goto err_ret; } /* Check the disk format. */ err = fmCheckDiskFormat(syshd); if ( err >= 0 ) { /* OK: Set the file system format/endian format. */ fsinfo->diskform = DiskFormVersion(err); fsinfo->bigEndian = DiskFormEndian(err); break; } fmpUnmapDisk(mid, MD_RDONLY); } if ( i >= (W)N_BOOTSZ ) { err = E_ILFMT; goto err_ret; } bigEndian = fsinfo->bigEndian; /* Correction value for computing the physical block number Correction value when the boot block size and logical block size are not equal */ fsinfo->pbadj = ((W)bootsz[i] - (W)fmConvEndianH(syshd->sblk, bigEndian)) / fsinfo->dskInfo.blocksize;#if !MisalignLogBlk if ( fsinfo->pbadj != 0 ) { fmpUnmapDisk(mid, MD_RDONLY); err = E_ILFMT; goto err_ret; }#endif /* Obtain the file system information. */ fsinfo->acclv = (H)fmConvEndianH((UH)syshd->acclv, bigEndian); fsinfo->nbmp = (W)fmConvEndianH(syshd->nbmp, bigEndian); fsinfo->nfmax = fmConvEndianH(syshd->nfmax, bigEndian); fsinfo->nlb = (W)fmConvEndianW((UW)syshd->nlb, bigEndian); fsinfo->sblk = fmConvEndianH(syshd->sblk, bigEndian); (void)fmConvEndianTC(fsinfo->fsName, (TC*)syshd->fsnm, FsNameLen, bigEndian); if ( fsinfo->diskform >= DiskForm_B ) { /* STDFS extended format */ fsinfo->nbmp *= TSD_FGF_CNT_4; /* Bit map is word count. */ } fsinfo->blkRatio = (UH)(fsinfo->sblk / fsinfo->dskInfo.blocksize); ssys = fmConvEndianH(syshd->ssys, bigEndian); sfidt = fmConvEndianH(syshd->sfidt, bigEndian); fsinfo->shead = dskadr = (DskAdrS)(UW)fsinfo->sblk; fsinfo->usebm = (VB*)dskadr + sizeof(DfSystemHeader); fsinfo->fidt = (VB*)dskadr + (ssys * fsinfo->sblk); fsinfo->fsnt = (VB*)dskadr + ((ssys + sfidt) * fsinfo->sblk); fmpUnmapDisk(mid, MD_RDONLY); err = fmpCheckDiskError(NULL, fsinfo); if ( err < E_OK ) { goto err_ret; } /* Notify the segment management of the file system information. */ fsspec.lbsz = fsinfo->sblk; fsspec.btsz = (UH)bootsz[i]; err = InformFS(fsinfo->dskid, &fsspec); if ( err < E_OK ) { if ( err == E_BUSY ) { err = E_SYS; } goto err_ret; } return E_OK;err_ret: DEBUG_PRINT(("fmpGetFileSystemInfo err = %d\n", err)); return err;}/* * att_fls: Connect the file system. */LOCAL void fmpAttachFileSystem( FmCmdPkt *pkt, FsInfo *fsinfo ){ FM_ATT_FLS_PARA *cmdPara = (FM_ATT_FLS_PARA*)pkt->cmd.para; DfFileHeaderBlock *fhd; ID mid; W i; ER err; /* Initialize the file system management information (FsInfo). */ for ( i = 0; i < OFCB_QSZ; ++i ) { QueInit(&fsinfo->ofcb[i]); } QueInit(&fsinfo->wrkFilLst); QueInit(&fsinfo->resumeReq); /* Fetch the connection parameter. */ err = fmGetAplStr(fsinfo->devName, cmdPara->dev, DevNameLen); if ( err < E_OK ) { goto err_ret1; } err = fmGetAplStr(fsinfo->conName, cmdPara->name, ConNameLen); if ( err < E_OK ) { goto err_ret1; } if ( (cmdPara->mode & ~TSD_FAF_MSK_0X0003) != 0U ) { err = E_PAR; goto err_ret1; } fsinfo->conMode = cmdPara->mode; /* Parameter check */ err = fmCheckFileName(fsinfo->conName, ConNameLen); if ( err < E_OK ) { goto err_ret1; } err = fmConNameExist(fsinfo->conName); if ( err < E_OK ) { goto err_ret1; } if ( cmdPara->lnk != NULL ) { err = CheckSpaceRW(cmdPara->lnk, sizeof(LINK)); if ( err < E_OK ) { goto err_ret1; } } /* Register the disk exception handler. */ err = fmpDefineDiskErrorHandler(TRUE); if ( err < E_OK ) { goto err_ret1; } /* Connect the file system. */ err = AttachFS(fsinfo->devName, D_ATTACH|D_WEXCL, pkt->wrk.pinfo, &fsinfo->dskInfo); if ( err < E_OK ) { goto err_ret2; } fsinfo->dskid = (ID)err; /* Check the disk partition information. */ err = fmCheckPartitionID(fsinfo->devName); if ( err < E_OK ) { goto err_ret3; } /* Obtain the file system information. */ err = fmpGetFileSystemInfo(fsinfo); if ( err < E_OK ) { goto err_ret3; } /* Check the file header ID of the root file. */ fhd = fmpMapFileHeader(0, NULL, &mid, fsinfo); if ( fhd == NULL ) { err = ( mid == E_NOEXS )? E_ILFMT: mid; goto err_ret3; } i = ( (fmpConvEndianW(fhd->head.startid, fsinfo) == FileHeaderTopID) && (fmpConvEndianW(fhd->head.endid, fsinfo) == FileHeaderEndID) )? E_OK: E_ILFMT; fmpUnmapDisk(mid, MD_RDONLY); err = fmpCheckDiskError(NULL, fsinfo); if ( err < E_OK ) { goto err_ret3; } err = i; if ( err < E_OK ) { goto err_ret3; } /* Whether the file system of the same name is already connected. */ err = fmFsNameExist(fsinfo->fsName); if ( err < E_OK ) { goto err_ret3; } if ( cmdPara->lnk != NULL ) { /* Return the link to the root file. */ *cmdPara->lnk = RootFile(fsinfo); } pkt->cmd.ret = E_OK; return;err_ret3: (void)DetachFS(fsinfo->dskid, NULL, FALSE);err_ret2: (void)fmpDefineDiskErrorHandler(FALSE);err_ret1: DEBUG_PRINT(("fmpAttachFileSystem err = %d\n", err)); pkt->cmd.ret = err; return;}/* * chg_fsm: Change the connection mode of the file system. */LOCAL void fmpChangeFileSystemMode( FmCmdPkt *pkt, FsInfo *fsinfo ){ FM_CHG_FSM_PARA *cmdPara = (FM_CHG_FSM_PARA*)pkt->cmd.para; UW old; ER err; /* Parameter check */ if ( (cmdPara->mode & ~TSD_FAF_MSK_0X0003) != 0U ) { err = E_PAR; goto err_ret; } /* Access right check */ err = CheckFS(cmdPara->dev, D_ATTACH, pkt->wrk.pinfo); if ( err < E_OK ) { goto err_ret; } /* Synchronize the disk. */ err = SyncFS(fsinfo->dskid, 0); if ( err < E_OK ) { goto err_ret; } /* Change the connection mode. */ old = fsinfo->conMode; fsinfo->conMode = cmdPara->mode; pkt->cmd.ret = (W)old; return;err_ret: DEBUG_PRINT(("fmpChangeFileSystemMode err = %d\n", err)); pkt->cmd.ret = err; return;}/* * det_fls: Disconnect the file system. */LOCAL void fmpDetachFileSystem( FmCmdPkt *pkt, FsInfo *fsinfo ){ FM_DET_FLS_PARA *cmdPara = (FM_DET_FLS_PARA*)pkt->cmd.para; W i; ER err; /* Whether there is a file being opened. */ for ( i = 0; i < OFCB_QSZ; ++i ) { if ( !isQueEmpty(&fsinfo->ofcb[i]) ) { err = E_BUSY; goto err_ret; } } /* Whether it is specified as the work file */ if ( !isQueEmpty(&fsinfo->wrkFilLst) ) { err = E_BUSY; goto err_ret; } /* Disconnect the file system. */ err = DetachFS(fsinfo->dskid, pkt->wrk.pinfo, cmdPara->eject); i = fmpCheckDiskError(NULL, fsinfo); if ( (err < E_OK) || ((err = i) < E_OK) ) { goto err_ret; } /*** Hereafter, the disconnection processing can not be stopped. ***/ /* Deregister the disk exception handler. */ (void)fmpDefineDiskErrorHandler(FALSE); pkt->cmd.ret = E_OK; return;err_ret: DEBUG_PRINT(("fmpDetachFileSystem err = %d\n", err)); pkt->cmd.ret = err; return;}/* * Forcefully disconnect the file system. */LOCAL void fmpFinish( FmCmdPkt *pkt, FsInfo *fsinfo ){ ER err, error = E_OK; /* Disconnect the file system. */ err = DetachFS(fsinfo->dskid, NULL, TRUE); if ( err < E_OK ) { error = err; } /* Deregister the disk exception handler. */ (void)fmpDefineDiskErrorHandler(FALSE); err = fmpCheckDiskError(NULL, fsinfo); if ( err < E_OK ) { error = err; } /* Delete OFCB and RCB. */ err = fmpDeleteAllOFCB(fsinfo); if ( err < E_OK ) { error = err; } /* Detach the queue just in case. */ QueRemove(&fsinfo->wrkFilLst); QueRemove(&fsinfo->resumeReq);#ifdef DEBUG if ( error < E_OK ) { DEBUG_PRINT(("fmpFinish err = %d\n", error)); }#endif pkt->cmd.ret = error; return;}/* * Break service */LOCAL void fmpBreak( FmCmdPkt *pkt, FsInfo *fsinfo ){ FM_BREAK_PARA *cmdPara = (FM_BREAK_PARA*)pkt->cmd.para; PINFO *pinfo; QUEUE *fdList, *q; FD *fd; FmCmdPkt *waitReq; ER err, error = E_OK; /* Process to break */ pinfo = GET_PINFO(cmdPara->tskid); if ( pinfo == NULL ) { error = E_CTX; goto err_ret; } LockFD(); fdList = &pinfo->file.fdList; for ( q = fdList->next; q != fdList; q = q->next ) { fd = (FD*)q; if ( fd->fs != fsinfo ) { continue; } waitReq = fd->waitReq; if ( (waitReq != NULL) && (waitReq->cmd.tid == cmdPara->tskid) ) { /* Release the lock waiting. */ err = fmpBreakLockWait(waitReq, fsinfo); if ( err < E_OK ) { error = err; } fd->waitReq = NULL; } } UnlockFD();err_ret:#ifdef DEBUG if ( error < E_OK ) { DEBUG_PRINT(("fmpBreak err = %d\n", error)); }#endif pkt->cmd.ret = error; return;}/* * Request processing entry when the file is specified by FD. */LOCAL FwdID fdEntry( FmCmdPkt *pkt, FsInfo *fsinfo ){ FD *fd; FmCmdPkt *waitReq; FwdID fwd = NoForward; ER err; /* Obtain FD. */ fd = fmGetFD(((W*)pkt->cmd.para)[0], pkt->wrk.pinfo); if ( fd == NULL ) { err = E_FD; goto err_ret1; } waitReq = fd->waitReq; if ( (waitReq != NULL) && (waitReq != pkt) ) { /* There exists an indeterminate waiting request (Double execution) */ err = E_BUSY; goto err_ret1; } switch ( pkt->cmd.fno.w ) { case FM_CLS_FIL_FN: fmpCloseFile(pkt); break; case FM_SEE_REC_FN: fmpSeekRecord(pkt); break; case FM_FND_REC_FN: fmpFindRecord(pkt); break; case FM_FND_LNK_FN: fmpFindLinkRecord(pkt); break; case FM_REA_REC_FN: fmpReadRecord(pkt); break; case FM_WRI_REC_FN: fmpWriteRecord(pkt); break; case FM_INS_REC_FN: fmpInsertRecord(pkt); break; case FM_APD_REC_FN: fmpAppendRecord(pkt); break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -