📄 create.c
字号:
pkt->cmd.ret = E_OK; return MD_RDONLY;err_ret2: if ( rf != NULL ) { (void)fmpICloseFile(rf, F_WRITE); }err_ret1: DEBUG_PRINT(("fmpCreateLinkFile err = %d\n", err)); pkt->cmd.ret = err; return MD_RDONLY;}/* * File generation * Return MD_WRITE when writing is performed to opara->fhd. * Otherwise, return MD_RDONLY. */EXPORT UW fmpGenerateFile( FmCmdPkt *pkt, OpenPara *opara, FsInfo *fsinfo ){ FM_GEN_FIL_PARA *cmdPara = (FM_GEN_FIL_PARA*)pkt->cmd.para; LINK *lnk = cmdPara->lnk; F_STATE *stat = cmdPara->stat; F_LINK *ref = cmdPara->ref; PINFO *pinfo = pkt->wrk.pinfo; OFCB *rf; UH ftype; W mkfid; FD *fd; ER err; err = CheckSpaceRW(lnk, sizeof(LINK)); if ( err < E_OK ) { goto err_ret1; } /* fstate parameter check */ err = CheckSpaceR(stat, sizeof(F_STATE)); if ( err < E_OK ) { goto err_ret1; } ftype = stat->f_type; if ( isLinkFile(ftype) != 0 ) { /* ref parameter check */ err = CheckSpaceR(ref, sizeof(F_LINK)); if ( err < E_OK ) { goto err_ret1; } err = fmCheckFileName(ref->f_name, FileNameLen); if ( err < E_OK ) { goto err_ret1; } err = fmCheckFileName(ref->fs_name, L_FSNM); if ( err < E_OK ) { goto err_ret1; } if ( isSameFS(ref->fs_name, fsinfo) != 0 ) { /* Same file system */ err = E_PAR; goto err_ret1; } } else { /* name parameter check */ err = CheckStrSpaceR(cmdPara->name, FileNameLen); if ( err < E_OK ) { goto err_ret1; } err = fmCheckFileName(cmdPara->name, FileNameLen); if ( err < E_OK ) { goto err_ret1; } } /* Whether the user level is 0. */ if ( getUserLevel(pinfo) > 0 ) { err = E_FACV; goto err_ret1; } /* Whether the file system is writable or not. */ if ( isNoWriteFS(fsinfo) != 0 ) { err = E_RONLY; goto err_ret1; } switch ( cmdPara->opt ) { case F_FLOAT: rf = NULL; /* No reference file */ mkfid = TSD_FMF_MKF_M1; /* Automatically select a free file ID. */ break; case F_FIX: /* Open the reference file (The file specified by lnk). */ rf = fmpIOpenFile(opara, F_WRITE, pinfo, fsinfo, &err); if ( rf == NULL ) { goto err_ret1; } mkfid = TSD_FMF_MKF_M1; /* Automatically select a free file ID. */ break; case F_FILEID: rf = NULL; /* No reference file */ mkfid = (W)lnk->f_id; /* Generate a file with the specified file ID. */ break; default: err = E_PAR; goto err_ret1; } if ( isLinkFile(ftype) != 0 ) { F_STATE fstate; /* Set the link file management information. */ setLinkFileState(&fstate, ref->f_atype, ref->f_ctime); /* Link file generation */ err = createFile(mkfid, ref->f_name, &fstate, ref, fsinfo); if ( err < E_OK ) { goto err_ret2; } mkfid = (W)err; } else { /* Normal file generation */ err = createFile(mkfid, cmdPara->name, stat, NULL, fsinfo); if ( err < E_OK ) { goto err_ret2; } mkfid = (W)err; } /* LINK generation */ MakeLINK(lnk, (FID)mkfid, fsinfo); if ( rf != NULL ) { /* Add the link record of the generated file to the reference file. */ err = fmpIAppendLinkRecord(rf, lnk); if ( err < E_OK ) { goto err_ret2; } /* Close */ err = fmpICloseFile(rf, F_WRITE); if ( err < E_OK ) { goto err_ret1; } } if ( isLinkFile(ftype) != 0 ) { pkt->cmd.ret = E_OK; } else { /* Open the generated file. */ fd = fmpOpenNewFile((FID)mkfid, F_UPDATE, pinfo, fsinfo, &err); if ( fd == NULL ) { goto err_ret1; } pkt->cmd.ret = getFDno(fd); } return MD_RDONLY;err_ret2: if ( rf != NULL ) { (void)fmpICloseFile(rf, F_WRITE); }err_ret1: DEBUG_PRINT(("fmpGenerateFile err = %d\n", err)); pkt->cmd.ret = err; return MD_RDONLY;}/* ------------------------------------------------------------------------ *//* * Obtain the reference count of the file of fid. * When fh == NULL, a reference count more than 255 is returned as 255. */EXPORT WER fmpGetFileReferenceCount( FID fid, DfFileHeader *fh, FsInfo *fsinfo ){ DfFileID *fidt, f; W refcnt; ID mid; ER err; /* Map the file ID table. */ fidt = fmpMapFileID(fid, &mid, fsinfo); if ( fidt == NULL ) { err = (ER)mid; goto err_ret; } /* Fetch the reference count. */ f = fmpConvEndianFileID(*fidt, fsinfo); fmpUnmapDisk(mid, MD_RDONLY); err = fmpCheckDiskError(NULL, fsinfo); if ( err < E_OK ) { goto err_ret; } refcnt = (W)f.s.refcnt; if ( (refcnt == TSD_GRC_VAL_255) && (fsinfo->diskform >= DiskForm_B) && (fh != NULL) ) { /* Reference count of extended format STDFS (>=255) */ refcnt = (W)fmpConvEndianW((UW)fh->refcnt, fsinfo); } return refcnt;err_ret: DEBUG_PRINT(("fmpGetFileReferenceCount err = %d\n", err)); return err;}/* * Whether the file can be deleted. */LOCAL ER checkFileDeleteOK( FID fid, UH ftype, FsInfo *fsinfo ){ QUEUE *finfo; QUEUE *wfl = &fsinfo->wrkFilLst; W offset = (W)offsetof(FINFO, workFile.f_id); /* Whether it is specified as a work file. */ LOCK_PINFO_SECTION( finfo = QueSearchH(wfl, wfl, (H)fid, offset) ); if ( finfo != wfl ) { return E_BUSY; } /* Whether the delete protect attribute is set. */ if ( (ftype & F_PERM) != 0U ) { return E_PERM; } return E_OK;}/* * Whether the record can be deleted. */LOCAL ER checkRecordDeleteOK( RCB *rcb ){ if ( rcb == NULL ) { return E_OK; } /* Whether it is referred as the current record. */ if ( rcb->ref > 0 ) { return E_BUSY; } /* Whether it is record locked. */ if ( rcb->lkfd != NULL ) { return E_LOCK; } return E_OK;}/* * Delete from the file ID table. */LOCAL ER deleteFileID( FID fid, FsInfo *fsinfo ){ DfFileID *fidt; ID mid; fidt = fmpMapFileID(fid, &mid, fsinfo); if ( fidt == NULL ) { goto err_ret; } /* Delete the file ID. */ fidt->w = 0; fmpUnmapDisk(mid, MD_WRITE); return E_OK;err_ret: DEBUG_PRINT(("deleteFileID err = %d\n", mid)); return (ER)mid;}/* * Delete all the record data. * Reduce the reference count by deleting data of the data record or * by disconnecting links of the link record. The record index is made unused. * (The record index blocks are not deleted.) * Return the number of files whose file reference count became 0 * as the result of the link of the link record being disconnected. */LOCAL WER deleteAllRecordData( OFCB *ofcb ){ FsInfo *fsinfo = ofcb->fsinfo; RIdx ri; DfRecordIndex *ridx; W ndel = 0; W i; ER err; /* Prepare to obtain the record index. */ err = fmpOpenRIdx(&ri, FIRST_RIdx, ofcb); if ( err < E_OK ) { goto err_ret1; } for ( i = 0; i < ofcb->nrec; ++i ) { /* Obtain the record index. */ ridx = fmpGetRecordRIdx(&ri); if ( ridx == NULL ) { goto err_ret3; } if ( ridx->type[1] == TSD_DAR_VAL_0X80 ) { /* Link record: Disconnect the link. */ err = fmpDecrementFileReferenceCount(&ridx->l, fsinfo); if ( err < E_OK ) { goto err_ret2; } ndel += (W)err; } else { UW size; size = fmpConvEndianW(ridx->n.size, fsinfo); if ( size > 0U ) { /* Data record: Delete the data. */ err = fmpITruncateDataRecord(&ri, 0); if ( err < E_OK ) { goto err_ret2; } } } } err = fmpCloseRIdx(&ri); if ( err < E_OK ) { goto err_ret1; } return ndel;err_ret3: err = fmpGetRIdxError(&ri);err_ret2: (void)fmpCloseRIdx(&ri);err_ret1: DEBUG_PRINT(("deleteAllRecordData err = %d\n", err)); return err;}/* * Delete the record index/block. */LOCAL ER deleteIndexBlock( UW delblk, W lv, OFCB *ofcb ){ FsInfo *fsinfo = ofcb->fsinfo; DfIndirectIndex *iidx; W i, end; UW blk; ID mid; ER err; if ( lv < ofcb->idxlv ) { /* Delete the index block the indirect index indicates. */ iidx = fmpMapLogBlk(delblk, ofcb, &mid, fsinfo); if ( iidx == NULL ) { err = (ER)mid; goto err_ret1; } end = (W)((UW)fsinfo->sblk / sizeof(DfIndirectIndex)); for ( i = TopIIdx(lv, ofcb); i < end; ++i ) { blk = fmpConvEndianW(iidx[i].blk, fsinfo); if ( blk != 0U ) { err = fmpCheckDiskError(ofcb, fsinfo); if ( err < E_OK ) { goto err_ret2; } err = deleteIndexBlock(blk, lv + 1, ofcb); if ( err < E_OK ) { goto err_ret2; } } } fmpUnmapDisk(mid, MD_RDONLY); } /* Delete its own index block. */ err = fmpFreeOneBlock(delblk, NULL, fsinfo); if ( err < E_OK ) { goto err_ret1; } return E_OK;err_ret2: fmpUnmapDisk(mid, MD_RDONLY);err_ret1: DEBUG_PRINT(("deleteIndexBlock err = %d\n", err)); return err;}/* * Delete the normal file. * Return the number of files whose file reference count became 0 * as the result of the link record being deleted. */LOCAL WER deleteFile( OFCB *ofcb ){ FsInfo *fsinfo = ofcb->fsinfo; W ndel; ER err; /* Delete all the record data. */ ndel = deleteAllRecordData(ofcb); if ( ndel < E_OK ) { err = (ER)ndel; goto err_ret; } /* Delete from the file ID table. */ err = deleteFileID(ofcb->fid, fsinfo); if ( err < E_OK ) { goto err_ret; } /* Delete all record indexes and file headers. */ err = deleteIndexBlock(fmpDAdrToLBlk(ofcb->fhead, fsinfo), 0, ofcb); if ( err < E_OK ) { goto err_ret; } return ndel;err_ret: DEBUG_PRINT(("deleteFile err = %d\n", err)); return err;}/* * Delete the link file. */LOCAL ER deleteLinkFile( FID fid, UW hdblk, FsInfo *fsinfo ){ ER err; /* Delete from the file ID table. */ err = deleteFileID(fid, fsinfo); if ( err < E_OK ) { goto err_ret; } /* Delete the file header. */ err = fmpFreeOneBlock(hdblk, NULL, fsinfo); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: DEBUG_PRINT(("deleteLinkFile err = %d\n", err)); return err;}/* * Delete the file. * Return MD_WRITE when writing is performed to opara->fhd. * Otherwise, return MD_RDONLY. */EXPORT UW fmpDeleteFile( FmCmdPkt *pkt, OpenPara *opara, FsInfo *fsinfo ){ FM_DEL_FIL_PARA *cmdPara = (FM_DEL_FIL_PARA*)pkt->cmd.para; LINK *org = cmdPara->org; LINK *lnk = cmdPara->lnk; PINFO *pinfo = pkt->wrk.pinfo; OFCB *of = NULL; OFCB *lf = NULL; UH lnktype = 0; UW lnkhblk = 0; W nref, ndel; IdxAdr delrec; RCB *delrcb; ID mid; ER err; /* lnk parameter check */ err = CheckSpaceR(lnk, sizeof(LINK)); if ( err < E_OK ) { goto err_ret1; } /* Whether the file system is writable or not. */ if ( isNoWriteFS(fsinfo) != 0 ) { err = E_RONLY; goto err_ret1; } if ( org != NULL ) { /* Check the file system name of lnk. */ if ( !isSameFS(lnk->fs_name, fsinfo) ) { err = E_PAR; goto err_ret1; } /* Open org. */ of = fmpIOpenFile(opara, F_WRITE, pinfo, fsinfo, &err); if ( of == NULL ) { goto err_ret1; } /* Retrieve the record of lnk. */ err = fmpISearchLinkRecord(of, lnk->f_id, &delrec, &delrcb); if ( err < E_OK ) { goto err_ret1; } /* Whether the record can be deleted. */ err = checkRecordDeleteOK(delrcb); if ( err < E_OK ) { goto err_ret1; } } /* Obtain the reference count of lnk. */ nref = fmpGetFileReferenceCount(lnk->f_id, NULL, fsinfo); if ( nref < E_OK ) { err = (ER)nref; goto err_ret1; } if ( org != NULL ) { nref--; } if ( nref <= 0 ) { OpenPara op; W nlnk; mid = fmpGetOpenPara(&op, lnk->f_id, fsinfo); if ( mid < E_OK ) { err = (ER)mid; goto err_ret1; } /* Link count, file type and header block location of lnk. */ lnkhblk = fmpDAdrToLBlk(op.dadr, fsinfo); lnktype = fmpConvEndianH(op.fhd->head.ftype, fsinfo); nlnk = (W)fmpConvEndianH((UH)op.fhd->head.nlnk, fsinfo); err = fmpCheckDiskError(NULL, fsinfo); if ( err < E_OK ) { goto err_ret2; } /* Whether lnk can be deleted. */ err = checkFileDeleteOK(lnk->f_id, lnktype, fsinfo); if ( err < E_OK ) { goto err_ret2; } if ( isNormFile(lnktype) != 0 ) { /* Open lnk. */ lf = fmpIOpenFile(&op, F_EXCL, pinfo, fsinfo, &err); if ( lf == NULL ) { goto err_ret2; } /* Check the number of link records included in lnk. */ if ( (cmdPara->force == 0) && (nlnk > 0) ) { err = E_REC; goto err_ret2; } } fmpUnmapDisk(mid, MD_RDONLY); err = fmpCheckDiskError(NULL, fsinfo); if ( err < E_OK ) { goto err_ret1; } } else { if ( org == NULL ) { err = E_BUSY; goto err_ret1; } } if ( org != NULL ) { /* Delete the record of lnk from org. */ err = fmpIDeleteLinkRecord(of, &delrec, delrcb); if ( err < E_OK ) { goto err_ret1; } /* Close org. */ err = fmpICloseFile(of, F_WRITE); if ( err < E_OK ) { goto err_ret1; } } if ( nref <= 0 ) { if ( isNormFile(lnktype) != 0 ) { /* Delete the normal file (lnk). */ ndel = deleteFile(lf); if ( ndel < E_OK ) { err = (ER)ndel; goto err_ret1; } /* Close lnk. */ err = fmpICloseFile(lf, F_UPDATE|F_EXCL); if ( err < E_OK ) { goto err_ret1; } } else { /* Delete the link file (lnk). */ err = deleteLinkFile(lnk->f_id, lnkhblk, fsinfo); if ( err < E_OK ) { goto err_ret1; } ndel = 0; } } else { ndel = 0; } pkt->cmd.ret = ndel; return MD_RDONLY;err_ret2: fmpUnmapDisk(mid, MD_RDONLY);err_ret1: if ( of != NULL ) { (void)fmpICloseFile(of, F_WRITE); } if ( lf != NULL ) { (void)fmpICloseFile(lf, F_UPDATE|F_EXCL); } DEBUG_PRINT(("fmpDeleteFile err = %d\n", err)); pkt->cmd.ret = err; return MD_RDONLY;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -