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>
2014-07-23 17:15:35 +04:00
# include <sys/syscall.h>
2005-04-17 02:20:36 +04:00
# include "hostfs.h"
2007-10-16 12:27:13 +04:00
# include <utime.h>
2005-04-17 02:20:36 +04:00
2010-06-07 04:08:56 +04:00
static void stat64_to_hostfs ( const struct stat64 * buf , struct hostfs_stat * p )
{
p - > ino = buf - > st_ino ;
p - > mode = buf - > st_mode ;
p - > nlink = buf - > st_nlink ;
p - > uid = buf - > st_uid ;
p - > gid = buf - > st_gid ;
p - > size = buf - > st_size ;
p - > atime . tv_sec = buf - > st_atime ;
p - > atime . tv_nsec = 0 ;
p - > ctime . tv_sec = buf - > st_ctime ;
p - > ctime . tv_nsec = 0 ;
p - > mtime . tv_sec = buf - > st_mtime ;
p - > mtime . tv_nsec = 0 ;
p - > blksize = buf - > st_blksize ;
p - > blocks = buf - > st_blocks ;
p - > maj = os_major ( buf - > st_rdev ) ;
p - > min = os_minor ( buf - > st_rdev ) ;
}
int stat_file ( const char * path , struct hostfs_stat * p , 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
}
2010-06-07 04:08:56 +04:00
stat64_to_hostfs ( & buf , p ) ;
2007-05-08 11:23:18 +04:00
return 0 ;
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 ;
2010-10-27 01:22:20 +04:00
2007-05-08 11:23:18 +04:00
return dir ;
2005-04-17 02:20:36 +04:00
}
2015-03-24 17:47:38 +03:00
void seek_dir ( void * stream , unsigned long long pos )
{
DIR * dir = stream ;
seekdir ( dir , pos ) ;
}
char * read_dir ( void * stream , unsigned long long * pos_out ,
2012-01-27 22:14:58 +04:00
unsigned long long * ino_out , int * len_out ,
unsigned int * type_out )
2005-04-17 02:20:36 +04:00
{
DIR * dir = stream ;
struct dirent * ent ;
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 ;
2012-01-27 22:14:58 +04:00
* type_out = ent - > d_type ;
2015-03-24 17:47:38 +03:00
* pos_out = ent - > d_off ;
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 ;
}
2010-06-07 07:49:18 +04:00
int replace_file ( int oldfd , int fd )
{
return dup2 ( oldfd , fd ) ;
}
2005-04-17 02:20:36 +04:00
void close_file ( void * stream )
{
close ( * ( ( int * ) stream ) ) ;
}
void close_dir ( void * stream )
{
closedir ( stream ) ;
}
2015-03-05 01:44:54 +03:00
int file_create ( char * name , int mode )
2005-04-17 02:20:36 +04:00
{
2015-03-05 01:44:54 +03:00
int fd ;
2005-04-17 02:20:36 +04:00
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
{
2010-06-07 04:08:56 +04:00
struct hostfs_stat st ;
2007-05-08 11:23:16 +04:00
struct timeval times [ 2 ] ;
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 )
2010-10-27 01:22:20 +04:00
return - errno ;
2007-05-08 11:23:16 +04:00
} 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 ) {
2010-06-07 04:08:56 +04:00
err = stat_file ( file , & st , fd ) ;
2007-05-08 11:23:16 +04:00
if ( err ! = 0 )
return err ;
2010-06-07 04:08:56 +04:00
times [ 0 ] . tv_sec = st . atime . tv_sec ;
times [ 0 ] . tv_usec = st . atime . tv_nsec / 1000 ;
times [ 1 ] . tv_sec = st . mtime . tv_sec ;
times [ 1 ] . tv_usec = st . mtime . 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 ) ) {
2010-06-07 04:08:56 +04:00
err = stat_file ( file , & st , fd ) ;
attrs - > ia_atime = st . atime ;
attrs - > ia_mtime = st . mtime ;
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
}
2018-03-11 13:34:48 +03:00
int hostfs_do_rmdir ( const char * file )
2005-04-17 02:20:36 +04:00
{
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 ;
2009-04-21 09:27:08 +04:00
err = mknod ( file , mode , os_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
}
2014-07-23 17:15:35 +04:00
int rename2_file ( char * from , char * to , unsigned int flags )
{
int err ;
# ifndef SYS_renameat2
# ifdef __x86_64__
# define SYS_renameat2 316
# endif
# ifdef __i386__
# define SYS_renameat2 353
# endif
# endif
# ifdef SYS_renameat2
err = syscall ( SYS_renameat2 , AT_FDCWD , from , AT_FDCWD , to , flags ) ;
if ( err < 0 ) {
if ( errno ! = ENOSYS )
return - errno ;
else
return - EINVAL ;
}
return 0 ;
# else
return - EINVAL ;
# endif
}
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 ,
2010-10-27 01:21:18 +04:00
void * fsid_out , int fsid_size , long * namelen_out )
2005-04-17 02:20:36 +04:00
{
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 ;
2010-10-27 01:21:18 +04:00
2007-05-08 11:23:18 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}