📄 create.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. * *---------------------------------------------------------------------- *//* * create.c (file) * * File management * File creation/deletion */#include "fileio.h"#include "diskio.h"#include "dskalloc.h"LOCAL void setLinkFileState( F_STATE *fstate, UH atype, STIME ctime );LOCAL void setLinkFileState( F_STATE *fstate, UH atype, STIME ctime );LOCAL void setUserName( UserName dst, UserName src, W acclv );LOCAL void setFileState( F_STATE *fstate, A_MODE *mode, UH atype,PINFO *pinfo, FsInfo *fsinfo );LOCAL DfFileID* allocateFID( W *fid, ID_ERR *mid, FsInfo *fsinfo );LOCAL DfFileID* checkFID( W fid, ID_ERR *mid, FsInfo *fsinfo );LOCAL UH std_ridxofs( FsInfo *fsinfo );LOCAL void setNewFileHeader( DfFileHeader *fh,FID fid, TC *name, F_STATE *fstate, FsInfo *fsinfo );LOCAL void setLinkFile( DfLinkFile *lh, F_LINK *ref, FsInfo *fsinfo );LOCAL WER createFile( W mkfid, TC *name, F_STATE *fstate, F_LINK *ref,FsInfo *fsinfo );LOCAL ER checkFileDeleteOK( FID fid, UH ftype, FsInfo *fsinfo );LOCAL ER checkRecordDeleteOK( RCB *rcb );LOCAL ER deleteFileID( FID fid, FsInfo *fsinfo );LOCAL WER deleteAllRecordData( OFCB *ofcb );LOCAL ER deleteIndexBlock( UW delblk, W lv, OFCB *ofcb );LOCAL WER deleteFile( OFCB *ofcb );LOCAL ER deleteLinkFile( FID fid, UW hdblk, FsInfo *fsinfo );#define TSD_SFS_FLT_M1 (-1)#define TSD_SFS_OWN_0X0000 0x0000U#define TSD_SFS_GRP_0X0000 0x0000U#define TSD_FMF_MKF_M1 (-1)#define TSD_SRF_VAL_24 24#define TSD_DAR_VAL_0X80 (UB)0x80#define TSD_SFS_PUB_0X0FFF 0x0fffU#define TSD_SFS_CAS_1 1#define TSD_SFS_CAS_2 2#define TSD_SFS_CAS_3 3#define TSD_SFS_CAS_4 4#define TSD_FCR_VAL_4 4U#define TSD_GRC_VAL_255 255/* * Set the file management information of the link file. */LOCAL void setLinkFileState( F_STATE *fstate, UH atype, STIME ctime ){ memset(fstate, 0, (size_t)sizeof(F_STATE)); fstate->f_atype = atype; fstate->f_nblk = 1; fstate->f_ltime = TSD_SFS_FLT_M1; fstate->f_atime = ctime; fstate->f_mtime = ctime; fstate->f_ctime = ctime;}/* * Set the owner name/group name based on the access level. */LOCAL void setUserName( UserName dst, UserName src, W acclv ){ if ( (src != NULL) && (acclv > 0) ) { if ( acclv == 1 ) { /* Hidden name is always 0. */ memcpy(dst, src, (size_t)(sizeof(UserName)-sizeof(HideName))); memset(dst + OpenNameLen, 0, (size_t)sizeof(HideName)); } else { /* All valid */ memcpy(dst, src, (size_t)sizeof(UserName)); } } else { /* Always no name (0) */ memset(dst, 0, (size_t)sizeof(UserName)); }}/* * Set the file management information of the normal file. * Set fstate from mode and atype. */LOCAL void setFileState( F_STATE *fstate, A_MODE *mode, UH atype, PINFO *pinfo, FsInfo *fsinfo ){ W acclv = fsinfo->acclv; A_MODE m; P_USER *user; STIME now; TC *gname; if ( acclv == 0 ) { /* Fixed to the specification below when the access management level is 0. */ m.f_ownacc = TSD_SFS_OWN_0X0000; m.f_grpacc = TSD_SFS_GRP_0X0000; m.f_pubacc = TSD_SFS_PUB_0X0FFF; m.f_grpno = 0; } else if ( mode == NULL ) { /* Use the default access mode. */ DA_MODE *dm; LOCK_PINFO_SECTION( dm = &pinfo->user->mode; m.f_ownacc = dm->f_ownacc; m.f_grpacc = dm->f_grpacc; m.f_pubacc = dm->f_pubacc; m.f_grpno = dm->f_grpno; ); } else { m = *mode; } fstate->f_type = F_FILE | m.f_ownacc; fstate->f_atype = atype; LOCK_PINFO_SECTION( user = &pinfo->user->user; setUserName(fstate->f_owner, user->usr_name, acclv); switch( m.f_grpno ) { case TSD_SFS_CAS_1: gname = user->grp_name1; break; case TSD_SFS_CAS_2: gname = user->grp_name2; break; case TSD_SFS_CAS_3: gname = user->grp_name3; break; case TSD_SFS_CAS_4: gname = user->grp_name4; break; default: gname = NULL; break; } setUserName(fstate->f_group, gname, acclv); ); fstate->f_grpacc = m.f_grpacc; fstate->f_pubacc = m.f_pubacc; now = fmGetTime(); fstate->f_atime = now; fstate->f_mtime = now; fstate->f_ctime = now; fstate->f_ltime = TSD_SFS_FLT_M1;}/* * Find a free file ID. */LOCAL DfFileID* allocateFID( W *fid, ID_ERR *mid, FsInfo *fsinfo ){ DfFileID *p = NULL; DskAdrS fidt; W i, n; ER err; fidt = fsinfo->fidt; n = 0; for ( i = 0; i < fsinfo->nfmax; ++i ) { if ( --n <= 0 ) { if ( p != NULL ) { fmpUnmapDisk(*mid, MD_RDONLY); } /* Map the file ID table by one logical block. */ p = fmpMapDskAdrS(fidt, (W)fsinfo->sblk, MAP_SYS(fsinfo), mid, fsinfo); if ( p == NULL ) { err = (ER)*mid; goto err_ret; } fidt = (DskAdrS)((VB*)fidt + fsinfo->sblk); n = (W)((UW)fsinfo->sblk / sizeof(DfFileID)); } if ( p->w == 0U ) { break; /* The free ID found. */ } p++; } err = fmpCheckDiskError(NULL, fsinfo); if ( err < E_OK ) { goto err_ret; } if ( i >= fsinfo->nfmax ) { err = E_LIMIT; goto err_ret; } *fid = i; return p;err_ret: if ( p != NULL ) { fmpUnmapDisk(*mid, MD_RDONLY); } DEBUG_PRINT(("allocateFID err = %d\n", err)); *mid = err; return NULL;}/* * Check whether the specified file ID is free. */LOCAL DfFileID* checkFID( W fid, ID_ERR *mid, FsInfo *fsinfo ){ DfFileID *fidt; ER err; /* Map the file ID table. */ fidt = fmpMapFileID((FID)fid, mid, fsinfo); if ( fidt == NULL ) { err = (ER)*mid; goto err_ret; } if ( fidt->w != 0U ) { /* It is already used. */ err = E_OBJ; goto err_ret; } return fidt;err_ret: fmpUnmapDisk(*mid, MD_RDONLY); DEBUG_PRINT(("checkFID err = %d\n", err)); *mid = err; return NULL;}/* * Return the location of the standard record index. */LOCAL UH std_ridxofs( FsInfo *fsinfo ){ W n; /* Because the location of the record index is fixed and the index is not specified in the file header before the extended format 2, return 0. */ if ( fsinfo->diskform < DiskForm_C ) { return 0; } /* Reserve the fragment table area of 24 entries per 1 KB logical block size. */ n = fsinfo->sblk / KB; if ( n < 1 ) { n = 1; } n *= TSD_SRF_VAL_24; return (UH)offsetof(DfFileHeaderBlock, f.frag2[n]);}/* * Initialize the new file header. */LOCAL void setNewFileHeader( DfFileHeader *fh, FID fid, TC *name, F_STATE *fstate, FsInfo *fsinfo ){ BOOL big = fsinfo->bigEndian; fh->startid = fmConvEndianW(FileHeaderTopID, big); fh->ftype = fmConvEndianH(fstate->f_type, big); fh->atype = fmConvEndianH(fstate->f_atype, big); fmConvEndianHs((UH*)fh->own, (UH*)fstate->f_owner, UserNameLen, big); fmConvEndianHs((UH*)fh->grp, (UH*)fstate->f_group, UserNameLen, big); fh->gacclv = fmConvEndianH(fstate->f_grpacc, big); fh->pacclv = fmConvEndianH(fstate->f_pubacc, big); fh->nlnk = 0; fh->idxlv = 0; fh->size = 0; fh->nblk = (W)fmConvEndianW(1, big); fh->nrec = 0; fh->ltime = (W)fmConvEndianW((UW)fstate->f_ltime, big); fh->atime = (W)fmConvEndianW((UW)fstate->f_atime, big); fh->mtime = (W)fmConvEndianW((UW)fstate->f_mtime, big); fh->ctime = (W)fmConvEndianW((UW)fstate->f_ctime, big); fmConvEndianTC((TC*)fh->name, name, FileNameLen, big); fh->refcnt = 0; fh->ridxofs = fmConvEndianH(std_ridxofs(fsinfo), big); fh->fid = fmConvEndianH(fid, big); fh->endid = fmConvEndianW(FileHeaderEndID, big);}/* * Set the file location data. */LOCAL void setLinkFile( DfLinkFile *lh, F_LINK *ref, FsInfo *fsinfo ){ BOOL big = fsinfo->bigEndian; lh->fid = fmConvEndianH(ref->f_id, big); setMisalignW(lh->ctime, fmConvEndianW((UW)ref->rf_ctime, big)); (void)fmConvEndianTC((TC*)lh->fsnm, ref->fs_name, L_FSNM, big); (void)fmConvEndianTC((TC*)lh->devnm, ref->fs_locat, L_DLNM, big);}/* * Set the file abbreviated name. */EXPORT ER fmpSetShortFileName( FID fid, TC *name, FsInfo *fsinfo ){ DfShortName *fsnt, *dadr; ID mid; ER err; /* Map the file abbreviated name table. */ dadr = (DfShortName*)fsinfo->fsnt; fsnt = fmpMapDskAdrS(&dadr[fid], sizeof(DfShortName), MAP_SYS(fsinfo), &mid, fsinfo); if ( fsnt == NULL ) { err = (ER)mid; goto err_ret; } /* Set the abbreviated name. */ *fsnt = fmpConvEndianW(fmShortFileName(name), fsinfo); fmpUnmapDisk(mid, MD_WRITE); err = fmpCheckDiskError(NULL, fsinfo); if ( err < E_OK ) { goto err_ret; } return E_OK;err_ret: DEBUG_PRINT(("fmpSetShortFileName err = %d\n", err)); return err;}/* * File generation */LOCAL WER createFile( W mkfid, TC *name, F_STATE *fstate, F_LINK *ref, FsInfo *fsinfo ){ DfFileID *fidt; DfFileHeaderBlock *fh; W hdblk; ID idmid, hdmid; ER err; if ( mkfid < 0 ) { /* Find a free file ID. */ fidt = allocateFID(&mkfid, &idmid, fsinfo); if ( fidt == NULL ) { err = (ER)idmid; goto err_ret1; } } else { /* Check whether the specified file ID is free. */ fidt = checkFID(mkfid, &idmid, fsinfo); if ( fidt == NULL ) { err = (ER)idmid; goto err_ret1; } } /* Reserve one block for the file header. */ hdblk = fmpAllocateOneBlock(0, NULL, fsinfo); if ( hdblk < E_OK ) { err = (ER)hdblk; goto err_ret2; } fh = fmpMapAndClearLogBlk((UW)hdblk, MAP_FSTSK, &hdmid, fsinfo); if ( fh == NULL ) { err = (ER)hdmid; goto err_ret2; } /* Set the file header. */ setNewFileHeader(&fh->head, (UH)mkfid, name, fstate, fsinfo); if ( ref != NULL ) { /* Set the file location. */ setLinkFile(&fh->f.link, ref, fsinfo); } fmpUnmapDisk(hdmid, MD_WRITE); /* Set the file abbreviated name. */ err = fmpSetShortFileName((FID)mkfid, name, fsinfo); if ( err < E_OK ) { goto err_ret2; } /* Set to the file ID table. */ fidt->s.refcnt = 0; fidt->s.blkadr = hdblk; *fidt = fmpConvEndianFileID(*fidt, fsinfo); fmpUnmapDisk(idmid, MD_WRITE); err = fmpSyncFile(MAP_FSTSK, fsinfo); if ( err < E_OK ) { goto err_ret0; } return mkfid;err_ret2: fmpUnmapDisk(idmid, MD_RDONLY);err_ret1: (void)fmpSyncFile(MAP_FSTSK, fsinfo);err_ret0: DEBUG_PRINT(("createFile err = %d\n", err)); return err;}/* * Normal file generation * Return MD_WRITE when writing is performed to opara->fhd. * Otherwise, return MD_RDONLY. */EXPORT UW fmpCreateFile( FmCmdPkt *pkt, OpenPara *opara, FsInfo *fsinfo ){ FM_CRE_FIL_PARA *cmdPara = (FM_CRE_FIL_PARA*)pkt->cmd.para; LINK *lnk = cmdPara->lnk; A_MODE *mode = cmdPara->mode; PINFO *pinfo = pkt->wrk.pinfo; OFCB *rf; W mkfid; F_STATE fstate; FD *fd; ER err; err = CheckSpaceRW(lnk, sizeof(LINK)); if ( err < E_OK ) { goto err_ret1; } /* mode parameter check */ if ( mode != NULL ) { err = CheckSpaceR(mode, sizeof(A_MODE)); if ( err < E_OK ) { goto err_ret1; } if ( ((UH)mode->f_grpno > TSD_FCR_VAL_4) || ((mode->f_ownacc & ~F_OWNACC) != 0U) ){ err = E_PAR; goto err_ret1; } } /* 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 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; } /* Set the normal file management information. */ setFileState(&fstate, mode, cmdPara->atype, pinfo, fsinfo); /* Normal file generation */ err = createFile(mkfid, cmdPara->name, &fstate, 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; } } /* 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(("fmpCreateFile err = %d\n", err)); pkt->cmd.ret = err; return MD_RDONLY;}/* * Link file generation. * Return MD_WRITE when writing is performed to opara->fhd. * Otherwise, return MD_RDONLY. */EXPORT UW fmpCreateLinkFile( FmCmdPkt *pkt, OpenPara *opara, FsInfo *fsinfo ){ FM_CRE_LNK_PARA *cmdPara = (FM_CRE_LNK_PARA*)pkt->cmd.para; LINK *lnk = cmdPara->lnk; F_LINK *ref = cmdPara->ref; F_STATE fstate; PINFO *pinfo = pkt->wrk.pinfo; OFCB *rf; W mkfid; ER err; err = CheckSpaceRW(lnk, sizeof(LINK)); if ( err < E_OK ) { goto err_ret1; } /* 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; } /* 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; } /* Set the link file management information. */ setLinkFileState(&fstate, ref->f_atype, fmGetTime()); /* Link file generation */ err = createFile(mkfid, ref->f_name, &fstate, ref, 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; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -