📄 open.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. * *---------------------------------------------------------------------- *//* * open.c (file) * * File management * File open/close * Replace the file contents. */#include "fileio.h"#include "diskio.h"LOCAL ER exchangeFileHeader( OFCB *ofcb1, OFCB *ofcb2 );LOCAL void exchangeOFCB( OFCB *ofcb1, OFCB *ofcb2 );LOCAL ER exchangeFileContent( OFCB *ofcb1, OFCB *ofcb2 );/* * Obtain the open parameter. * Map the file header and return the map ID. */EXPORT ID_ERR fmpGetOpenPara( OpenPara *opara, FID fid, FsInfo *fsinfo ){ ID mid; opara->fid = fid; opara->fhd = fmpMapFileHeader(fid, &opara->dadr, &mid, fsinfo); return mid;}/* * File open for internal use * RCB and FD are not used. */EXPORT OFCB* fmpIOpenFile( OpenPara *opara, W omode, PINFO *pinfo, FsInfo *fsinfo, ER *errp ){ FileAccMode amode; OFCB *ofcb; ER err; /* Fetch the file access mode. */ err = fmpGetFileAccMode(&amode, &opara->fhd->head, fsinfo); if ( err < E_OK ) { goto err_ret1; } /* Access right check */ err = fmpCheckFileAccMode(pinfo, &amode, (UW)omode, fsinfo); if ( err < E_OK ) { goto err_ret1; } /* Obtain OFCB. */ ofcb = fmpGetOFCB(opara, fsinfo, &err); if ( ofcb == NULL ) { goto err_ret1; } /* The exclusive access check is not preformed when doing only search access. */ if ( (UW)omode != F_EXCUTE ) { /* Check the exclusive access mode. */ err = fmpCheckExclusiveOpen(ofcb, (UW)omode); if ( err < E_OK ) { goto err_ret2; } } *errp = E_OK; return ofcb;err_ret2: fmpRemoveOFCB(ofcb, FALSE);err_ret1: DEBUG_PRINT(("fmpIOpenFile err = %d\n", err)); *errp = err; return NULL;}/* * Open the newly generated file. */EXPORT FD* fmpOpenNewFile( FID fid, W omode, PINFO *pinfo, FsInfo *fsinfo, ER *err ){ OFCB *ofcb; FD *fd; OpenPara opara; ID mid; /* Obtain the open parameter. */ mid = fmpGetOpenPara(&opara, fid, fsinfo); if ( mid < E_OK ) { *err = (ER)mid; goto err_ret1; } /* Obtain OFCB. */ ofcb = fmpGetOFCB(&opara, fsinfo, err); if ( ofcb == NULL ) { goto err_ret2; } /* Obtain FD. */ fd = fmpOpenFD(pinfo, (UW)omode, ofcb, err); if ( fd == NULL ) { goto err_ret3; } fmpUnmapDisk(mid, MD_RDONLY); return fd;err_ret3: fmpRemoveOFCB(ofcb, FALSE);err_ret2: fmpUnmapDisk(mid, MD_RDONLY);err_ret1: DEBUG_PRINT(("fmpOpenNewFile err = %d\n", *err)); return NULL;}/* * File open * When writing into opara->fhd, return MD_WRITE. * Otherwise, return MD_RDONLY. */EXPORT UW fmpOpenFile( FmCmdPkt *pkt, OpenPara *opara, FsInfo *fsinfo ){ FM_OPN_FIL_PARA *cmdPara = (FM_OPN_FIL_PARA*)pkt->cmd.para; FileAccMode amode; OFCB *ofcb; FD *fd; ER err; /* Parameter check */ if ( (((UW)cmdPara->o_mode & ~(UW)(F_UPDATE|F_EXCL|F_WEXCL)) != 0U) || (((UW)cmdPara->o_mode & (F_EXCL|F_WEXCL)) == (F_EXCL|F_WEXCL)) || (((UW)cmdPara->o_mode & F_UPDATE) == 0U) ) { err = E_PAR; goto err_ret1; } /* Fetch the file access mode. */ err = fmpGetFileAccMode(&amode, &opara->fhd->head, fsinfo); if ( err < E_OK ) { goto err_ret1; } /* Access right check */ err = fmpCheckFileAccMode(pkt->wrk.pinfo, &amode, (UW)cmdPara->o_mode, fsinfo); if ( err < E_OK ) { goto err_ret1; } /* Password check */ err = fmpCheckPassWord(&opara->fhd->head, cmdPara->pwd, fsinfo); if ( err < E_OK ) { goto err_ret1; } /* Obtain OFCB. */ ofcb = fmpGetOFCB(opara, fsinfo, &err); if ( ofcb == NULL ) { goto err_ret1; } /* Check the exclusive access mode. */ err = fmpCheckExclusiveOpen(ofcb, (UW)cmdPara->o_mode); if ( err < E_OK ) { goto err_ret2; } /* Obtain FD. */ fd = fmpOpenFD(pkt->wrk.pinfo, (UW)cmdPara->o_mode, ofcb, &err); if ( fd == NULL ) { goto err_ret2; } pkt->cmd.ret = getFDno(fd); return MD_RDONLY;err_ret2: fmpRemoveOFCB(ofcb, FALSE);err_ret1: DEBUG_PRINT(("fmpOpenFile err = %d\n", err)); pkt->cmd.ret = err; return MD_RDONLY;}/* ------------------------------------------------------------------------ *//* * Close the file for internal use. */EXPORT ER fmpICloseFile( OFCB *ofcb, W omode ){ ER err; /* Write the cached data at the final close or final close of the write mode. */ if ( (ofcb->ref <= 0) || ((((UW)omode & F_WRITE) != 0U) && (ofcb->omode.write <= 0)) ) { /* Write the cached data. */ err = fmpSyncFile(ofcb, ofcb->fsinfo); if ( err < E_OK ) { goto err_ret; } } /* Delete OFCB. */ fmpRemoveOFCB(ofcb, FALSE); return E_OK;err_ret: DEBUG_PRINT(("fmpICloseFile err = %d\n", err)); return err;}/* * File close * (*) It is called also from the cleanup service function. */EXPORT void fmpCloseFile( FmCmdPkt *pkt ){ FM_CLS_FIL_PARA *cmdPara = (FM_CLS_FIL_PARA*)pkt->cmd.para; FD *fd; OFCB *ofcb; FsInfo *fsinfo; ER err, error = E_OK; /* Obtain FD and OFCB. */ fd = getFDp(cmdPara->fd); ofcb = fd->ofcb; fsinfo = fd->fs; /* Release all record locks. */ fmpUnlockAllRecord(fd, ofcb); /* Release all record maps */ err = fmpUnmapAllRecord(fd, ofcb); if ( err < E_OK ) { error = err; } /* Write the cached data at the final close or final close of the write mode. Write it also when the file system is connected in synchronous mode. */ if ( (fsinfo->conMode == FS_SYNC) || (ofcb->ref <= 1) || (((fd->omode & F_WRITE) != 0) && (ofcb->omode.write <= 1)) ) { /* Write the cached data. */ err = fmpSyncFile(ofcb, fsinfo); if ( err < E_OK ) { error = err; } } cancelSyncAtExit((UB)SAE_OPENF, fsinfo); /* Release FD. */ fmpCloseFD(fd); /* Delete OFCB. */ fmpRemoveOFCB(ofcb, FALSE);#ifdef DEBUG if ( error < E_OK ) { DEBUG_PRINT(("fmpCloseFile err = %d\n", error)); }#endif pkt->cmd.ret = error; return;}/* * Synchronize the files. */EXPORT void fmpSyncFileData( FmCmdPkt *pkt ){ FM_SYN_FIL_PARA *cmdPara = (FM_SYN_FIL_PARA*)pkt->cmd.para; FD *fd; OFCB *ofcb; FsInfo *fsinfo; ER err, error = E_OK; /* Obtain FD and OFCB. */ fd = getFDp(cmdPara->fd); ofcb = fd->ofcb; fsinfo = fd->fs; /* Write the cached data. */ err = fmpSyncFile(ofcb, fsinfo); if ( err < E_OK ) { error = err; } cancelSyncAtExit((UB)SAE_OPENF, fsinfo);#ifdef DEBUG if ( error < E_OK ) { DEBUG_PRINT(("fmpSyncFileData err = %d\n", error)); }#endif pkt->cmd.ret = error; return;}/* ======================================================================== *//* * Replace the file header. */LOCAL ER exchangeFileHeader( OFCB *ofcb1, OFCB *ofcb2 ){ FsInfo *fsinfo = ofcb1->fsinfo; DfFileHeaderBlock *fh1, *fh2; ID mid1, mid2; VP tmp; W tmpsize = (W)(fsinfo->sblk - sizeof(DfFileHeader)); ER err; /* Work memory */ tmp = Kmalloc((size_t)tmpsize); if ( tmp == NULL ) { err = E_SYSMEM; goto err_ret1; } /* Map the file header. */ fh1 = fmpMapLogBlk(fmpDAdrToLBlk(ofcb1->fhead, fsinfo), ofcb1, &mid1, fsinfo); if ( fh1 == NULL ) { err = (ER)mid1; goto err_ret2; } fh2 = fmpMapLogBlk(fmpDAdrToLBlk(ofcb2->fhead, fsinfo), ofcb2, &mid2, fsinfo); if ( fh2 == NULL ) { err = (ER)mid2; goto err_ret3; } /* Replace the file header contents */ memcpy(tmp, &fh1->f, (size_t)tmpsize); memcpy(&fh1->f, &fh2->f, (size_t)tmpsize); memcpy(&fh2->f, tmp, (size_t)tmpsize); xchg(H, fh1->head.nlnk, fh2->head.nlnk); xchg(H, fh1->head.idxlv, fh2->head.idxlv); xchg(W, fh1->head.size, fh2->head.size); xchg(W, fh1->head.nblk, fh2->head.nblk); xchg(W, fh1->head.nrec, fh2->head.nrec); fmpUnmapDisk(mid1, MD_WRITE); fmpUnmapDisk(mid2, MD_WRITE); Kfree(tmp); err = fmpCheckDiskError(ofcb1, fsinfo); if ( err < E_OK ) { goto err_ret1; } err = fmpCheckDiskError(ofcb2, fsinfo); if ( err < E_OK ) { goto err_ret1; } return err;err_ret3: fmpUnmapDisk(mid1, MD_RDONLY);err_ret2: Kfree(tmp);err_ret1: DEBUG_PRINT(("exchangeFileHeader err = %d\n", err)); return err;}/* * Replace OFCB. */LOCAL void exchangeOFCB( OFCB *ofcb1, OFCB *ofcb2 ){ RCB *top1, *top2; /* Replace the file header information. */ xchg(H, ofcb1->idxlv, ofcb2->idxlv); xchg(W, ofcb1->nrec, ofcb2->nrec); /* Replace RCB. */ top1 = FirstRCB(ofcb1); top2 = FirstRCB(ofcb2); if ( !isEndRCB(top1, ofcb1) ) { QueRemove(&ofcb1->rcb); } else { top1 = NULL; } if ( !isEndRCB(top2, ofcb2) ) { QueRemove(&ofcb2->rcb); } else { top2 = NULL; } if ( top2 != NULL ) { QueInsert(&ofcb1->rcb, &top2->q); } else { QueInit(&ofcb1->rcb); } if ( top1 != NULL ) { QueInsert(&ofcb2->rcb, &top1->q); } else { QueInit(&ofcb2->rcb); } /* Make all RCBs invalid. */ fmpSetInvalidAllRCB(ofcb1); fmpSetInvalidAllRCB(ofcb2);}/* * Replace the file contents. */LOCAL ER exchangeFileContent( OFCB *ofcb1, OFCB *ofcb2 ){ ER err; /* Replace the file header. */ err = exchangeFileHeader(ofcb1, ofcb2); if ( err < E_OK ) { goto err_ret; } /* Replace OFCB. */ exchangeOFCB(ofcb1, ofcb2); return E_OK;err_ret: DEBUG_PRINT(("exchangeFileContent err = %d\n", err)); return err;}/* * Replace the file contents. */EXPORT void fmpExchangeFileContent( FmCmdPkt *pkt ){ FM_XCH_FIL_PARA *cmdPara = (FM_XCH_FIL_PARA*)pkt->cmd.para; FD *fd1, *fd2; OFCB *ofcb1, *ofcb2; FsInfo *fsinfo; ER err; /* Obtain FD and OFCB. */ fd1 = getFDp(cmdPara->fd_1); ofcb1 = fd1->ofcb; fsinfo = fd1->fs; fd2 = fmGetFD(cmdPara->fd_2, pkt->wrk.pinfo); if ( fd2 == NULL ) { err = E_FD; goto err_ret1; } ofcb2 = fd2->ofcb; /* Whether it is the same file. */ if ( ofcb1 == ofcb2 ) { err = E_PAR; goto err_ret1; } /* Whether it is the same file system. */ if ( fd1->fs != fd2->fs ) { err = E_XFS; goto err_ret1; } /* Whether it is open in both update mode and exclusive mode. */ err = fmpCheckFileOpenMode(fd1, F_UPDATE|F_EXCL); if ( err < E_OK ) { goto err_ret1; } err = fmpCheckFileOpenMode(fd2, F_UPDATE|F_EXCL); if ( err < E_OK ) { goto err_ret1; } /* Whether some records are locked. */ err = fmpCheckLockAllRecord(ofcb1); if ( err < E_OK ) { goto err_ret1; } err = fmpCheckLockAllRecord(ofcb2); if ( err < E_OK ) { goto err_ret1; } /* Whether some records are mapped. */ if ( isMapRecords(fd1) || isMapRecords(fd2) ) { err = E_BUSY; goto err_ret1; } /* Replace the file contents. */ err = exchangeFileContent(ofcb1, ofcb2); if ( err < E_OK ) { goto err_ret2; } /* Define the current record as the first record. */ xchg(RCB*, fd1->crcb, fd2->crcb); fmpMoveCurRecord(fd1, FirstRCB(ofcb1)); fmpMoveCurRecord(fd2, FirstRCB(ofcb2)); /* Update the time stamp. */ err = fmpSetTimeStamp(ofcb1, F_READ|F_WRITE); if ( err < E_OK ) { goto err_ret2; } err = fmpSetTimeStamp(ofcb2, F_READ|F_WRITE); if ( err < E_OK ) { goto err_ret2; } /* Write it here when the file system is connected in synchronous mode. */ if ( fsinfo->conMode == FS_SYNC ) { err = fmpSyncFile(ofcb1, fsinfo); if ( err < E_OK ) { goto err_ret2a; } err = fmpSyncFile(ofcb2, fsinfo); if ( err < E_OK ) { goto err_ret1; } } pkt->cmd.ret = E_OK; return;err_ret2: if ( fsinfo->conMode == FS_SYNC ) { (void)fmpSyncFile(ofcb1, fsinfo);err_ret2a: (void)fmpSyncFile(ofcb2, fsinfo); }err_ret1: DEBUG_PRINT(("fmpExchangeFileContent err = %d\n", err)); pkt->cmd.ret = err; return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -