📄 fileio.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. * *---------------------------------------------------------------------- *//* * @(#)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 + -