📄 insrec.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. * *---------------------------------------------------------------------- *//* * insrec.c (file) * * File management * Insert/Add/Delete records. */#include "fileio.h"#include "diskio.h"LOCAL ER changeRecordCount( OFCB *ofcb, W rtype, W diff );LOCAL WER changeFileReferenceCount( FID fid, W diff, FsInfo *fsinfo );LOCAL ER checkLINK( LINK *lnk, FsInfo *fsinfo );LOCAL ER appendRecord( RCB **rcb, OFCB *ofcb, W type, UH subtype, LINK *lnk );LOCAL ER insertRecord( RCB **rcb, OFCB *ofcb, W type, UH subtype, LINK *lnk );LOCAL WER deleteRecord( FD *fd, RCB *rcb, OFCB *ofcb );#define TSD_FRC_VAL_255 255#define TSD_FPR_VAL_32 32#define TSD_FRC_VAL_M1 (-1)#define TSD_DRD_VAL_M1 (-1)/* * Update the total number of records. * Increase/Decrease the total number of records of the file header by diff. * In the case of the link record, increase/decrease the number of included links as well. */LOCAL ER changeRecordCount( OFCB *ofcb, W rtype, W diff ){ FsInfo *fsinfo = ofcb->fsinfo; DfFileHeader *fh; H nlnk; ID mid; ER err; /* Map the file header. */ fh = fmpMapDskAdr(ofcb->fhead, sizeof(DfFileHeader), ofcb, &mid, fsinfo); if ( fh == NULL ) { err = (ER)mid; goto err_ret; } /* Update the total number of records. */ ofcb->nrec += diff; fh->nrec = (W)fmpConvEndianW((UW)ofcb->nrec, fsinfo); if ( isLinkRecord(rtype) != 0 ) { /* Update the number of included links. */ nlnk = (H)fmpConvEndianH((UH)fh->nlnk, fsinfo) + (H)diff; fh->nlnk = (H)fmpConvEndianH((UH)nlnk, fsinfo); } fmpUnmapDisk(mid, MD_WRITE); err = fmpCheckDiskError(ofcb, fsinfo); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: DEBUG_PRINT(("changeRecordCount err = %d\n", err)); return err;}/* * Update the file reference count. * Increase/Decrease the reference count of the file ID table by diff. * Return the updated reference count. */LOCAL WER changeFileReferenceCount( FID fid, W diff, FsInfo *fsinfo ){ W refcnt; DfFileID *fidt, f; DfFileHeader *fh = NULL; ID mid, mid2; ER err; /* Map the file ID table. */ fidt = fmpMapFileID(fid, &mid, fsinfo); if ( fidt == NULL ) { err = (ER)mid; goto err_ret1; } if ( fidt->w == 0U ) { /* File does not exist. */ err = E_NOEXS; goto err_ret2; } f = fmpConvEndianFileID(*fidt, fsinfo); refcnt = (W)f.s.refcnt; if ( ((refcnt == TSD_FRC_VAL_255) || ((refcnt + diff) >= TSD_FRC_VAL_255)) && (fsinfo->diskform >= DiskForm_B) ) { /* Map the file header. */ fh = fmpMapDskAdr(fmpLBlkToDAdr(f.s.blkadr, fsinfo), sizeof(DfFileHeader), MAP_FSTSK, &mid2, fsinfo); if ( fh == NULL ) { err = (ER)mid2; goto err_ret2; } if ( refcnt == TSD_FRC_VAL_255 ) { /* File reference count in STDFS extended format (>=255) */ refcnt = (W)fmpConvEndianW((UW)fh->refcnt, fsinfo); } } refcnt += diff; if ( (refcnt < 0) || ((refcnt > TSD_FRC_VAL_255) && (fsinfo->diskform == DiskForm_A)) ) { /* The reference count overflowed. */ err = E_LIMIT; goto err_ret3; } if ( fh != NULL ) { /* File the reference count in STDFS extended format (>=255) */ fh->refcnt = (W)fmpConvEndianW(( refcnt >= TSD_FRC_VAL_255 )? (UW)refcnt: 0, fsinfo); fmpUnmapDisk(mid2, MD_WRITE); } /* Update the file reference count */ f.s.refcnt = (UB)(( refcnt >= TSD_FRC_VAL_255 )? TSD_FRC_VAL_255: refcnt); *fidt = fmpConvEndianFileID(f, fsinfo); fmpUnmapDisk(mid, MD_WRITE); err = fmpCheckDiskError(NULL, fsinfo); if ( err < E_OK ) { goto err_ret1; } return refcnt;err_ret3: fmpUnmapDisk(mid2, MD_RDONLY);err_ret2: fmpUnmapDisk(mid, MD_RDONLY);err_ret1: DEBUG_PRINT(("changeFileReferenceCount err = %d\n", err)); return err;}/* * Check the contents of LINK. * If correct, up the reference count. */LOCAL ER checkLINK( LINK *lnk, FsInfo *fsinfo ){ ER err; /* Check the file system. */ if ( tc_strncmp(lnk->fs_name, fsinfo->fsName, FsNameLen) != 0 ) { /* The file system is different. */ err = E_REC; goto err_ret; } /* Up the file reference count. */ err = changeFileReferenceCount(lnk->f_id, +1, fsinfo); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: DEBUG_PRINT(("checkLINK err = %d\n", err)); return err;}/* * Add the record. * Add new record just before the end record. * Return the RCB of the added new record to *rcb. */LOCAL ER appendRecord( RCB **rcb, OFCB *ofcb, W type, UH subtype, LINK *lnk ){ RIdx ri; RCB *newrcb; DfRecordIndex *ridx; ER err; /* Locate ri at the last record index. */ err = fmpOpenRIdx(&ri, LAST_RIdx, ofcb); if ( err < E_OK ) { goto err_ret1; } ridx = fmpGetRIdx(&ri); if ( ridx == NULL ) { goto err_ret3; } /* Whether the current location is an unused record index. */ if ( !((ridx->type[0] == 0) && (ridx->type[1] == 0)) ) { /* It is used. */ RCB *currcb = prevRCB(EndRCB(ofcb)); err = fmpSetRCB(currcb, ofcb); if ( err < E_OK ) { goto err_ret2; } /* Add the record index. */ ridx = fmpAppendRIdx(&ri, currcb); if ( ridx == NULL ) { goto err_ret3; } } /* Add the new RCB just before the end record. */ err = fmpNewRCB(EndRCB(ofcb)); if ( err < E_OK ) { goto err_ret2; } /* Initialize the record index. */ err = fmpSetRIdx(&ri, type, subtype, lnk); if ( err < E_OK ) { goto err_ret2; } err = fmpCloseRIdx(&ri); if ( err < E_OK ) { goto err_ret1; } /* Update the total number of records of the file header. */ err = changeRecordCount(ofcb, type, +1); if ( err < E_OK ) { goto err_ret1; } /* Initialize the added RCB. */ newrcb = prevRCB(EndRCB(ofcb)); err = fmpSetRCB(newrcb, ofcb); if ( err < E_OK ) { goto err_ret1; } *rcb = newrcb; return E_OK;err_ret3: err = fmpGetRIdxError(&ri);err_ret2: (void)fmpCloseRIdx(&ri);err_ret1: DEBUG_PRINT(("appendRecord err = %d\n", err)); return err;}/* * Insert the record. * Insert the new record just before *rcb. * *rcb must not be the end record. * Return the RCB of the inserted new record to *rcb. */LOCAL ER insertRecord( RCB **rcb, OFCB *ofcb, W type, UH subtype, LINK *lnk ){ RIdx ri; RCB *currcb = *rcb; RCB *newrcb; DfRecordIndex *ridx; ER err; /* Locate ri at the first record index of currcb. */ err = fmpOpenRIdx(&ri, &currcb->idxadr, ofcb); if ( err < E_OK ) { goto err_ret1; } ridx = fmpGetRIdx(&ri); if ( ridx == NULL ) { goto err_ret3; } /* Insert the record index. */ ridx = fmpInsertRIdx(&ri, currcb); if ( ridx == NULL ) { goto err_ret3; } /* Insert the new RCB just before currcb. */ err = fmpNewRCB(currcb); if ( err < E_OK ) { goto err_ret2; } /* Increase the record numbers after currcb by 1. */ fmpIncRNoRCB(currcb, ofcb); /* Initialize the record index. */ err = fmpSetRIdx(&ri, type, subtype, lnk); if ( err < E_OK ) { goto err_ret2; } err = fmpCloseRIdx(&ri); if ( err < E_OK ) { goto err_ret1; } /* Update the total number of records of the file header. */ err = changeRecordCount(ofcb, type, +1); if ( err < E_OK ) { goto err_ret1; } /* Initialize the inserted RCB. */ newrcb = prevRCB(currcb); err = fmpSetRCB(newrcb, ofcb); if ( err < E_OK ) { goto err_ret1; } *rcb = newrcb; return E_OK;err_ret3: err = fmpGetRIdxError(&ri);err_ret2: (void)fmpCloseRIdx(&ri);err_ret1: DEBUG_PRINT(("insertRecord err = %d\n", err)); return err;}/* * Insert the record. */EXPORT void fmpInsertRecord( FmCmdPkt *pkt ){ FM_INS_REC_PARA *cmdPara = (FM_INS_REC_PARA*)pkt->cmd.para; FD *fd; OFCB *ofcb; RCB *rcb; ER err, error = E_OK; /* Obtain FD and OFCB. */ fd = getFDp(cmdPara->fd); ofcb = fd->ofcb; /* Check the open mode. */ err = fmpCheckFileOpenMode(fd, F_WRITE); if ( err < E_OK ) { goto err_ret; } /* Parameter check */ if ( !((cmdPara->type >= 0) && (cmdPara->type < TSD_FPR_VAL_32)) || (cmdPara->size < 0) ) { err = E_PAR; goto err_ret; } if ( isLinkRecord(cmdPara->type) != 0 ) { /* Check when the link record is inserted. */ if ( ((UW)cmdPara->size != sizeof(LINK)) || (cmdPara->buf == NULL) ) { err = E_PAR; goto err_ret; } err = CheckSpaceR(cmdPara->buf, sizeof(LINK)); if ( err < E_OK ) { goto err_ret; } /* Check the contents of LINK. */ err = checkLINK((LINK*)cmdPara->buf, ofcb->fsinfo); if ( err < E_OK ) { goto err_ret; } } /* Obtain the current record. */ rcb = fd->crcb; if ( !isEndRCB(rcb, ofcb) ) { err = fmpSetRCB(rcb, ofcb); if ( err < E_OK ) { goto err_ret; } /* Insert the record. */ err = insertRecord(&rcb, ofcb, cmdPara->type, cmdPara->subtype, (LINK*)cmdPara->buf); if ( err < E_OK ) { goto err_ret; } } else { /* Add the record. */ err = appendRecord(&rcb, ofcb, cmdPara->type, cmdPara->subtype, (LINK*)cmdPara->buf); if ( err < E_OK ) { goto err_ret; } } if ( isDataRecord(cmdPara->type) && (cmdPara->size > 0) ) { /* Write the data record. */ err = fmpWriteDataRecord(rcb, ofcb, 0, cmdPara->buf, cmdPara->size, cmdPara->units); if ( err < E_OK ) { if ( err != E_NODSK ) { goto err_ret; } error = err; } } /* Update the time stamp. */ err = fmpSetTimeStamp(ofcb, F_WRITE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -