📄 file.cxx
字号:
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);
// We really shouldn't get an error here.
if( 0 != ret )
FILEIO_RETURN(ret);
}
cyg_cdir_mtab_entry = mte;
cyg_cdir_dir = newdir;
FILEIO_RETURN(ENOERR);
}
//==========================================================================
// Get file statistics
__externC int stat( const char *path, struct stat *buf )
{
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->stat( mte, dir, name, buf );
UNLOCK_FS( mte );
FILEIO_RETURN(ret);
}
//==========================================================================
// Get file configurable pathname variables
__externC long pathconf( const char *path, int vname )
{
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);
struct cyg_pathconf_info info;
info.name = vname;
info.value = 0;
LOCK_FS( mte );
ret = mte->fs->getinfo( mte, dir, name,
FS_INFO_CONF, (char *)&info, sizeof(info) );
UNLOCK_FS( mte );
if( 0 != ret )
FILEIO_RETURN(ret);
FILEIO_RETURN_VALUE(info.value);
}
//==========================================================================
// Access() function.
// This simply piggybacks onto stat().
extern int access(const char *path, int amode)
{
FILEIO_ENTRY();
int ret;
struct stat buf;
ret = stat( path, &buf );
// Translate not found into EACCES if the F_OK bit is
// set.
if( (amode & F_OK) && (ret < 0) && (errno == ENOENT) )
FILEIO_RETURN(EACCES);
// All other errors go straight back to the user.
if( ret < 0 )
FILEIO_RETURN_VALUE(ret);
// At present we do not have any access modes, so there is nothing
// to test. Just return success for all access modes.
FILEIO_RETURN(ENOERR);
}
//==========================================================================
// getcwd()
__externC char *getcwd( char *buf, size_t size )
{
FILEIO_ENTRY();
int err = ENOERR;
cyg_mtab_entry *mte = cyg_cdir_mtab_entry;
cyg_dir dir = cyg_cdir_dir;
cyg_getcwd_info info;
if( size == 0 )
{
errno = EINVAL;
FILEIO_RETURN_VALUE(NULL);
}
info.buf = buf;
info.size = size;
LOCK_FS( mte );
err = mte->fs->getinfo( mte, dir, "",
FS_INFO_GETCWD, (char *)&info, sizeof(info) );
UNLOCK_FS( mte );
if( err == ENOERR )
FILEIO_RETURN_VALUE(buf);
// Attempting to use filesystem support for getcwd() has
// failed.
#ifdef CYGPKG_IO_FILEIO_TRACK_CWD
// If this option is set, the current directory path has been
// tracked in chdir(). Just report that value here.
if( size < cwd_size+1 )
{
errno = ERANGE;
FILEIO_RETURN_VALUE(NULL);
}
char *p = my_strcpy( buf, cwd );
*p = '\0';
#else
// As a fallback we try to use ".." entries in the directory tree
// to climb back up to the root. Because we cannot assume that
// any filesystem can handle more than one directory pointer we
// have to do the climbing textually, by manufacturing a path name
// consisting of ".."s. At each level we then scan the parent
// directory looking for the entry for the lower level directory
// by matching st_ino values. This is not guaranteed to work at
// all since there is no requirement on filesystems to support "."
// and "..", or for them to report distinct inode values in
// stat().
static char ddbuf[PATH_MAX];
char *p = buf+size-1;
int ddbufpos;
// Claim lock to serialize use of ddbuf.
FILEIO_MUTEX_LOCK(getcwd_lock);
// Initialize ddbuf with ".".
ddbuf[0] = '.';
ddbuf[1] = '\0';
ddbufpos = 1;
// Start result buffer with a zero terminator. We accumulate the
// path name in the top end of the result buffer.
*p = '\0';
for(;;)
{
struct stat sdbuf;
struct stat sddbuf;
// Get status for "." and "..". If the filesystem does not
// support these, then this whole function will fail here.
err = stat( ddbuf, &sdbuf );
if( err < 0 ) break;
ddbuf[ddbufpos++] = '/';
ddbuf[ddbufpos++] = '.';
ddbuf[ddbufpos++] = '.';
ddbuf[ddbufpos] = '\0';
err = stat( ddbuf, &sddbuf );
if( err < 0 ) break;
// See whether we are at the root. This will be true when
// the inode numbers of "." and ".." are the same.
if( sdbuf.st_ino == sddbuf.st_ino )
break;
// We now need to find an entry in the ".." directory that
// matches the inode number of ".".
struct dirent de;
DIR *d = opendir( ddbuf );
if( d == NULL )
{
err = -1;
break;
}
for(;;)
{
struct dirent *res;
struct stat objstat;
int i;
err = readdir_r( d, &de, &res );
if( err < 0 || res == NULL ) break;
// Skip "." and ".." entries.
if( pathcmp( de.d_name, "." ) || pathcmp( de.d_name, ".." ) )
continue;
// Tack the name of the directory entry on to the ddbuf
// and stat the object.
ddbuf[ddbufpos] = '/';
for( i = 0; de.d_name[i] != '\0'; i++ )
ddbuf[ddbufpos+i+1] = de.d_name[i];
ddbuf[ddbufpos+i+1] = '\0';
// Take a look at it
err = stat( ddbuf, &objstat );
if( err < 0 ) break;
// Cast out directories
if( !S_ISDIR(objstat.st_mode) )
continue;
// We have a directory. Compare its inode with that of "."
// and if they are the same, we have found our entry.
if( sdbuf.st_ino == objstat.st_ino )
break;
}
ddbuf[ddbufpos] = '\0'; // reterminate ddbuf
closedir( d );
// Halt on any errors.
if( err < 0 )
break;
// Here de contains the name of the directory entry in ".."
// that has the same inode as ".". Add the name to the path we
// are accumulating in the buffer.
char *q = de.d_name;
while( *q != '\0' ) q++; // skip to end of name
do
{
*--p = *--q;
} while( q != de.d_name );
*--p = '/'; // add a separator
}
// We have finished using ddbuf now.
FILEIO_MUTEX_UNLOCK(getcwd_lock);
if( err < 0 )
FILEIO_RETURN_VALUE(NULL);
// We have the directory path in the top end of the buffer. Add
// the mount point name at the beginning and copy the rest of the
// name down.
char *bp = buf;
bp = my_strcpy( bp, mte->name );
// Sort out the separators between the mount name and the
// pathname. This is a bit messy since we have to deal with mount
// names of both "/" and "/foo" and pathnames that start with '/'
// or are empty.
if( *(bp-1) != '/' && *p != '\0' ) *bp++ = '/';
if( *p == '/' ) p++;
// Now copy the path over.
while( *p )
*bp++ = *p++;
*bp = '\0'; // Terminate the string
// All done!
#endif
FILEIO_RETURN_VALUE(buf);
}
//==========================================================================
// FS get info.
__externC int cyg_fs_getinfo( const char *path, int key, void *buf, int len )
{
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->getinfo( mte, dir, name, key, buf, len );
UNLOCK_FS( mte );
FILEIO_RETURN(ret);
}
//==========================================================================
// FS set info.
__externC int cyg_fs_setinfo( const char *path, int key, void *buf, int len )
{
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->setinfo( mte, dir, name, key, buf, len );
UNLOCK_FS( mte );
FILEIO_RETURN(ret);
}
// -------------------------------------------------------------------------
// EOF file.cxx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -