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

📄 fileio.c

📁 T-kernel 的extension源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *---------------------------------------------------------------------- *    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. * *---------------------------------------------------------------------- *//* *	@(#)fileio.c (seio) * *	Standard input-output *	File input-output common part  */#include "sfmgr.h"#define TSD_FIO_VAL_2		2#define TSD_FIO_SZT_2		2#define TSD_UUT_VAL_2		2#define TSD_PAR_MSK_0XFF00	0xff00U#define TSD_CFA_STK_2048	(2*1024)#define TSD_UOP_MSK_0X03	0x03UInline FD* searchFileDescriptor( UXINFO *uxinfo, int fildes );Inline void Lock_UX( void );Inline void Unlock_UX( void );Inline void Lock_FS( FS *fs );Inline void Unlock_FS( FS *fs );LOCAL WER get_DeviceNumber( TC *devnm );LOCAL FS* new_FileSystem( const TC *devnm, const B *connm, W mode, ER *err );LOCAL ER del_FileSystem( FS *fs );LOCAL ER new_FileDescriptor( FS *fs, FDPkt *fdp, UXINFO *uxinfo );LOCAL ER del_FileDescriptor( UXINFO *uxinfo, FDPkt *fdp );LOCAL WER dup_FileDescriptor( UXINFO *uxinfo, FDPkt *fdp );LOCAL FS* searchFileSystem_devnm( const TC *devnm );LOCAL FS* searchFileSystem_path( B **path, UXINFO *uxinfo );LOCAL ER _u_attach( FS *fs, CmdPkt *pkt );LOCAL ER _u_detach( FS *fs, CmdPkt *pkt );LOCAL WER _u_open( FS *fs, CmdPkt *pkt );LOCAL ER _u_close( FS *fs, CmdPkt *pkt );LOCAL WER _u_lseek( FS *fs, CmdPkt *pkt );LOCAL WER _u_read( FS *fs, CmdPkt *pkt );LOCAL WER _u_write( FS *fs, CmdPkt *pkt );LOCAL WER _u_getdents( FS *fs, CmdPkt *pkt );LOCAL WER _u_fsync( FS *fs, CmdPkt *pkt );LOCAL WER _u_dup( FS *fs, CmdPkt *pkt );LOCAL WER _u_dup2( FS *fs, CmdPkt *pkt );LOCAL ER _u_rename( FS *fs, CmdPkt *pkt );LOCAL ER _u_unlink( FS *fs, CmdPkt *pkt );LOCAL ER _u_chdir( FS *fs, CmdPkt *pkt );LOCAL ER _u_fchdir( FS *fs, CmdPkt *pkt );LOCAL ER _u_chmod( FS *fs, CmdPkt *pkt );LOCAL ER _u_fchmod( FS *fs, CmdPkt *pkt );LOCAL ER _u_mkdir( FS *fs, CmdPkt *pkt );LOCAL ER _u_rmdir( FS *fs, CmdPkt *pkt );LOCAL WER _u_creat( FS *fs, CmdPkt *pkt );LOCAL ER _u_utimes( FS *fs, CmdPkt *pkt );LOCAL WER _u_umask( FS *fs, CmdPkt *pkt );LOCAL ER _u_truncate( FS *fs, CmdPkt *pkt );LOCAL ER _u_ftruncate( FS *fs, CmdPkt *pkt );LOCAL ER _u_sync( FS *fs, CmdPkt *pkt );LOCAL ER _u_stat( FS *fs, CmdPkt *pkt );LOCAL ER _u_lstat( FS *fs, CmdPkt *pkt );LOCAL ER _u_fstat( FS *fs, CmdPkt *pkt );LOCAL ER _u_getfsstat( FS *fs, CmdPkt *pkt );LOCAL ER _u_getlink( FS *fs, CmdPkt *pkt );LOCAL ER _u_lookup( FS *fs, CmdPkt *pkt );LOCAL ER CallFileFunction( FS *fs, CmdPkt *pkt );LOCAL void FileSystemTask( FS *fs );LOCAL ER CallFileSystemTask( FS *fs, CmdPkt *pkt );/* * Disc error handler */EXPORT void DiskErrorHandler( DiskErrInfo *info ){	INODE	*inode = (VP)info->mode.info;	FS	*fs;	T_RTSK	rtsk;	tk_ref_tsk(info->taskid, &rtsk);	fs = (FS*)rtsk.exinf;	if ( inode == NULL ) {		/* The error caused in common portion*/		if ( fs != NULL ) {			fs->diskerr = info->err;		}	} else {		/* The error caused in file individual portion */		inode->diskerr = info->err;	}}/* * Disk error check *	inode == NULL	The error caused in common part *	inode != NULL	The error caused in file unit */EXPORT ER CheckDiskError( FS *fs, INODE *inode ){	UW	imask;	ER	err, error = E_OK;	/* Work with a disk error handler exclusively */	if ( inode != NULL ) {		DI(imask);		err = inode->diskerr;		inode->diskerr = E_OK;		EI(imask);		if ( err < E_OK ) {			error = err;		}	}	DI(imask);	err = fs->diskerr;	fs->diskerr = E_OK;	EI(imask);	if ( err < E_OK ) {		error = err;	}	return error;}/* --------------------------------------------------------------------------- *//* * Acquisition of device number *	Acquire the device number from device name. */LOCAL WER get_DeviceNumber( TC *devnm ){	ID	devid;	UB	dn[L_DEVNM + 1];	TC	tcdn[L_DEVNM + 1];	ER	err;	/* Conversion of device name */	tc_strncpy(tcdn, devnm, L_DEVNM);	tcdn[L_DEVNM] = TNULL;	err = tcstoeucs(dn, tcdn);	if ( err < E_OK ) {		goto err_ret;	}	/* Acquisition of device ID */	devid = tk_ref_dev(dn, NULL);	if ( devid < E_OK ) {		err = E_NOEXS;		goto err_ret;	}	return devid;err_ret:	DEBUG_PRINT(("get_DeviceNumber err=%#x\n", err));	return err;}/* --------------------------------------------------------------------------- *//* * File system information queue */EXPORT	QUEUE	FSQue = { &FSQue, &FSQue };/* * Creation of file system connection information */LOCAL FS* new_FileSystem( const TC *devnm, const B *connm, W mode, ER *err ){	FS	*fs;	QUEUE	*q;	W	size;	/* Size of file system connection information*/	size = get_fssize(mode);	if (size < 0) {		*err = E_PAR;		goto err_ret;	}	/* Check of Same name device name or connection name  */	for ( q = FSQue.next; q != &FSQue; q = q->next ) {		fs = (FS*)q;		if (( tc_strncmp(fs->devnm, (const TC*)devnm, L_DEVNM) == 0 )||		    ( strncmp(fs->connm, connm, (size_t)L_FCONNM) == 0 )) {			*err = E_OBJ;			goto err_ret;		}	}	/* Creation of file system information */	fs = Kcalloc(1U, (UW)size);	if ( fs == NULL ) {		*err = E_NOMEM;		goto err_ret;	}	QueInsert(&fs->q, &FSQue);	tc_strncpy(fs->devnm, (const TC*)devnm, L_DEVNM);	strncpy(fs->connm, connm, (size_t)L_FCONNM);	fs->mode = mode;	fs->diskerr = E_OK;	return fs;err_ret:	DEBUG_PRINT(("new_FileSystem NULL\n"));	return NULL;}/* * Deletion of file system connection information */LOCAL ER del_FileSystem( FS *fs ){	QueRemove(&fs->q);	Kfree(fs);	return E_OK;}/* * Creation of file descriptor */LOCAL ER new_FileDescriptor( FS *fs, FDPkt *fdp, UXINFO *uxinfo ){	FD	*fd;	W	size, i;	ER	err;	/* Size of file descriptor */	if ( fs == (FS*)&STD_FS ) {		/* Standard file system */		size = sizeof(SFFD);	} else if ( fs == (FS*)&ROOT_FS ) {		/* Root directory */		size = sizeof(RTFD);	} else if ( fs != NULL ) {		/* Other file systems */		size = get_fssize(fs->mode);		if (size < 0) {			err = E_PAR;			goto err_ret;		}	} else {		err = E_PAR;		goto err_ret;	}	if ( uxinfo->fdtbl == NULL ) {		err = E_SYSMEM;		goto err_ret;	}	for ( i = 0; i < MaxOpenF; ++i ) {		if ( uxinfo->fdtbl[i] == NULL ) {			break;		}	}	if ( i >= MaxOpenF ) {		err = toERUX(EMFILE);		goto err_ret;	}	fd = Vcalloc(1U, (UW)size);	if ( fd == NULL ) {		err = E_NOMEM;		goto err_ret;	}	fd->fs = fs;	fd->inode = NULL;	fd->fpos = 0;	fd->refcnt = 1;	fdp->fdno = i;	fdp->fd = fd;	/* Registration of file descriptor */	uxinfo->fdtbl[i] = fd;	return E_OK;err_ret:	DEBUG_PRINT(("new_FileDescriptor err=%#x\n", err));	return err;}/* * Deletion of file descriptor */LOCAL ER del_FileDescriptor( UXINFO *uxinfo, FDPkt *fdp ){	FD	*fd = fdp->fd;	ER	err, error = E_OK;	uxinfo->fdtbl[fdp->fdno] = NULL;	if ( --fd->refcnt > 0 ) {		return E_OK;	}	/* Release of file reference node */	err = inode_Release(fd->fs, fd->inode, fd->omode, TRUE);	if ( err < E_OK ) {		error = err;	}	Vfree(fdp->fd);#ifdef DEBUG	if ( error < E_OK ) {		DEBUG_PRINT(("del_FileDescriptor err=%#x\n", error));	}#endif	return error;}/* * Search of file descriptor */Inline FD* searchFileDescriptor( UXINFO *uxinfo, int fildes ){	if ( uxinfo->fdtbl == NULL ) {		return NULL;	}	if (( fildes < 0 )||( fildes >= MaxOpenF )) {		return NULL;	}	return uxinfo->fdtbl[fildes];}/* * Duplicate of file descriptor */LOCAL WER dup_FileDescriptor( UXINFO *uxinfo, FDPkt *fdp ){	FD	*old = fdp->fd;	W	i;	ER	err;	if ( uxinfo->fdtbl == NULL ) {		err = E_SYSMEM;		goto err_ret;	}	for ( i = 0; i < MaxOpenF; ++i ) {		if ( uxinfo->fdtbl[i] == NULL ) {			break;		}	}	if ( i >= MaxOpenF ) {		err = toERUX(EMFILE);		goto err_ret;	}	/* Duplicate of file descriptor */	uxinfo->fdtbl[i] = old;	old->refcnt++;	return i;err_ret:	DEBUG_PRINT(("dup_FileDescriptor err=%#x\n", err));	return err;}/* --------------------------------------------------------------------------- *//* * Selection of file system from device name */LOCAL FS* searchFileSystem_devnm( const TC *devnm ){	QUEUE	*q;	FS	*fs;	/* Search of file system queue */	for ( q = FSQue.next; q != &FSQue; q = q->next ) {		fs = (FS*)q;		if ( tc_strncmp(fs->devnm, (const TC*)devnm, L_DEVNM) == 0 ) {			/* File system */			return fs;		}	}	/* Standard file system*/	return (FS*)&STD_FS;}/* * Selection of file system from path name *	1. Select the file system from connection name. *		In the case of absolute path, read the path name until just before the connection name. *		*In the case where current directory is a root, read to the top of connection name. *	2. Select the file system from current directory. *		 Keep path name as it is  */LOCAL FS* searchFileSystem_path( B **path, UXINFO *uxinfo ){	QUEUE		*q;	FS		*fs;	B		c, connm[L_FCONNM + 1], *p, *np;	W		len;	if ( **path != '/' ) {	/* Relative path */		/* Root directory if it is the path name termination  */		if ( **path == '\0' ) {			return (FS*)&ROOT_FS;		}		/* Current directory file system */		fs = uxinfo->curdir.fs;		if ( fs != (FS*)&ROOT_FS ) {			return fs;		}		p = *path;	} else {		/* Absolute path */		/* Forward to the first file name */		for( p = *path; *p == '/'; p++ ) {			;		}	}	/* Read to the connection name */	while ( (np = strchr(p, '/')) != NULL ) {		/* Disregard "." and  ".." */		if ((((np - p) == 1 )&&( strncmp(p, ".", (size_t)1) == 0)) ||		    (((np - p) == TSD_FIO_VAL_2 )&&( strncmp(p, "..", (size_t)TSD_FIO_SZT_2) == 0))) {			for( ; *(np + 1) == '/'; np++ ) {				;			}			*path = np;			p = ++np;			continue;		}		break;	}	if ( np == NULL ) {		np = strchr(p, '\0');		/* Root directory if it is the path name termination*/		if (((np - p) == 0) ||		    (((np - p) == 1 )&&( strncmp(p, ".", (size_t)1) == 0)) ||		    (((np - p) == TSD_FIO_VAL_2 )&&( strncmp(p, "..", (size_t)TSD_FIO_SZT_2) == 0))) {			*path = np;			return (FS*)&ROOT_FS;		}	}	/* Acquisition of connection name from path name */	for ( len = 0; len < L_FCONNM; len++) {		c = *(p + len);		if (( c == '\0' )||( c == '/' )) {			break;		}		connm[len] = c;	}	connm[len] = '\0';	for ( q = FSQue.next; q != &FSQue; q = q->next ) {		fs = (FS*)q;		if ( strncmp(fs->connm, connm, (size_t)L_FCONNM) == 0 ) {			/* File system */			return fs;		}	}	/* Standard file system*/	return (FS*)&STD_FS;}/* --------------------------------------------------------------------------- *//* * SEIO Lock */Inline void Lock_UX( void ){	Lock(&UxLock);}/* * SEIO Unlock */Inline void Unlock_UX( void ){	Unlock(&UxLock);}/* * File system lock */Inline void Lock_FS( FS *fs ){	if (( fs != NULL )&&	    ( fs != (FS*)&STD_FS )&&	    ( fs != (FS*)&ROOT_FS )&&	    ( fs != (FS*)&STDIO_FS )) {		/* Lock */		Lock(&fs->lock);	}}/* * File system unlock */Inline void Unlock_FS( FS *fs ){	if (( fs != NULL )&&	    ( fs != (FS*)&STD_FS )&&	    ( fs != (FS*)&ROOT_FS )&&	    ( fs != (FS*)&STDIO_FS )) {		/* Unlock */		Unlock(&fs->lock);	}}/* --------------------------------------------------------------------------- *//* * File system connection */LOCAL ER _u_attach( FS *fs, CmdPkt *pkt ){	SF_ATTACH_PARA *para = pkt->cmd.para;	ER	err;	/* Queue initialization */	inode_QueInit(fs);	if ( ((UW)para->mode & TSD_PAR_MSK_0XFF00) == SF_STDFS ) {		err = sf_attach(para->devnm, para->connm, para->mode);	} else {		err = call_attach( (UW)para->mode & TSD_PAR_MSK_0XFF00 , fs);	}	if ( err < E_OK ) {		goto err_ret;	}	return E_OK;err_ret:	DEBUG_PRINT(("_u_attach err=%#x\n", err));	return err;}/* * File system detachment */LOCAL ER _u_detach( FS *fs, CmdPkt *pkt ){	SF_DETACH_PARA	*para = pkt->cmd.para;	ER		err;	/* Check if there is the process under referencing or not */	err = inode_CheckEmpty(fs);	if ( err < E_OK ) {		goto err_ret;	}	if ( fs != (FS*)&STD_FS ) {		/* Detachment processing */		err = (*fs->u_detach)(fs, para->eject);	} else {		/* Standard FS detachment processing */		err = sf_detach(para->devnm, para->eject);	}	if ( err < E_OK ) {		goto err_ret;	}	return E_OK;err_ret:	DEBUG_PRINT(("_u_detach err=%#x\n", err));	return err;}/* * File open */LOCAL WER _u_open( FS *fs, CmdPkt *pkt ){	SF_OPEN_PARA	*para = pkt->cmd.para;	LPINF		*lp = pkt->exinf;	INODE		*inode = lp->inode;	W		oflag = para->oflag, fildes;	mode_t		mode = 0;	FDPkt		fdp;	ER		err;	/* Parameter check */	if ( ((UW)oflag & TSD_UOP_MSK_0X03) > O_RDWR ) {		err = E_PAR;		goto err_ret1;	}	if (( fs != (FS*)&ROOT_FS )&&( fs != (FS*)&STDIO_FS )) {		/* Check the file system writing access */		if ( (((UW)oflag & O_ACCMODE) != O_RDONLY )&&		     ((fs != (FS*)&STD_FS) &&( fs->rdonly)) ) {			err = E_RONLY;			goto err_ret1;		}		if ( inode->ino != NOEXS_INO ) {	/* Existent file */			if ( (((UW)oflag & O_CREAT) != 0) && (((UW)oflag & O_EXCL) != 0) ) {				err = E_OBJ;				goto err_ret1;			}			if (( inode->type == DT_DIR )&&( ((UW)oflag & O_ACCMODE) != O_RDONLY )) {				/* Directory is reading open */				err = toERUX(EISDIR);				goto err_ret1;			}		} else {				/* Nonnexisitent file */			if ( ((UW)oflag & O_CREAT) == 0 ) {				err = E_NOEXS;				goto err_ret1;			}			/* Writing access of file system */			if (( fs != (FS*)&STD_FS )&&( fs->rdonly )) {				err = E_RONLY;				goto err_ret1;			}			/* File creation mode */			mode = (mode_t)para->mode & ~(pkt->uxinfo->cmask);		}	}	/* Creation of file descriptor */	err = new_FileDescriptor(fs, &fdp, pkt->uxinfo);	if ( err < E_OK ) {		goto err_ret1;	}	/* Open */	fdp.fd->inode = inode;	if ( fs == (FS*)&STD_FS ) {		fildes = sf_open(&fdp, lp->path, para->oflag, mode);		if ( fildes < E_OK ) {			err = fildes;			goto err_ret2;		}	} else if ( fs == (FS*)&ROOT_FS ) {		fildes = rt_open(&fdp, para->oflag, mode);		if ( fildes < E_OK ) {			err = fildes;			goto err_ret2;		}	} else if ( fs == (FS*)&STDIO_FS ) {		fildes = std_open(&fdp, para->oflag, mode);		if ( fildes < E_OK ) {			err = fildes;			goto err_ret2; 		}	} else {		fildes = (*fs->u_open)(&fdp, lp->path, para->oflag, mode);		if ( fildes < E_OK ) {			err = fildes;			goto err_ret2;		}		(void)SyncFS(fs->diskid, NULL);		err = CheckDiskError(fs, NULL);		if ( err < E_OK ) {			goto err_ret2;		}	}	/* Registration of file reference node */	inode_Register(fs, fdp.fd->inode, fdp.fd->omode);	return fildes;err_ret2:	fdp.fd->inode = NULL;	(void)del_FileDescriptor(pkt->uxinfo, &fdp);err_ret1:	inode_Free(fs, inode);	DEBUG_PRINT(("_u_open err=%#x\n", err));	return err;}/* * File close */LOCAL ER _u_close( FS *fs, CmdPkt *pkt ){	SF_CLOSE_PARA	*para = pkt->cmd.para;	FD		*fd;	FDPkt		fdp;	ER		err, error = E_OK;	/* Search of file descriptor */	fd = searchFileDescriptor(pkt->uxinfo, para->fildes);	if (( fd == NULL )||( fd->fs != fs )) {		error = E_FD;		goto err_ret;	}	fdp.fd = fd;	fdp.fdno = para->fildes;	/* Close */	if ( fd->refcnt <= 1 ) {		if ( fs == (FS*)&STD_FS ) {			err = sf_close(&fdp);		} else if ( fs == (FS*)&ROOT_FS ) {			err = rt_close(&fdp);		} else if ( fs == (FS*)&STDIO_FS ) {			err = std_close(&fdp);		} else {			err = (*fs->u_close)(&fdp);		}		if ( err < E_OK ) {			error = err;		}	}	/* Deletion of file descriptor */	err = del_FileDescriptor(pkt->uxinfo, &fdp);	if (( err < E_OK )&&( error == E_OK )) {		error = err;	}err_ret:

⌨️ 快捷键说明

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