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

📄 etc.c

📁 T-kernel 的extension源代码
💻 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. * *---------------------------------------------------------------------- *//* *	etc.c (file) * *	File management *	Various functions */#include "fminfo.h"#include "diskio.h"#define TSD_LTL_POS_0		0#define TSD_LTL_POS_1		1#define TSD_LTL_POS_2		2#define TSD_LTL_POS_3		3#define TSD_LTL_POS_4		4#define TSD_CFN_VAL_M1		(-1)#define TSD_FCN_VAL_0X001F	(TC)0x001f#define TSD_FCN_VAL_0XFF00	(TC)0xff00#define TSD_DSN_SFT_16		16LOCAL	DfShortName*	getSFNp( SFN *sfn, FID fid );/* ======================================================================== *//* *	Data transfer to application tasks *//* * Data transfer from application tasks */EXPORT ER fmGetAplData( VP to, VP from, W len ){	ER	err;	/* Check the address space. */	err = CheckSpaceR(from, len);	if ( err != E_OK ) {		DEBUG_PRINT(("CheckSpace err = %d\n", err));		return err;	}	/* Memory transfer */	memcpy(to, from, (size_t)len);	return E_OK;}/* * Data transfer with applications */EXPORT ER fmSetAplData( VP to, VP from, W len ){	ER	err;	/* Check the address space. */	err = CheckSpaceRW(to, len);	if ( err != E_OK ) {		DEBUG_PRINT(("CheckSpace err = %d\n", err));		return err;	}	/* Memory transfer */	memcpy(to, from, (size_t)len);	return E_OK;}/* * Character string transfer from applications */EXPORT WER fmGetAplStr( TC *to, TC *from, W max ){	W	len;	/* Check the address space */	len = CheckStrSpaceR(from, max);	if ( (ER)len < E_OK ) {		DEBUG_PRINT(("CheckStrSpace err = %d\n", (ER)len));		return (ER)len;	}	/* Memory transfer */	memcpy(to, from, (size_t)((UW)len * sizeof(TC)));	return E_OK;}/* ======================================================================== *//* *	Analyze the path name. *//* * Cut out the path name. *	Analyze the path name from the position of *pathp, and return the first token to *name. *	Return the location advanced by one token to *pathp. *	Return the type of the token to the return value. */EXPORT PTYPE fmGetPathToken( TC **pathp, PathToken name ){	TC	*p = *pathp;	TC	c;	PTYPE	type;	W	i;	switch ( *p ) {	  case TC_FDLM:		type = PT_CON;	/* Connection name */		p++; /* Omit / at the start. */		break;	  case TC_FOWN:		type = PT_OWN;	/* Work file */		break;	  default:		type = PT_NAM;	/* File name */		break;	}	i = 0;	while ( (c = *(p++)) != TC_FDLM ) {		if ( c == TNULL ) {			p--; /* Return to the location of TNULL. */			break;		}		*(name++) = c;		if ( ++i >= PathTokenLen ) {			break;		}	}	*name = TNULL;	*pathp = p;	return type;}/* * Fetch the file name. *	Fetch only the portion of file name from the file name (*name) including the occurrence *	order, and return it to *name. Return the occurrence order to the return value. */EXPORT W fmGetFileName( PathToken name ){	TC	*p;	/* Cut out the file name. */	p = tc_strchr(name, TC_FSEP);	if ( p == NULL ) {		return 0; /* The occurrence order is not specified. */	}	*p = TNULL;	/* Fetch the occurrence order. */	return tc_atoi(p + 1);}/* * Check the validity of the connection name, file system name, and file name (excluding the occurrence order). *	Check the followings. *	* Whether invalid character is not included. *	* Whether it is not empty. */EXPORT ER fmCheckFileName( TC *name, W max ){	TC	c;	W	i = TSD_CFN_VAL_M1;	while ( (++i < max) && ((c = *(name++)) != TNULL) ) {		/* Control code and Special code are invalid. */		if ( (c <= TSD_FCN_VAL_0X001F) || (c >= TSD_FCN_VAL_0XFF00) ) {			return E_FNAME;		}	}	if ( i == 0 ) {		return E_FNAME;	}	return E_OK;}/* * Check the validity of the path name. *	Check the followings. *	* Whether invalid character is not included. *	* Whether it is not empty. */EXPORT ER fmCheckPathName( PathName name ){	TC	c;	W	i = 0;	while ( (++i <= PathNameLen) && ((c = *(name++)) != TNULL) ) {		/* Special code for path name is OK. */		if ( (c == TC_FDLM) || (c == TC_FSEP) || (c == TC_FOWN) ) {			continue;		}		/* Control code and Special code are invalid. */		if ( (c <= TSD_FCN_VAL_0X001F) || (c >= TSD_FCN_VAL_0XFF00) ) {			return E_FNAME;		}	}	if ( i == 0 ) {		return E_FNAME;	}	return E_OK;}/* ======================================================================== *//* *	File name *//* * Generate file abbreviated name. */EXPORT DfShortName fmShortFileName( FileName name ){	DfShortName	sn  = 0;	W		cnt = sizeof(FileName) / sizeof(UW);	while ( --cnt >= 0 ) {		if ( *name != TNULL ) {			sn ^= (UW)*(name++) << TSD_DSN_SFT_16;		}		if ( *name != TNULL ) {			sn ^= (UW)*(name++);		}		sn = ROR1(sn);	}	return sn;}/* * Obtain the file name. */EXPORT ER fmpGetFileName( FID fid, FileName name, FsInfo *fsinfo ){	DfFileHeaderBlock	*fh;	ID			mid;	ER			err;	fh = fmpMapFileHeader(fid, NULL, &mid, fsinfo);	if ( fh == NULL ) {		err = (ER)mid;		goto err_ret;	}	(void)fmpConvEndianTC(name, (TC*)fh->head.name, FileNameLen, fsinfo);	fmpUnmapDisk(mid, MD_RDONLY);	err = fmpCheckDiskError(NULL, fsinfo);	if ( err < E_OK ) {		goto err_ret;	}	return E_OK;err_ret:	DEBUG_PRINT(("fmpGetFileName err = %d\n", err));	return err;}/* ======================================================================== *//* *	Convert the endian. *//* * Convert the endian of character string. */EXPORT W fmConvEndianTC( TC *to, TC *from, W max, BOOL bigEndian ){	TC	ch;	W	i;	for ( i = 0; i < max; ++i ) {		*(to++) = ch = fmConvEndianH(*(from++), bigEndian);		if ( ch == TNULL ) {			break;		}	}	while ( i < --max ) {		*(to++) = TNULL;	/* Fill the remainder with 0.  */	}	return i;}/* * Convert the endian of UH data string. */EXPORT void fmConvEndianHs( UH *to, UH *from, W len, BOOL bigEndian ){	while ( --len >= 0 ) {		*(to++) = fmConvEndianH(*(from++), bigEndian);	}}/* ======================================================================== *//* *	Time *//* * Obtain the current time (GMT). */EXPORT STIME fmGetTime( void ){	STIME	now = 0;#if USE_CLOCK_MANAGER#ifdef DEBUG	ER err = tkse_get_tim2(&now, NULL);	if ( err < E_OK ) {		DEBUG_PRINT(("fmGetTime err = %d\n", err));	}#else	tkse_get_tim2(&now, NULL);#endif#endif	return now;}/* * Update the time stamp. *	mode	F_READ|F_EXCUTE	Update the date/time of access. *		F_WRITE		Update the date/time of update. */EXPORT ER fmpSetTimeStamp( OFCB *ofcb, UW mode ){	FsInfo		*fsinfo = ofcb->fsinfo;	DfFileHeader	*fhd;	STIME		now;	ID		mid;	mode &= F_WRITE|F_READ|F_EXCUTE;	/* Do nothing if the file system is not writable. */	if ( isNoWriteFS(fsinfo) != 0 ) {		return E_OK;	}	/* Process the time stamp update control option. */	if ( ((fmInfo.updTimeStamp & UTS_RecordRead) != 0U)	  && ((mode & ~(UW)(F_READ|F_EXCUTE)) == 0U) ) {		return E_OK;	}	/* Current time */	now = fmGetTime();	now = (STIME)fmpConvEndianW((UW)now, fsinfo);	/* Map the file header. */	fhd = fmpMapDskAdr(ofcb->fhead, sizeof(DfFileHeader),					ofcb, &mid, fsinfo);	if ( fhd == NULL ) {		return (ER)mid;	}	if ( (mode & (F_READ|F_EXCUTE)) != 0U ) {		/* Update the date/time of access. */		fhd->atime = now;	}	if ( (mode & F_WRITE) != 0U ) {		/* Update the date/time of update. */		fhd->mtime = now;	}	fmpUnmapDisk(mid, MD_WRITE);	return fmpCheckDiskError(ofcb, fsinfo);}/* * Update the time stamp. *	mode	F_READ|F_EXCUTE	Update the date/time of access. *		F_WRITE		Update the date/time of update. *	Return MD_WRITE when writing is performed to fh. *	Otherwise, return MD_RDONLY. *	However, when err < E_OK, treat it as MD_WRITE. */EXPORT WER fmpSetTimeStampFh( DfFileHeader *fh, UW mode, FsInfo *fsinfo ){	STIME		now;	ER		err;	/* Do nothing if the file system is not writable. */	if ( isNoWriteFS(fsinfo) != 0 ) {		return MD_RDONLY;	}	/* Current time */	now = fmGetTime();	now = (STIME)fmpConvEndianW((UW)now, fsinfo);	if ( (mode & (F_READ|F_EXCUTE)) != 0U ) {		/* Update the date/time of access. */		fh->atime = now;	}	if ( (mode & F_WRITE) != 0U ) {		/* Update the date/time of update. */		fh->mtime = now;	}	err = fmpCheckDiskError(NULL, fsinfo);	if ( err < E_OK ) {		return err;	}	return MD_WRITE;}/* ======================================================================== *//* *	Logical block list *//* * Create new logical block list. */EXPORT ER fmNewLBlks( LBlks *lb ){	LBList	*lp;	lb->nlblk = 0;	QueInit(&lb->list);	lp = (LBList*)Vmalloc(sizeof(LBList));	if ( lp == NULL ) {		return E_SYSMEM;	}	QueInsert(&lp->q, &lb->list);	lb->next = &lp->lblk[0];	return E_OK;}/* * Delete the logical block list. */EXPORT void fmDeleteLBlks( LBlks *lb ){	LBList	*lp;	while ( (lp = (LBList*)QueRemoveNext(&lb->list)) != NULL ) {		Vfree((VB*)lp);	}}/* * Add the logical block to the logical block list. */EXPORT ER fmAddLBlks( LBlks *lb, LogBlk lblk ){	LBList	*lp;	*(lb->next++) = lblk;	lb->nlblk++;	if ( (lb->nlblk % nLBlks) == 0 ) {		/* Add LBList. */		lp = (LBList*)Vmalloc(sizeof(LBList));		if ( lp == NULL ) {			return E_SYSMEM;		}		QueInsert(&lp->q, &lb->list);		lb->next = &lp->lblk[0];	}	return E_OK;}/* * Return the location of the next entry of the logical block list to *lblk. *	At first, call it with *lblk = NULL. *	Return FALSE when reach the end. */EXPORT BOOL fmNextLBlks( LBlks *lb, LogBlk **lblk ){	if ( *lblk == NULL ) {		/* Start */		lb->read = (LBList*)lb->list.next;		*lblk = &lb->read->lblk[0];		return ( *lblk != lb->next );	}	/* Advance to the next. */	(*lblk)++;	if ( *lblk > &lb->read->lblk[nLBlks - 1] ) {		/* Move to the next LBList. */		lb->read = (LBList*)lb->read->q.next;		*lblk = &lb->read->lblk[0];	}	return ( *lblk != lb->next );}/* ======================================================================== *//* *	Index record address *//* * Extend the index level. *	Extend the index level of *idxadr with the location of new root indirect index *	defined as newroot. */EXPORT void fmpExpandIdxAdr( IdxAdr *idxadr, DskAdr newroot ){	W	i;	for ( i = MaxIndexLevel - 1; i > 0; --i ) {		idxadr->iidx[i] = idxadr->iidx[i - 1];	}	idxadr->iidx[0] = newroot;}/* ======================================================================== *//* *	Retrieve a file name. *//* * Prepare to retrieve a file name. *	When the file name to be retrieved is constant, set fname to the file name. *	The speed becomes higher because the computation of abbreviated name is required only once. *	Since fname stores only the address, the call side must hold the memory of fname *	until fmpCloseSFN is executed. *	When the file name is not specified, fname = NULL. */EXPORT ER fmpOpenSFN( SFN *sfn, FileName fname, FsInfo *fsinfo ){	memset(sfn, 0, (size_t)sizeof(SFN));	if ( fname != NULL ) {		/* Save the file name and abbreviated name. */		sfn->fname = fname;		sfn->sname = fmShortFileName(fname);	}	sfn->fsinfo = fsinfo;	sfn->idx = N_SFN_MAPINFO - 1;	return E_OK;}/* * Finish retrieving the file name. */EXPORT ER fmpCloseSFN( SFN *sfn ){	struct sfn_mapinfo *mi;	ER	err;	/* Unmap all. */	for ( mi = sfn->mi; mi < &sfn->mi[N_SFN_MAPINFO]; mi++ ) {		if ( mi->mid == 0 ) {			continue;		}		fmpUnmapDisk(mi->mid, MD_RDONLY);	}	err = fmpCheckDiskError(NULL, sfn->fsinfo);	if ( err < E_OK ) {		sfn->error = err;		DEBUG_PRINT(("fmpCloseSFN err = %d\n", err));	}	return sfn->error;}/* * Return the address of the abbreviated name of the file of fid in the file abbreviated name table. * The returned address is valid until getSFNp() is called next time. * Do not access the abbreviated names (addresses) of before and after it. */LOCAL DfShortName* getSFNp( SFN *sfn, FID fid ){	struct sfn_mapinfo *mi;	W	n, nf;	FsInfo	*fsinfo = sfn->fsinfo;	ER	err;	/* Find from the ones already mapped. */	for ( mi = sfn->mi; mi < &sfn->mi[N_SFN_MAPINFO]; mi++ ) {		if ( mi->mid == 0 ) {			continue;		}		n = fid - mi->topfid;		if ( (n >= 0) && (n < mi->nfid) ) {			/* Some are already mapped. */			return mi->mapbase + n;		}	}	/* Nothing is mapped. */	sfn->idx = (sfn->idx + 1) % N_SFN_MAPINFO;	mi = &sfn->mi[sfn->idx];	if ( mi->mid != 0 ) {		/* Unmap the ones already mapped now. */		fmpUnmapDisk(mi->mid, MD_RDONLY);		mi->mid = 0;	}	/* Perform a new mapping. */	nf = (W)(fsinfo->sblk / sizeof(DfShortName));	mi->topfid = (UH)(fid - (fid % nf));	n = fsinfo->nfmax - mi->topfid;	if ( nf > n ) {		nf = n;	}	mi->nfid = (UH)nf;	mi->mapbase = fmpMapDskAdrS((DfShortName*)fsinfo->fsnt + mi->topfid,		(nf * (W)sizeof(DfShortName)), MAP_SYS(fsinfo), &err, fsinfo);	if ( mi->mapbase == NULL ) {		goto err_ret;	}	mi->mid = (ID)err;	return mi->mapbase + (fid - mi->topfid);err_ret:	sfn->error = err;	DEBUG_PRINT(("getSFNp err = %d\n", err));	return &sfn->dummy;}/* * Judge whether the file name matches. *	Judge whether the file name of the file of fid matches with fname. *	When fname == NULL, use fname specified with fmpOpenSFN. *	If it matches, return 1. If not matches, return 0. */EXPORT WER fmpMatchSFN( SFN *sfn, FID fid, FileName fname ){	FsInfo		*fsinfo = sfn->fsinfo;	DfShortName	sname, sn;	FileName	nm;	BOOL		match;	ER		err;	if ( fid >= fsinfo->nfmax ) {		err = E_NOEXS;		goto err_ret;	}	if ( fname == NULL ) {		fname = sfn->fname;		sname = sfn->sname;	} else {		sname = fmShortFileName(fname);	}	/* Abbreviated name of the file of fid */	sn = fmpConvEndianW(*getSFNp(sfn, fid), fsinfo);	/* Abbreviated name matched? */	match = ( sname == sn );	if ( match != 0 ) {		/* Obtain the file name. */		err = fmpGetFileName(fid, nm, fsinfo);		if ( err < E_OK ) {			goto err_ret;		}		/* File name matched? */		match = ( tc_strncmp(fname, nm, FileNameLen) == 0 );	}	return match;err_ret:	DEBUG_PRINT(("fmpMatchSFN err = %d\n", err));	return err;}/* ======================================================================== *//* *	LINK generation *//* * Generate LINK from the link index. */EXPORT void fmpLIdxToLINK( LINK *lnk, DfLinkIndex *lidx, FsInfo *fsinfo ){	BOOL	bigEndian = fsinfo->bigEndian;	tc_strncpy(lnk->fs_name, fsinfo->fsName, FsNameLen);	lnk->f_id = fmConvEndianH(lidx->fid, bigEndian);	lnk->atr1 = fmConvEndianH(lidx->atr[TSD_LTL_POS_0], bigEndian);	lnk->atr2 = fmConvEndianH(lidx->atr[TSD_LTL_POS_1], bigEndian);	lnk->atr3 = fmConvEndianH(lidx->atr[TSD_LTL_POS_2], bigEndian);	lnk->atr4 = fmConvEndianH(lidx->atr[TSD_LTL_POS_3], bigEndian);	lnk->atr5 = fmConvEndianH(lidx->atr[TSD_LTL_POS_4], bigEndian);}

⌨️ 快捷键说明

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