📄 file.cxx
字号:
//==========================================================================
//
// file.cxx
//
// Fileio file operations
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): nickg
// Contributors: nickg
// Date: 2000-05-25
// Purpose: Fileio file operations
// Description: These are the functions that operate on files as a whole,
// such as open(), creat(), mkdir() etc.
//
//
//
//####DESCRIPTIONEND####
//
//==========================================================================
#include <pkgconf/hal.h>
#include <pkgconf/io_fileio.h>
#include <pkgconf/isoinfra.h>
#include <cyg/infra/cyg_trac.h> // tracing macros
#include <cyg/infra/cyg_ass.h> // assertion macros
#include <string.h> // string functions
#include <dirent.h>
#include <stdio.h> // stdin, stdout, stderr
#include "fio.h" // Private header
//==========================================================================
// Implement filesystem locking protocol.
#define LOCK_FS( _mte_ ) { \
CYG_ASSERT(_mte_ != NULL, "Bad mount table entry"); \
CYG_ASSERT(_mte_->fs != NULL, "Bad mount filesystem entry"); \
cyg_fs_lock( _mte_, (_mte_)->fs->syncmode); \
}
#define UNLOCK_FS( _mte_ ) cyg_fs_unlock( _mte_, (_mte_)->fs->syncmode)
//==========================================================================
// A local strcpy clone that returns a pointer to the end of the copied
// string, not the beginning.
static char *my_strcpy( char *s1, const char *s2 )
{
while( (*s1++ = *s2++) != 0);
return s1-1;
}
//==========================================================================
// Compare a pathname fragment with an element in a pathname. This
// deals with zero or separator termination and avoids substring
// matches.
static int pathcmp( const char *path, const char *name )
{
while( *path == *name && *path != '\0' )
path++, name++;
if( *name != '\0' ) return false;
if( *path == '/' || *path == '\0' ) return true;
return false;
}
//==========================================================================
// CWD support
#ifdef CYGPKG_IO_FILEIO_TRACK_CWD
// buffer for storing CWD path
static char cwd[PATH_MAX];
static size_t cwd_size = 0;
static void update_cwd( cyg_mtab_entry *mte, cyg_dir dir, const char *path )
{
char *p = cwd;
if( mte != cyg_cdir_mtab_entry || dir != cyg_cdir_dir )
{
// Here, the path is relative to the root of the filesystem,
// or in a totally new filesystem, initialize the cwd with the
// mount point name of the filesystem.
p = my_strcpy( p, mte->name );
}
else p = cwd+cwd_size;
// We must now copy the path into the cwd buffer while dealing
// with any "." and ".." components textually.
while( *path != '\0' )
{
// skip any stray directory separators.
if( *path == '/' ) path++;
// Look for a "." entry and just ignore it.
if( pathcmp( path, "." ) )
{
path++;
continue;
}
// Look for a ".." entry. If found, chew off the last cwd
// entry.
if( pathcmp( path, ".." ) )
{
while( *(--p) != '/' ); // back up to last '/'
path += 2; // skip "..".
continue;
}
// Otherwise just copy the name fragment over to the cwd.
if( *(p-1) != '/' )
*p++ = '/'; // add a directory separator
while( *path != '/' && *path != '\0' )
*p++ = *path++;
}
// Zero terminate the cwd.
*p = '\0';
// update size
cwd_size = p-cwd;
}
#else
#ifdef CYGPKG_KERNEL
static Cyg_Mutex getcwd_lock CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_IO_FS);
#endif
#endif
//==========================================================================
// Open a file
__externC int open( const char *path, int oflag, ... )
{
FILEIO_ENTRY();
// we want to be sure we pull in stdin/out/err, so they can be
// assigned to fds 0, 1 and 2
#ifdef CYGINT_ISO_STDIO_STREAMS
CYG_REFERENCE_OBJECT(stdin);
CYG_REFERENCE_OBJECT(stdout);
CYG_REFERENCE_OBJECT(stderr);
#endif
CYG_CANCELLATION_POINT;
int ret = 0;
int fd;
cyg_file *file;
cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
cyg_dir dir = cyg_cdir_dir;
const char *name = path;
// At least one of O_RDONLY, O_WRONLY, O_RDWR must be provided
if( (oflag & O_RDWR) == 0 )
FILEIO_RETURN(EINVAL);
fd = cyg_fd_alloc(0);
if( fd < 0 )
FILEIO_RETURN(EMFILE);
file = cyg_file_alloc();
if( file == NULL )
{
cyg_fd_free(fd);
FILEIO_RETURN(ENFILE);
}
ret = cyg_mtab_lookup( &dir, &name, &mte );
if( 0 != ret )
{
cyg_fd_free(fd);
cyg_file_free(file);
FILEIO_RETURN(ENOENT);
}
LOCK_FS( mte );
ret = mte->fs->open( mte, dir, name, oflag, file );
UNLOCK_FS( mte );
if( 0 != ret )
{
cyg_fd_free(fd);
cyg_file_free(file);
FILEIO_RETURN(ret);
}
file->f_mte = mte;
file->f_syncmode = mte->fs->syncmode;
cyg_fd_assign( fd, file );
FILEIO_RETURN_VALUE(fd);
}
//==========================================================================
// create a file
__externC int creat( const char *path, mode_t mode )
{
return open( path, O_WRONLY | O_CREAT | O_TRUNC, mode );
}
//==========================================================================
// Unlink/remove a file
__externC int unlink( const char *path )
{
FILEIO_ENTRY();
int ret = 0;
cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
cyg_dir dir = cyg_cdir_dir;
const char *name = path;
ret = cyg_mtab_lookup( &dir, &name, &mte );
if( 0 != ret )
FILEIO_RETURN(ENOENT);
LOCK_FS( mte );
ret = mte->fs->unlink( mte, dir, name );
UNLOCK_FS( mte );
FILEIO_RETURN(ret);
}
//==========================================================================
// Make a directory
__externC int mkdir( const char *path, mode_t mode )
{
FILEIO_ENTRY();
int ret = 0;
cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
cyg_dir dir = cyg_cdir_dir;
const char *name = path;
mode=mode;
ret = cyg_mtab_lookup( &dir, &name, &mte );
if( 0 != ret )
FILEIO_RETURN(ENOENT);
LOCK_FS( mte );
ret = mte->fs->mkdir( mte, dir, name );
UNLOCK_FS( mte );
FILEIO_RETURN(ret);
}
//==========================================================================
// Remove a directory
__externC int rmdir( const char *path )
{
FILEIO_ENTRY();
int ret = 0;
cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
cyg_dir dir = cyg_cdir_dir;
const char *name = path;
ret = cyg_mtab_lookup( &dir, &name, &mte );
if( 0 != ret )
FILEIO_RETURN(ENOENT);
LOCK_FS( mte );
ret = mte->fs->rmdir( mte, dir, name );
UNLOCK_FS( mte );
FILEIO_RETURN(ret);
}
//==========================================================================
// Rename a file
__externC int rename( const char *path1, const char *path2 ) __THROW
{
FILEIO_ENTRY();
int ret = 0;
cyg_mtab_entry *mte1 = cyg_cdir_mtab_entry;
cyg_mtab_entry *mte2 = cyg_cdir_mtab_entry;
cyg_dir dir1 = cyg_cdir_dir;
cyg_dir dir2 = cyg_cdir_dir;
const char *name1 = path1;
const char *name2 = path2;
ret = cyg_mtab_lookup( &dir1, &name1, &mte1 );
if( 0 != ret )
FILEIO_RETURN(ENOENT);
ret = cyg_mtab_lookup( &dir2, &name2, &mte2 );
if( 0 != ret )
FILEIO_RETURN(ENOENT);
// Cannot rename between different filesystems
if( mte1 != mte2 )
FILEIO_RETURN(EXDEV);
LOCK_FS( mte1 );
ret = mte1->fs->rename( mte1, dir1, name1, dir2, name2 );
UNLOCK_FS( mte1 );
FILEIO_RETURN(ret);
}
//==========================================================================
// Create a link from an existing file (path1) to a new one (path2)
__externC int link( const char *path1, const char *path2 )
{
FILEIO_ENTRY();
int ret = 0;
cyg_mtab_entry *mte1 = cyg_cdir_mtab_entry;
cyg_mtab_entry *mte2 = cyg_cdir_mtab_entry;
cyg_dir dir1 = cyg_cdir_dir;
cyg_dir dir2 = cyg_cdir_dir;
const char *name1 = path1;
const char *name2 = path2;
ret = cyg_mtab_lookup( &dir1, &name1, &mte1 );
if( 0 != ret )
FILEIO_RETURN(ENOENT);
ret = cyg_mtab_lookup( &dir2, &name2, &mte2 );
if( 0 != ret )
FILEIO_RETURN(ENOENT);
// Cannot hard-link between different filesystems
if( mte1 != mte2 )
FILEIO_RETURN(EXDEV);
LOCK_FS( mte1 );
ret = mte1->fs->link( mte1, dir1, name1, dir2, name2, CYG_FSLINK_HARD );
UNLOCK_FS( mte1 );
FILEIO_RETURN(ret);
}
//==========================================================================
// Change current directory
__externC int chdir( const char *path )
{
FILEIO_ENTRY();
int ret = 0;
cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
cyg_dir dir = cyg_cdir_dir;
cyg_dir newdir;
const char *name = path;
ret = cyg_mtab_lookup( &dir, &name, &mte );
if( 0 != ret )
FILEIO_RETURN(ENOENT);
LOCK_FS(mte);
ret = mte->fs->chdir( mte, dir, name, &newdir );
UNLOCK_FS(mte);
if( 0 != ret )
FILEIO_RETURN(ret);
#ifdef CYGPKG_IO_FILEIO_TRACK_CWD
update_cwd( mte, dir, name );
#endif
if( cyg_cdir_mtab_entry != NULL && cyg_cdir_dir != CYG_DIR_NULL )
{
// Now detach from current cyg_cdir. We call the current directory's
// chdir routine with a NULL dir_out pointer.
LOCK_FS(cyg_cdir_mtab_entry);
ret = cyg_cdir_mtab_entry->fs->chdir( cyg_cdir_mtab_entry, cyg_cdir_dir, NULL, NULL );
UNLOCK_FS(cyg_cdir_mtab_entry);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -