⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rwrec.c

📁 T-kernel 的extension源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *---------------------------------------------------------------------- *    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. * *---------------------------------------------------------------------- *//* *	rwrec.c (file) * *	File management *	Record read/write */#include "fileio.h"#include "diskio.h"#include "dskalloc.h"#define HASH_AREA_SZ		16	/* Hash Function for 16Byte area */#define MAX_RANK		7	/* max rank set */#define DSK_NOT_USE		(-1)	/* unused entries */#define TSD_WLR_VAL_0		0#define TSD_WLR_VAL_1		1#define TSD_WLR_VAL_2		2#define TSD_WLR_VAL_3		3#define TSD_WLR_VAL_4		4#define TSD_GRB_PRE_M1		(-1)#define TSD_ERS_UNI_1024	1024U#define TSD_FWR_VAL_M1		(-1)#define TSD_ABR_CT1_255		255#define TSD_ABR_CT1_255_U	255U/* * Read/Write flag */typedef enum {	Read	= MD_RDONLY,	/* Read */	Write	= MD_WRITE	/* Write */} RW;LOCAL W afterBlkPos( LogBlk *lblk, W pos, FsInfo *fsinfo );LOCAL W beforeBlkPos( LogBlk *lblk, W pos, FsInfo *fsinfo );LOCAL ER rwDataRecord( VB *buf, RCB *rcb, W start, W size, OFCB *ofcb, RW rw );LOCAL ER readDataRecord( RCB *rcb, OFCB *ofcb, FM_REA_REC_PARA *cmdPara );LOCAL ER readLinkRecord( RCB *rcb, OFCB *ofcb, FM_REA_REC_PARA *cmdPara );LOCAL ER changeFileSize( OFCB *ofcb, W diffsize );LOCAL ER blockMove( UW toLBlk, UW fromLBlk, W start, W end, OFCB *ofcb );LOCAL ER appendBlockRCB( RCB *rcb, RIdx *ri, LLogBlk lnew, W *sz );LOCAL WER expandRSizeFromFragmentSpace( RCB *rcb, W size, OFCB *ofcb );LOCAL WER expandRSizeFromLastBlock( RCB *rcb, W size, W units, OFCB *ofcb );LOCAL ER expandRSizeFromNewBlock( RCB *rcb, W *size, W units, OFCB *ofcb );LOCAL ER expandRecordSize( RCB *rcb, W rsize, UW units, OFCB *ofcb );LOCAL ER writeLinkRecord( RCB *rcb, OFCB *ofcb, FM_WRI_REC_PARA *cmdPara );LOCAL WER getRecordBlockList( RCB *rcb, OFCB *ofcb, PhyBlk blklst[], W *offset, W max );/* * Return the block that includes the area after pos of *lblk * Return the location of pos in new *lblk to the return value. */LOCAL W afterBlkPos( LogBlk *lblk, W pos, FsInfo *fsinfo ){	W	nblk, offset;	nblk = pos / fsinfo->sblk;	offset = pos % fsinfo->sblk;	lblk->cnt -= nblk;	lblk->adr += nblk;	return offset;}/* * Return the block that includes the area before pos of *lblk * Return the location of pos in new *lblk to the return value. */LOCAL W beforeBlkPos( LogBlk *lblk, W pos, FsInfo *fsinfo ){	W	nblk;	nblk = pos / fsinfo->sblk;	lblk->cnt = nblk + 1;	return pos;}/* * Create the logical block list for the record map. *	Create the logical block list in lb to map the size bytes from *	start th byte of the record data of *rcb. *	Since the lb is on a logical block basis, return the offset *	 from the start to start th byte to the return value. */EXPORT WER fmpMakeLBlks( LBlks *lb, RCB *rcb, W start, W size, OFCB *ofcb ){	FsInfo		*fsinfo = ofcb->fsinfo;	RIdx		ri;	DfRecordIndex	*ridx;	W		cp;	LogBlk		lblk;	W		end, total, blktp;	W		mapoff;	ER		err;	/* Location of map end */	end = start + size - 1;	/* Prepare to obtain the record index. */	err = fmpOpenRIdx(&ri, &rcb->idxadr, ofcb);	if ( err < E_OK ) {		goto err_ret1;	}	/* Obtain the location of the first data block and normal index. */	err = fmpGetDataBlkAdr(&ri, &lblk);	if ( err < E_OK ) {		goto err_ret2;	}	ridx = fmpGetMapAdr(&ri, &cp);	blktp = - (W)fmpConvEndianH(ridx->n.offset, fsinfo);	total = blktp + (lblk.cnt * fsinfo->sblk);	while ( total <= start ) {		/* Obtain the location of the data blocks after the first one from the connection index. */		err = fmpGetDataBlkAdr(&ri, &lblk);		if ( err < E_OK ) {			goto err_ret2;		}		blktp = total;		total += lblk.cnt * fsinfo->sblk;	}	/* Add to the map block list. */	if ( total > end ) {		(void)beforeBlkPos(&lblk, end - blktp, fsinfo);	}	mapoff = afterBlkPos(&lblk, start - blktp, fsinfo);	err = fmAddLBlks(lb, lblk);	if ( err < E_OK ) {		goto err_ret2;	}	while ( total <= end ) {		/* Obtain the location of the data blocks after the first one from the connection index. */		err = fmpGetDataBlkAdr(&ri, &lblk);		if ( err < E_OK ) {			goto err_ret2;		}		blktp = total;		total += lblk.cnt * fsinfo->sblk;		/* Add to the map block list. */		if ( total > end ) {			(void)beforeBlkPos(&lblk, end - blktp, fsinfo);		}		err = fmAddLBlks(lb, lblk);		if ( err < E_OK ) {			goto err_ret2;		}	}	err = fmpCloseRIdx(&ri);	if ( err < E_OK ) {		goto err_ret1;	}	return mapoff;err_ret2:	(void)fmpCloseRIdx(&ri);err_ret1:	DEBUG_PRINT(("fmpMakeLBlks err = %d\n", err));	return err;}/* * Read/Write the record data. *	Read/Write the size bytes from start th byte of the record data of *rcb. * *	rw = Read	Read the record and store it in buf. *	rw = Write	Write to the record from buf. */LOCAL ER rwDataRecord( VB *buf, RCB *rcb, W start, W size, OFCB *ofcb, RW rw ){	FsInfo		*fsinfo = ofcb->fsinfo;	LBlks		lb;	W		offset;	MapModeClr	clear;	ER		err;	/* Prepare the block list. */	err = fmNewLBlks(&lb);	if ( err < E_OK ) {		goto err_ret1;	}	/* Create the record block list. */	offset = fmpMakeLBlks(&lb, rcb, start, size, ofcb);	if ( offset < 0 ) {		err = (ER)offset;		goto err_ret2;	}	/* Map the whole record at once to read/write */	{	VB	*mp;		ID	mid;		if ( rw == Write ) {			/* When writing, prevent unnecessary reading from occurring.			    */			clear = MapUnsettle;			if ( offset > 0 ) {				clear |= MapNoClrTop;			}			if ( ((offset + size) % fsinfo->sblk) > 0 ) {				clear |= MapNoClrEnd;			}		} else {			clear = MapNoClr;		}		/* Map the whole record. */		mp = fmpMapLogBlks(&lb, ofcb, clear, &mid, fsinfo);		if ( mp == NULL ) {			err = (ER)mid;			if ( (ER)((UW)err & EC_MASK) == E_IO ) {				goto err_ret2;			}		} else {			mp += offset;			/* Read/Write */			if ( rw == Read ) {				memcpy(buf, mp, (size_t)size);			}else{				memcpy(mp, buf, (size_t)size);			}			fmpUnmapDisk(mid, rw);			err = E_OK;		}	}	/* Read/Write the record on a logical block basis. */	if ( err < E_OK ) {		LogBlk	*lblk = NULL;		W	sz, b, i;		VB	*mp;		ID	mid;		while ( fmNextLBlks(&lb, &lblk) != 0 ) {			b = lblk->adr;			for ( i = lblk->cnt; i > 0; --i ) {				sz = fsinfo->sblk - offset;				if ( sz > size ) {					sz = size;				}				/* When writing to the whole logical block,				   prevent unnecessary writing from occurring. */				clear = ( (rw == Write) && (sz == fsinfo->sblk) )?						MapUnsettle: MapNoClr;				/* Map one logical block. */				mp = fmpMapLogBlkC((UW)b++, ofcb, clear,							&mid, fsinfo);				if ( mp == NULL ) {					err = (ER)mid;					goto err_ret2;				}				mp += offset;				/* Read/Write */				if ( rw == Read ) {					memcpy(buf, mp, (size_t)sz);				}else{					memcpy(mp, buf, (size_t)sz);				}				buf += sz;				size -= sz;				fmpUnmapDisk(mid, rw);				offset = 0;			}		}	}	err = fmpCheckDiskError(ofcb, fsinfo);	if ( err < E_OK ) {		goto err_ret2;	}	/* Release the block list. */	fmDeleteLBlks(&lb);	return E_OK;err_ret2:	fmDeleteLBlks(&lb);err_ret1:	DEBUG_PRINT(("rwDataRecord err = %d\n", err));	return err;}/* ------------------------------------------------------------------------ *//* * Read the data record. */LOCAL ER readDataRecord( RCB *rcb, OFCB *ofcb, FM_REA_REC_PARA *cmdPara ){	W	size;	ER	err;	/* Read size */	size = rcb->rsize - cmdPara->offset;	if ( cmdPara->size < size ) {		size = cmdPara->size;	}	if ( size <= 0 ) {		return E_OK;	}	/* Check the read buffer area. */	err = CheckSpaceRW(cmdPara->buf, size);	if ( err < E_OK ) {		goto err_ret;	}	/* Read the record */	err = rwDataRecord(cmdPara->buf, rcb, cmdPara->offset, size,							ofcb, Read);	if ( err < E_OK ) {		goto err_ret;	}	return E_OK;err_ret:	DEBUG_PRINT(("readDataRecord err = %d\n", err));	return err;}/* * Read the link record */LOCAL ER readLinkRecord( RCB *rcb, OFCB *ofcb, FM_REA_REC_PARA *cmdPara ){	FsInfo		*fsinfo = ofcb->fsinfo;	DfLinkIndex	*lidx;	LINK		*lnk;	ID		mid;	ER		err;	/* Parameter check */	if ( (cmdPara->offset != 0)	  || (cmdPara->size < (W)sizeof(LINK)) ) {		return E_PAR;	}	/* Check the LINK storing area. */	lnk = (LINK*)cmdPara->buf;	err = CheckSpaceRW(lnk, sizeof(LINK));	if ( err < E_OK ) {		return err;	}	/* Map the record index. */	lidx = fmpMapDskAdr(rcb->idxadr.ridx, sizeof(DfLinkIndex),						ofcb, &mid, fsinfo);	if ( lidx == NULL ) {		return (ER)mid;	}	/* Read LINK */	fmpLIdxToLINK(lnk, lidx, fsinfo);	fmpUnmapDisk(mid, MD_RDONLY);	return fmpCheckDiskError(ofcb, fsinfo);}/* * Read the record. */EXPORT void fmpReadRecord( FmCmdPkt *pkt ){	FM_REA_REC_PARA	*cmdPara = (FM_REA_REC_PARA*)pkt->cmd.para;	FD		*fd;	OFCB		*ofcb;	RCB		*rcb;	ER		err;	/* Obtain FD and OFCB. */	fd = getFDp(cmdPara->fd);	ofcb = fd->ofcb;	/* Check the open mode */	err = fmpCheckFileOpenMode(fd, F_READ);	if ( err < E_OK ) {		goto err_ret;	}	/* Obtain the current record. */	err = fmpSetRCB(rcb = fd->crcb, ofcb);	if ( err < E_OK ) {		goto err_ret;	}	/* Parameter check */	if ( (cmdPara->offset < 0)	  || (cmdPara->size < 0) ) {		err = E_PAR;		goto err_ret;	}	/* Check the record lock. */	if ( isLockRecord(fd, rcb) != 0 ) {		err = E_LOCK;		goto err_ret;	}	if ( !((cmdPara->buf == NULL) || (cmdPara->size == 0)) ) {		if ( isLinkRecord(rcb->rtype) != 0 ) {			/* Read the link record. */			err = readLinkRecord(rcb, ofcb, cmdPara);			if ( err < E_OK ) {				goto err_ret;			}		} else {			/* Read the data record. */			err = readDataRecord(rcb, ofcb, cmdPara);			if ( err < E_OK ) {				goto err_ret;			}		}	}	/* Return r_size and subtype. */	if ( cmdPara->r_size != NULL ) {		err = CheckSpaceRW(cmdPara->r_size, sizeof(W));		if ( err < E_OK ) {			goto err_ret;		}		*cmdPara->r_size = rcb->rsize - cmdPara->offset;	}	if ( cmdPara->subtype != NULL ) {		err = CheckSpaceRW(cmdPara->subtype, sizeof(UH));		if ( err < E_OK ) {			goto err_ret;		}		*cmdPara->subtype = rcb->stype;	}	/* Update the time stamp. */	err = fmpSetTimeStamp(ofcb, F_READ);	if ( err < E_OK ) {		goto err_ret;	}	pkt->cmd.ret = (W)rcb->rtype;	setSyncAtExit(SAE_OPENF, ofcb->fsinfo);	return;err_ret:	DEBUG_PRINT(("fmpReadRecord err = %d\n", err));	pkt->cmd.ret = err;	setSyncAtExit(SAE_OPENF, ofcb->fsinfo);	return;}/* ------------------------------------------------------------------------ *//* * Update the total byte count of the file. *	Increase/Decrease the total byte count of the file of the file header by diffsize. */LOCAL ER changeFileSize( OFCB *ofcb, W diffsize ){	FsInfo		*fsinfo = ofcb->fsinfo;	DfFileHeader	*fh;	W		size;	ID		mid;	ER		err;	/* Map the file header. */	fh = fmpMapDskAdr(ofcb->fhead, sizeof(DfFileHeader),					ofcb, &mid, fsinfo);	if ( fh == NULL ) {		err = (ER)mid;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -