2005-04-17 02:20:36 +04:00
/*
2007-05-08 11:23:18 +04:00
* Copyright ( C ) 2000 - 2007 Jeff Dike ( jdike @ { addtoit , linux . intel } . com )
2005-04-17 02:20:36 +04:00
* Licensed under the GPL
*/
# include <stdio.h>
2007-10-16 12:27:13 +04:00
# include <stddef.h>
# include <unistd.h>
2005-04-17 02:20:36 +04:00
# include <dirent.h>
# include <errno.h>
2007-10-16 12:27:13 +04:00
# include <fcntl.h>
2005-04-17 02:20:36 +04:00
# include <string.h>
# include <sys/stat.h>
# include <sys/time.h>
2007-10-16 12:27:13 +04:00
# include <sys/types.h>
2005-04-17 02:20:36 +04:00
# include <sys/vfs.h>
# include "hostfs.h"
2007-10-16 12:27:13 +04:00
# include "os.h"
2005-04-17 02:20:36 +04:00
# include "user.h"
2007-10-16 12:27:13 +04:00
# include <utime.h>
2005-04-17 02:20:36 +04:00
int stat_file ( const char * path , unsigned long long * inode_out , int * mode_out ,
int * nlink_out , int * uid_out , int * gid_out ,
unsigned long long * size_out , struct timespec * atime_out ,
struct timespec * mtime_out , struct timespec * ctime_out ,
2007-05-08 11:23:16 +04:00
int * blksize_out , unsigned long long * blocks_out , int fd )
2005-04-17 02:20:36 +04:00
{
struct stat64 buf ;
2007-10-16 12:27:13 +04:00
if ( fd > = 0 ) {
2007-05-08 11:23:16 +04:00
if ( fstat64 ( fd , & buf ) < 0 )
2007-05-08 11:23:18 +04:00
return - errno ;
2007-10-16 12:27:13 +04:00
} else if ( lstat64 ( path , & buf ) < 0 ) {
2007-05-08 11:23:18 +04:00
return - errno ;
2007-05-08 11:23:16 +04:00
}
2005-04-17 02:20:36 +04:00
2007-10-16 12:27:13 +04:00
if ( inode_out ! = NULL )
* inode_out = buf . st_ino ;
if ( mode_out ! = NULL )
* mode_out = buf . st_mode ;
if ( nlink_out ! = NULL )
* nlink_out = buf . st_nlink ;
if ( uid_out ! = NULL )
* uid_out = buf . st_uid ;
if ( gid_out ! = NULL )
* gid_out = buf . st_gid ;
if ( size_out ! = NULL )
* size_out = buf . st_size ;
if ( atime_out ! = NULL ) {
2005-04-17 02:20:36 +04:00
atime_out - > tv_sec = buf . st_atime ;
atime_out - > tv_nsec = 0 ;
}
2007-10-16 12:27:13 +04:00
if ( mtime_out ! = NULL ) {
2005-04-17 02:20:36 +04:00
mtime_out - > tv_sec = buf . st_mtime ;
mtime_out - > tv_nsec = 0 ;
}
2007-10-16 12:27:13 +04:00
if ( ctime_out ! = NULL ) {
2005-04-17 02:20:36 +04:00
ctime_out - > tv_sec = buf . st_ctime ;
ctime_out - > tv_nsec = 0 ;
}
2007-10-16 12:27:13 +04:00
if ( blksize_out ! = NULL )
* blksize_out = buf . st_blksize ;
if ( blocks_out ! = NULL )
* blocks_out = buf . st_blocks ;
2007-05-08 11:23:18 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
int file_type ( const char * path , int * maj , int * min )
{
struct stat64 buf ;
2007-10-16 12:27:13 +04:00
if ( lstat64 ( path , & buf ) < 0 )
2007-05-08 11:23:18 +04:00
return - errno ;
2007-10-16 12:27:13 +04:00
/*
* We cannot pass rdev as is because glibc and the kernel disagree
* about its definition .
*/
if ( maj ! = NULL )
2005-04-17 02:20:36 +04:00
* maj = major ( buf . st_rdev ) ;
2007-10-16 12:27:13 +04:00
if ( min ! = NULL )
2005-04-17 02:20:36 +04:00
* min = minor ( buf . st_rdev ) ;
2007-10-16 12:27:13 +04:00
if ( S_ISDIR ( buf . st_mode ) )
return OS_TYPE_DIR ;
else if ( S_ISLNK ( buf . st_mode ) )
return OS_TYPE_SYMLINK ;
else if ( S_ISCHR ( buf . st_mode ) )
return OS_TYPE_CHARDEV ;
else if ( S_ISBLK ( buf . st_mode ) )
return OS_TYPE_BLOCKDEV ;
else if ( S_ISFIFO ( buf . st_mode ) )
return OS_TYPE_FIFO ;
else if ( S_ISSOCK ( buf . st_mode ) )
return OS_TYPE_SOCK ;
2007-05-08 11:23:18 +04:00
else return OS_TYPE_FILE ;
2005-04-17 02:20:36 +04:00
}
int access_file ( char * path , int r , int w , int x )
{
int mode = 0 ;
2007-10-16 12:27:13 +04:00
if ( r )
mode = R_OK ;
if ( w )
mode | = W_OK ;
if ( x )
mode | = X_OK ;
if ( access ( path , mode ) ! = 0 )
2007-05-08 11:23:18 +04:00
return - errno ;
else return 0 ;
2005-04-17 02:20:36 +04:00
}
int open_file ( char * path , int r , int w , int append )
{
int mode = 0 , fd ;
2007-10-16 12:27:13 +04:00
if ( r & & ! w )
2005-04-17 02:20:36 +04:00
mode = O_RDONLY ;
2007-10-16 12:27:13 +04:00
else if ( ! r & & w )
2005-04-17 02:20:36 +04:00
mode = O_WRONLY ;
2007-10-16 12:27:13 +04:00
else if ( r & & w )
2005-04-17 02:20:36 +04:00
mode = O_RDWR ;
else panic ( " Impossible mode in open_file " ) ;
2007-10-16 12:27:13 +04:00
if ( append )
2005-04-17 02:20:36 +04:00
mode | = O_APPEND ;
fd = open64 ( path , mode ) ;
2007-10-16 12:27:13 +04:00
if ( fd < 0 )
2007-05-08 11:23:18 +04:00
return - errno ;
else return fd ;
2005-04-17 02:20:36 +04:00
}
void * open_dir ( char * path , int * err_out )
{
DIR * dir ;
dir = opendir ( path ) ;
* err_out = errno ;
2007-10-16 12:27:13 +04:00
if ( dir = = NULL )
2007-05-08 11:23:18 +04:00
return NULL ;
return dir ;
2005-04-17 02:20:36 +04:00
}
char * read_dir ( void * stream , unsigned long long * pos ,
unsigned long long * ino_out , int * len_out )
{
DIR * dir = stream ;
struct dirent * ent ;
seekdir ( dir , * pos ) ;
ent = readdir ( dir ) ;
2007-10-16 12:27:13 +04:00
if ( ent = = NULL )
2007-05-08 11:23:18 +04:00
return NULL ;
2005-04-17 02:20:36 +04:00
* len_out = strlen ( ent - > d_name ) ;
* ino_out = ent - > d_ino ;
* pos = telldir ( dir ) ;
2007-05-08 11:23:18 +04:00
return ent - > d_name ;
2005-04-17 02:20:36 +04:00
}
int read_file ( int fd , unsigned long long * offset , char * buf , int len )
{
int n ;
n = pread64 ( fd , buf , len , * offset ) ;
2007-10-16 12:27:13 +04:00
if ( n < 0 )
2007-05-08 11:23:18 +04:00
return - errno ;
2005-04-17 02:20:36 +04:00
* offset + = n ;
2007-05-08 11:23:18 +04:00
return n ;
2005-04-17 02:20:36 +04:00
}
int write_file ( int fd , unsigned long long * offset , const char * buf , int len )
{
int n ;
n = pwrite64 ( fd , buf , len , * offset ) ;
2007-10-16 12:27:13 +04:00
if ( n < 0 )
2007-05-08 11:23:18 +04:00
return - errno ;
2005-04-17 02:20:36 +04:00
* offset + = n ;
2007-05-08 11:23:18 +04:00
return n ;
2005-04-17 02:20:36 +04:00
}
int lseek_file ( int fd , long long offset , int whence )
{
int ret ;
ret = lseek64 ( fd , offset , whence ) ;
2007-10-16 12:27:13 +04:00
if ( ret < 0 )
2007-05-08 11:23:18 +04:00
return - errno ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
2005-07-29 08:16:15 +04:00
int fsync_file ( int fd , int datasync )
{
int ret ;
if ( datasync )
ret = fdatasync ( fd ) ;
else
ret = fsync ( fd ) ;
if ( ret < 0 )
return - errno ;
return 0 ;
}
2005-04-17 02:20:36 +04:00
void close_file ( void * stream )
{
close ( * ( ( int * ) stream ) ) ;
}
void close_dir ( void * stream )
{
closedir ( stream ) ;
}
int file_create ( char * name , int ur , int uw , int ux , int gr ,
int gw , int gx , int or , int ow , int ox )
{
int mode , fd ;
mode = 0 ;
mode | = ur ? S_IRUSR : 0 ;
mode | = uw ? S_IWUSR : 0 ;
mode | = ux ? S_IXUSR : 0 ;
mode | = gr ? S_IRGRP : 0 ;
mode | = gw ? S_IWGRP : 0 ;
mode | = gx ? S_IXGRP : 0 ;
mode | = or ? S_IROTH : 0 ;
mode | = ow ? S_IWOTH : 0 ;
mode | = ox ? S_IXOTH : 0 ;
fd = open64 ( name , O_CREAT | O_RDWR , mode ) ;
2007-10-16 12:27:13 +04:00
if ( fd < 0 )
2007-05-08 11:23:18 +04:00
return - errno ;
return fd ;
2005-04-17 02:20:36 +04:00
}
2007-05-08 11:23:16 +04:00
int set_attr ( const char * file , struct hostfs_iattr * attrs , int fd )
2005-04-17 02:20:36 +04:00
{
2007-05-08 11:23:16 +04:00
struct timeval times [ 2 ] ;
struct timespec atime_ts , mtime_ts ;
2005-04-17 02:20:36 +04:00
int err , ma ;
2007-05-08 11:23:16 +04:00
if ( attrs - > ia_valid & HOSTFS_ATTR_MODE ) {
if ( fd > = 0 ) {
if ( fchmod ( fd , attrs - > ia_mode ) ! = 0 )
return ( - errno ) ;
} else if ( chmod ( file , attrs - > ia_mode ) ! = 0 ) {
2007-05-08 11:23:18 +04:00
return - errno ;
2007-05-08 11:23:16 +04:00
}
2005-04-17 02:20:36 +04:00
}
2007-05-08 11:23:16 +04:00
if ( attrs - > ia_valid & HOSTFS_ATTR_UID ) {
if ( fd > = 0 ) {
if ( fchown ( fd , attrs - > ia_uid , - 1 ) )
2007-05-08 11:23:18 +04:00
return - errno ;
2007-10-16 12:27:13 +04:00
} else if ( chown ( file , attrs - > ia_uid , - 1 ) ) {
2007-05-08 11:23:18 +04:00
return - errno ;
2007-05-08 11:23:16 +04:00
}
2005-04-17 02:20:36 +04:00
}
2007-05-08 11:23:16 +04:00
if ( attrs - > ia_valid & HOSTFS_ATTR_GID ) {
if ( fd > = 0 ) {
if ( fchown ( fd , - 1 , attrs - > ia_gid ) )
2007-05-08 11:23:18 +04:00
return - errno ;
2007-05-08 11:23:16 +04:00
} else if ( chown ( file , - 1 , attrs - > ia_gid ) ) {
2007-05-08 11:23:18 +04:00
return - errno ;
2007-05-08 11:23:16 +04:00
}
2005-04-17 02:20:36 +04:00
}
2007-05-08 11:23:16 +04:00
if ( attrs - > ia_valid & HOSTFS_ATTR_SIZE ) {
if ( fd > = 0 ) {
if ( ftruncate ( fd , attrs - > ia_size ) )
2007-05-08 11:23:18 +04:00
return - errno ;
2007-05-08 11:23:16 +04:00
} else if ( truncate ( file , attrs - > ia_size ) ) {
2007-05-08 11:23:18 +04:00
return - errno ;
2007-05-08 11:23:16 +04:00
}
2005-04-17 02:20:36 +04:00
}
2007-05-08 11:23:16 +04:00
2007-10-16 12:27:13 +04:00
/*
* Update accessed and / or modified time , in two parts : first set
2007-05-08 11:23:16 +04:00
* times according to the changes to perform , and then call futimes ( )
2007-10-16 12:27:13 +04:00
* or utimes ( ) to apply them .
*/
2007-05-08 11:23:16 +04:00
ma = ( HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET ) ;
if ( attrs - > ia_valid & ma ) {
err = stat_file ( file , NULL , NULL , NULL , NULL , NULL , NULL ,
& atime_ts , & mtime_ts , NULL , NULL , NULL , fd ) ;
if ( err ! = 0 )
return err ;
times [ 0 ] . tv_sec = atime_ts . tv_sec ;
2008-02-05 09:31:15 +03:00
times [ 0 ] . tv_usec = atime_ts . tv_nsec / 1000 ;
2007-05-08 11:23:16 +04:00
times [ 1 ] . tv_sec = mtime_ts . tv_sec ;
2008-02-05 09:31:15 +03:00
times [ 1 ] . tv_usec = mtime_ts . tv_nsec / 1000 ;
2007-05-08 11:23:16 +04:00
if ( attrs - > ia_valid & HOSTFS_ATTR_ATIME_SET ) {
times [ 0 ] . tv_sec = attrs - > ia_atime . tv_sec ;
2008-02-05 09:31:15 +03:00
times [ 0 ] . tv_usec = attrs - > ia_atime . tv_nsec / 1000 ;
2005-04-17 02:20:36 +04:00
}
2007-05-08 11:23:16 +04:00
if ( attrs - > ia_valid & HOSTFS_ATTR_MTIME_SET ) {
times [ 1 ] . tv_sec = attrs - > ia_mtime . tv_sec ;
2008-02-05 09:31:15 +03:00
times [ 1 ] . tv_usec = attrs - > ia_mtime . tv_nsec / 1000 ;
2007-05-08 11:23:16 +04:00
}
if ( fd > = 0 ) {
if ( futimes ( fd , times ) ! = 0 )
2007-05-08 11:23:18 +04:00
return - errno ;
2007-05-08 11:23:16 +04:00
} else if ( utimes ( file , times ) ! = 0 ) {
2007-05-08 11:23:18 +04:00
return - errno ;
2005-04-17 02:20:36 +04:00
}
}
2007-05-08 11:23:16 +04:00
2007-10-16 12:27:13 +04:00
/* Note: ctime is not handled */
2007-10-16 12:27:13 +04:00
if ( attrs - > ia_valid & ( HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME ) ) {
2005-04-17 02:20:36 +04:00
err = stat_file ( file , NULL , NULL , NULL , NULL , NULL , NULL ,
& attrs - > ia_atime , & attrs - > ia_mtime , NULL ,
2007-05-08 11:23:16 +04:00
NULL , NULL , fd ) ;
2007-10-16 12:27:13 +04:00
if ( err ! = 0 )
2007-05-08 11:23:18 +04:00
return err ;
2005-04-17 02:20:36 +04:00
}
2007-05-08 11:23:18 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
int make_symlink ( const char * from , const char * to )
{
int err ;
err = symlink ( to , from ) ;
2007-10-16 12:27:13 +04:00
if ( err )
2007-05-08 11:23:18 +04:00
return - errno ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
int unlink_file ( const char * file )
{
int err ;
err = unlink ( file ) ;
2007-10-16 12:27:13 +04:00
if ( err )
2007-05-08 11:23:18 +04:00
return - errno ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
int do_mkdir ( const char * file , int mode )
{
int err ;
err = mkdir ( file , mode ) ;
2007-10-16 12:27:13 +04:00
if ( err )
2007-05-08 11:23:18 +04:00
return - errno ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
int do_rmdir ( const char * file )
{
int err ;
err = rmdir ( file ) ;
2007-10-16 12:27:13 +04:00
if ( err )
2007-05-08 11:23:18 +04:00
return - errno ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
2007-01-30 00:19:44 +03:00
int do_mknod ( const char * file , int mode , unsigned int major , unsigned int minor )
2005-04-17 02:20:36 +04:00
{
int err ;
2007-01-30 00:19:44 +03:00
err = mknod ( file , mode , makedev ( major , minor ) ) ;
2007-10-16 12:27:13 +04:00
if ( err )
2007-05-08 11:23:18 +04:00
return - errno ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
int link_file ( const char * to , const char * from )
{
int err ;
err = link ( to , from ) ;
2007-10-16 12:27:13 +04:00
if ( err )
2007-05-08 11:23:18 +04:00
return - errno ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
2008-11-20 02:36:46 +03:00
int hostfs_do_readlink ( char * file , char * buf , int size )
2005-04-17 02:20:36 +04:00
{
int n ;
n = readlink ( file , buf , size ) ;
2007-10-16 12:27:13 +04:00
if ( n < 0 )
2007-05-08 11:23:18 +04:00
return - errno ;
2007-10-16 12:27:13 +04:00
if ( n < size )
2005-04-17 02:20:36 +04:00
buf [ n ] = ' \0 ' ;
2007-05-08 11:23:18 +04:00
return n ;
2005-04-17 02:20:36 +04:00
}
int rename_file ( char * from , char * to )
{
int err ;
err = rename ( from , to ) ;
2007-10-16 12:27:13 +04:00
if ( err < 0 )
2007-05-08 11:23:18 +04:00
return - errno ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
int do_statfs ( char * root , long * bsize_out , long long * blocks_out ,
long long * bfree_out , long long * bavail_out ,
long long * files_out , long long * ffree_out ,
void * fsid_out , int fsid_size , long * namelen_out ,
long * spare_out )
{
struct statfs64 buf ;
int err ;
err = statfs64 ( root , & buf ) ;
2007-10-16 12:27:13 +04:00
if ( err < 0 )
2007-05-08 11:23:18 +04:00
return - errno ;
2005-04-17 02:20:36 +04:00
* bsize_out = buf . f_bsize ;
* blocks_out = buf . f_blocks ;
* bfree_out = buf . f_bfree ;
* bavail_out = buf . f_bavail ;
* files_out = buf . f_files ;
* ffree_out = buf . f_ffree ;
memcpy ( fsid_out , & buf . f_fsid ,
sizeof ( buf . f_fsid ) > fsid_size ? fsid_size :
sizeof ( buf . f_fsid ) ) ;
* namelen_out = buf . f_namelen ;
spare_out [ 0 ] = buf . f_spare [ 0 ] ;
spare_out [ 1 ] = buf . f_spare [ 1 ] ;
spare_out [ 2 ] = buf . f_spare [ 2 ] ;
spare_out [ 3 ] = buf . f_spare [ 3 ] ;
spare_out [ 4 ] = buf . f_spare [ 4 ] ;
2007-05-08 11:23:18 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}