Add statfs and fstatfs syscall
This commit is contained in:
		
							parent
							
								
									f2968799ae
								
							
						
					
					
						commit
						789b57c6f7
					
				
							
								
								
									
										2
									
								
								deps/sefs
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								deps/sefs
									
									
									
									
										vendored
									
									
								
							@ -1 +1 @@
 | 
				
			|||||||
Subproject commit 633060491f1e2a5c61cd331520c83d588eb5926b
 | 
					Subproject commit 6df33e6e415be7b17d6d46babf74ef15c044fba9
 | 
				
			||||||
@ -95,6 +95,10 @@ pub trait File: Debug + Sync + Send + Any {
 | 
				
			|||||||
        return_op_unsupported_error!("fallocate")
 | 
					        return_op_unsupported_error!("fallocate")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn fs(&self) -> Result<Arc<dyn FileSystem>> {
 | 
				
			||||||
 | 
					        return_op_unsupported_error!("fs")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO: remove this function after all users of this code are removed
 | 
					    // TODO: remove this function after all users of this code are removed
 | 
				
			||||||
    fn poll(&self) -> Result<(crate::net::PollEventFlags)> {
 | 
					    fn poll(&self) -> Result<(crate::net::PollEventFlags)> {
 | 
				
			||||||
        return_op_unsupported_error!("poll")
 | 
					        return_op_unsupported_error!("poll")
 | 
				
			||||||
 | 
				
			|||||||
@ -3,9 +3,11 @@ use super::*;
 | 
				
			|||||||
pub use self::chdir::do_chdir;
 | 
					pub use self::chdir::do_chdir;
 | 
				
			||||||
pub use self::getcwd::do_getcwd;
 | 
					pub use self::getcwd::do_getcwd;
 | 
				
			||||||
pub use self::mount::do_mount_rootfs;
 | 
					pub use self::mount::do_mount_rootfs;
 | 
				
			||||||
 | 
					pub use self::statfs::{do_fstatfs, do_statfs, Statfs};
 | 
				
			||||||
pub use self::sync::do_sync;
 | 
					pub use self::sync::do_sync;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mod chdir;
 | 
					mod chdir;
 | 
				
			||||||
mod getcwd;
 | 
					mod getcwd;
 | 
				
			||||||
mod mount;
 | 
					mod mount;
 | 
				
			||||||
 | 
					mod statfs;
 | 
				
			||||||
mod sync;
 | 
					mod sync;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										80
									
								
								src/libos/src/fs/fs_ops/statfs.rs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										80
									
								
								src/libos/src/fs/fs_ops/statfs.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,80 @@
 | 
				
			|||||||
 | 
					use super::*;
 | 
				
			||||||
 | 
					use rcore_fs::vfs::FsInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn do_fstatfs(fd: FileDesc) -> Result<Statfs> {
 | 
				
			||||||
 | 
					    debug!("fstatfs: fd: {}", fd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let file_ref = current!().file(fd)?;
 | 
				
			||||||
 | 
					    let statfs = Statfs::from(file_ref.fs()?.info());
 | 
				
			||||||
 | 
					    trace!("fstatfs result: {:?}", statfs);
 | 
				
			||||||
 | 
					    Ok(statfs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn do_statfs(path: &str) -> Result<Statfs> {
 | 
				
			||||||
 | 
					    debug!("statfs: path: {:?}", path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let inode = {
 | 
				
			||||||
 | 
					        let current = current!();
 | 
				
			||||||
 | 
					        let fs = current.fs().read().unwrap();
 | 
				
			||||||
 | 
					        fs.lookup_inode(path)?
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    let statfs = Statfs::from(inode.fs().info());
 | 
				
			||||||
 | 
					    trace!("statfs result: {:?}", statfs);
 | 
				
			||||||
 | 
					    Ok(statfs)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					#[repr(C)]
 | 
				
			||||||
 | 
					pub struct Statfs {
 | 
				
			||||||
 | 
					    /// Type of filesystem
 | 
				
			||||||
 | 
					    f_type: usize,
 | 
				
			||||||
 | 
					    /// Optimal transfer block size
 | 
				
			||||||
 | 
					    f_bsize: usize,
 | 
				
			||||||
 | 
					    /// Total data blocks in filesystem
 | 
				
			||||||
 | 
					    f_blocks: usize,
 | 
				
			||||||
 | 
					    /// Free blocks in filesystem
 | 
				
			||||||
 | 
					    f_bfree: usize,
 | 
				
			||||||
 | 
					    /// Free blocks available to unprivileged user
 | 
				
			||||||
 | 
					    f_bavail: usize,
 | 
				
			||||||
 | 
					    /// Total inodes in filesystem
 | 
				
			||||||
 | 
					    f_files: usize,
 | 
				
			||||||
 | 
					    /// Free inodes in filesystem
 | 
				
			||||||
 | 
					    f_ffree: usize,
 | 
				
			||||||
 | 
					    /// Filesystem ID
 | 
				
			||||||
 | 
					    f_fsid: [i32; 2],
 | 
				
			||||||
 | 
					    /// Maximum length of filenames
 | 
				
			||||||
 | 
					    f_namelen: usize,
 | 
				
			||||||
 | 
					    /// Fragment size
 | 
				
			||||||
 | 
					    f_frsize: usize,
 | 
				
			||||||
 | 
					    /// Mount flags of filesystem
 | 
				
			||||||
 | 
					    f_flags: usize,
 | 
				
			||||||
 | 
					    /// Padding bytes reserved for future use
 | 
				
			||||||
 | 
					    f_spare: [usize; 4],
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl From<FsInfo> for Statfs {
 | 
				
			||||||
 | 
					    fn from(info: FsInfo) -> Self {
 | 
				
			||||||
 | 
					        Self {
 | 
				
			||||||
 | 
					            f_type: match info.magic {
 | 
				
			||||||
 | 
					                // The "/dev" and "/dev/shm" are tmpfs on Linux, so we transform the
 | 
				
			||||||
 | 
					                // magic number to TMPFS_MAGIC.
 | 
				
			||||||
 | 
					                rcore_fs_ramfs::RAMFS_MAGIC | rcore_fs_devfs::DEVFS_MAGIC => {
 | 
				
			||||||
 | 
					                    const TMPFS_MAGIC: usize = 0x0102_1994;
 | 
				
			||||||
 | 
					                    TMPFS_MAGIC
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                val => val,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            f_bsize: info.bsize,
 | 
				
			||||||
 | 
					            f_blocks: info.blocks,
 | 
				
			||||||
 | 
					            f_bfree: info.bfree,
 | 
				
			||||||
 | 
					            f_bavail: info.bavail,
 | 
				
			||||||
 | 
					            f_files: info.files,
 | 
				
			||||||
 | 
					            f_ffree: info.ffree,
 | 
				
			||||||
 | 
					            f_fsid: [0i32; 2],
 | 
				
			||||||
 | 
					            f_namelen: info.namemax,
 | 
				
			||||||
 | 
					            f_frsize: info.frsize,
 | 
				
			||||||
 | 
					            f_flags: 0,
 | 
				
			||||||
 | 
					            f_spare: [0usize; 4],
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -36,7 +36,8 @@ impl FileSystem for HostFS {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn info(&self) -> FsInfo {
 | 
					    fn info(&self) -> FsInfo {
 | 
				
			||||||
        unimplemented!()
 | 
					        warn!("HostFS: FsInfo is unimplemented");
 | 
				
			||||||
 | 
					        Default::default()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -221,6 +221,10 @@ impl File for INodeFile {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn fs(&self) -> Result<Arc<dyn FileSystem>> {
 | 
				
			||||||
 | 
					        Ok(self.inode.fs())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn as_any(&self) -> &dyn Any {
 | 
					    fn as_any(&self) -> &dyn Any {
 | 
				
			||||||
        self
 | 
					        self
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,7 @@ pub use self::file_ops::{
 | 
				
			|||||||
    IfConf, IoctlCmd, Stat, StatusFlags, StructuredIoctlArgType, StructuredIoctlNum,
 | 
					    IfConf, IoctlCmd, Stat, StatusFlags, StructuredIoctlArgType, StructuredIoctlNum,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
pub use self::file_table::{FileDesc, FileTable, FileTableEvent, FileTableNotifier};
 | 
					pub use self::file_table::{FileDesc, FileTable, FileTableEvent, FileTableNotifier};
 | 
				
			||||||
 | 
					pub use self::fs_ops::Statfs;
 | 
				
			||||||
pub use self::fs_view::FsView;
 | 
					pub use self::fs_view::FsView;
 | 
				
			||||||
pub use self::host_fd::HostFd;
 | 
					pub use self::host_fd::HostFd;
 | 
				
			||||||
pub use self::inode_file::{AsINodeFile, INodeExt, INodeFile};
 | 
					pub use self::inode_file::{AsINodeFile, INodeExt, INodeFile};
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,9 @@ mod pid_inode;
 | 
				
			|||||||
mod proc_inode;
 | 
					mod proc_inode;
 | 
				
			||||||
mod self_inode;
 | 
					mod self_inode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Same with the procfs on Linux
 | 
				
			||||||
 | 
					const PROC_SUPER_MAGIC: usize = 0x9fa0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Proc file system
 | 
					/// Proc file system
 | 
				
			||||||
pub struct ProcFS {
 | 
					pub struct ProcFS {
 | 
				
			||||||
    root: Arc<Dir<LockedProcRootINode>>,
 | 
					    root: Arc<Dir<LockedProcRootINode>>,
 | 
				
			||||||
@ -33,14 +36,15 @@ impl FileSystem for ProcFS {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    fn info(&self) -> vfs::FsInfo {
 | 
					    fn info(&self) -> vfs::FsInfo {
 | 
				
			||||||
        vfs::FsInfo {
 | 
					        vfs::FsInfo {
 | 
				
			||||||
            bsize: 0,
 | 
					            magic: PROC_SUPER_MAGIC,
 | 
				
			||||||
            frsize: 0,
 | 
					            bsize: 4096,
 | 
				
			||||||
 | 
					            frsize: 4096,
 | 
				
			||||||
            blocks: 0,
 | 
					            blocks: 0,
 | 
				
			||||||
            bfree: 0,
 | 
					            bfree: 0,
 | 
				
			||||||
            bavail: 0,
 | 
					            bavail: 0,
 | 
				
			||||||
            files: 0,
 | 
					            files: 0,
 | 
				
			||||||
            ffree: 0,
 | 
					            ffree: 0,
 | 
				
			||||||
            namemax: 0,
 | 
					            namemax: 255,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -553,3 +553,24 @@ pub fn do_fallocate(fd: FileDesc, mode: u32, offset: off_t, len: off_t) -> Resul
 | 
				
			|||||||
    file_ops::do_fallocate(fd, mode, offset as u64, len as u64)?;
 | 
					    file_ops::do_fallocate(fd, mode, offset as u64, len as u64)?;
 | 
				
			||||||
    Ok(0)
 | 
					    Ok(0)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn do_fstatfs(fd: FileDesc, statfs_buf: *mut Statfs) -> Result<isize> {
 | 
				
			||||||
 | 
					    from_user::check_mut_ptr(statfs_buf)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let statfs = fs_ops::do_fstatfs(fd)?;
 | 
				
			||||||
 | 
					    unsafe {
 | 
				
			||||||
 | 
					        statfs_buf.write(statfs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Ok(0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn do_statfs(path: *const i8, statfs_buf: *mut Statfs) -> Result<isize> {
 | 
				
			||||||
 | 
					    let path = from_user::clone_cstring_safely(path)?
 | 
				
			||||||
 | 
					        .to_string_lossy()
 | 
				
			||||||
 | 
					        .into_owned();
 | 
				
			||||||
 | 
					    let statfs = fs_ops::do_statfs(&path)?;
 | 
				
			||||||
 | 
					    unsafe {
 | 
				
			||||||
 | 
					        statfs_buf.write(statfs);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Ok(0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -24,12 +24,12 @@ use crate::exception::do_handle_exception;
 | 
				
			|||||||
use crate::fs::{
 | 
					use crate::fs::{
 | 
				
			||||||
    do_access, do_chdir, do_chmod, do_chown, do_close, do_dup, do_dup2, do_dup3, do_eventfd,
 | 
					    do_access, do_chdir, do_chmod, do_chown, do_close, do_dup, do_dup2, do_dup3, do_eventfd,
 | 
				
			||||||
    do_eventfd2, do_faccessat, do_fallocate, do_fchmod, do_fchmodat, do_fchown, do_fchownat,
 | 
					    do_eventfd2, do_faccessat, do_fallocate, do_fchmod, do_fchmodat, do_fchown, do_fchownat,
 | 
				
			||||||
    do_fcntl, do_fdatasync, do_fstat, do_fstatat, do_fsync, do_ftruncate, do_getcwd, do_getdents,
 | 
					    do_fcntl, do_fdatasync, do_fstat, do_fstatat, do_fstatfs, do_fsync, do_ftruncate, do_getcwd,
 | 
				
			||||||
    do_getdents64, do_ioctl, do_lchown, do_link, do_linkat, do_lseek, do_lstat, do_mkdir,
 | 
					    do_getdents, do_getdents64, do_ioctl, do_lchown, do_link, do_linkat, do_lseek, do_lstat,
 | 
				
			||||||
    do_mkdirat, do_mount_rootfs, do_open, do_openat, do_pipe, do_pipe2, do_pread, do_pwrite,
 | 
					    do_mkdir, do_mkdirat, do_mount_rootfs, do_open, do_openat, do_pipe, do_pipe2, do_pread,
 | 
				
			||||||
    do_read, do_readlink, do_readlinkat, do_readv, do_rename, do_renameat, do_rmdir, do_sendfile,
 | 
					    do_pwrite, do_read, do_readlink, do_readlinkat, do_readv, do_rename, do_renameat, do_rmdir,
 | 
				
			||||||
    do_stat, do_symlink, do_symlinkat, do_sync, do_truncate, do_unlink, do_unlinkat, do_write,
 | 
					    do_sendfile, do_stat, do_statfs, do_symlink, do_symlinkat, do_sync, do_truncate, do_unlink,
 | 
				
			||||||
    do_writev, iovec_t, File, FileDesc, FileRef, HostStdioFds, Stat,
 | 
					    do_unlinkat, do_write, do_writev, iovec_t, File, FileDesc, FileRef, HostStdioFds, Stat, Statfs,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use crate::interrupt::{do_handle_interrupt, sgx_interrupt_info_t};
 | 
					use crate::interrupt::{do_handle_interrupt, sgx_interrupt_info_t};
 | 
				
			||||||
use crate::misc::{resource_t, rlimit_t, sysinfo_t, utsname_t};
 | 
					use crate::misc::{resource_t, rlimit_t, sysinfo_t, utsname_t};
 | 
				
			||||||
@ -222,8 +222,8 @@ macro_rules! process_syscall_table_with_callback {
 | 
				
			|||||||
            (Uselib = 134) => handle_unsupported(),
 | 
					            (Uselib = 134) => handle_unsupported(),
 | 
				
			||||||
            (Personality = 135) => handle_unsupported(),
 | 
					            (Personality = 135) => handle_unsupported(),
 | 
				
			||||||
            (Ustat = 136) => handle_unsupported(),
 | 
					            (Ustat = 136) => handle_unsupported(),
 | 
				
			||||||
            (Statfs = 137) => handle_unsupported(),
 | 
					            (Statfs = 137) => do_statfs(path: *const i8, statfs_buf: *mut Statfs),
 | 
				
			||||||
            (Fstatfs = 138) => handle_unsupported(),
 | 
					            (Fstatfs = 138) => do_fstatfs(fd: FileDesc, statfs_buf: *mut Statfs),
 | 
				
			||||||
            (SysFs = 139) => handle_unsupported(),
 | 
					            (SysFs = 139) => handle_unsupported(),
 | 
				
			||||||
            (Getpriority = 140) => handle_unsupported(),
 | 
					            (Getpriority = 140) => handle_unsupported(),
 | 
				
			||||||
            (Setpriority = 141) => handle_unsupported(),
 | 
					            (Setpriority = 141) => handle_unsupported(),
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,8 @@ TEST_DEPS := client data_sink naughty_child
 | 
				
			|||||||
TESTS ?= env empty hello_world malloc mmap file fs_perms getpid spawn sched pipe time \
 | 
					TESTS ?= env empty hello_world malloc mmap file fs_perms getpid spawn sched pipe time \
 | 
				
			||||||
	truncate readdir mkdir open stat link symlink chmod chown tls pthread uname rlimit \
 | 
						truncate readdir mkdir open stat link symlink chmod chown tls pthread uname rlimit \
 | 
				
			||||||
	server server_epoll unix_socket cout hostfs cpuid rdtsc device sleep exit_group \
 | 
						server server_epoll unix_socket cout hostfs cpuid rdtsc device sleep exit_group \
 | 
				
			||||||
	ioctl fcntl eventfd emulate_syscall access signal sysinfo prctl rename procfs wait spawn_attribute
 | 
						ioctl fcntl eventfd emulate_syscall access signal sysinfo prctl rename procfs wait \
 | 
				
			||||||
 | 
						spawn_attribute statfs
 | 
				
			||||||
# Benchmarks: need to be compiled and run by bench-% target
 | 
					# Benchmarks: need to be compiled and run by bench-% target
 | 
				
			||||||
BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput
 | 
					BENCHES := spawn_and_exit_latency pipe_throughput unix_socket_throughput
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,5 @@
 | 
				
			|||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <sys/vfs.h>
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <limits.h>
 | 
					#include <limits.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
@ -142,6 +143,22 @@ static int test_read_from_proc_cpuinfo() {
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PROC_SUPER_MAGIC 0x9fa0
 | 
				
			||||||
 | 
					static int test_statfs() {
 | 
				
			||||||
 | 
					    const char *file_path = "/proc/cpuinfo";
 | 
				
			||||||
 | 
					    struct statfs statfs_buf;
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = statfs(file_path, &statfs_buf);
 | 
				
			||||||
 | 
					    if (ret < 0) {
 | 
				
			||||||
 | 
					        THROW_ERROR("failed to statfs the file");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (statfs_buf.f_type != PROC_SUPER_MAGIC) {
 | 
				
			||||||
 | 
					        THROW_ERROR("failed to check the f_type");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ============================================================================
 | 
					// ============================================================================
 | 
				
			||||||
// Test suite main
 | 
					// Test suite main
 | 
				
			||||||
// ============================================================================
 | 
					// ============================================================================
 | 
				
			||||||
@ -154,6 +171,7 @@ static test_case_t test_cases[] = {
 | 
				
			|||||||
    TEST_CASE(test_read_from_proc_self_cmdline),
 | 
					    TEST_CASE(test_read_from_proc_self_cmdline),
 | 
				
			||||||
    TEST_CASE(test_read_from_proc_meminfo),
 | 
					    TEST_CASE(test_read_from_proc_meminfo),
 | 
				
			||||||
    TEST_CASE(test_read_from_proc_cpuinfo),
 | 
					    TEST_CASE(test_read_from_proc_cpuinfo),
 | 
				
			||||||
 | 
					    TEST_CASE(test_statfs),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, const char *argv[]) {
 | 
					int main(int argc, const char *argv[]) {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										5
									
								
								test/statfs/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										5
									
								
								test/statfs/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					include ../test_common.mk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXTRA_C_FLAGS :=
 | 
				
			||||||
 | 
					EXTRA_LINK_FLAGS :=
 | 
				
			||||||
 | 
					BIN_ARGS :=
 | 
				
			||||||
							
								
								
									
										117
									
								
								test/statfs/main.c
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										117
									
								
								test/statfs/main.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,117 @@
 | 
				
			|||||||
 | 
					#include <sys/vfs.h>
 | 
				
			||||||
 | 
					#include <sys/stat.h>
 | 
				
			||||||
 | 
					#include <errno.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include "test_fs.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ============================================================================
 | 
				
			||||||
 | 
					// Helper function
 | 
				
			||||||
 | 
					// ============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int create_file(const char *file_path) {
 | 
				
			||||||
 | 
					    int fd;
 | 
				
			||||||
 | 
					    int flags = O_RDONLY | O_CREAT | O_TRUNC;
 | 
				
			||||||
 | 
					    int mode = 00666;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fd = open(file_path, flags, mode);
 | 
				
			||||||
 | 
					    if (fd < 0) {
 | 
				
			||||||
 | 
					        THROW_ERROR("failed to create a file");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    close(fd);
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int remove_file(const char *file_path) {
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = unlink(file_path);
 | 
				
			||||||
 | 
					    if (ret < 0) {
 | 
				
			||||||
 | 
					        THROW_ERROR("failed to unlink the created file");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ============================================================================
 | 
				
			||||||
 | 
					// Test cases for statfs
 | 
				
			||||||
 | 
					// ============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __test_statfs(const char *file_path, unsigned long expected_type) {
 | 
				
			||||||
 | 
					    struct statfs statfs_buf;
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = statfs(file_path, &statfs_buf);
 | 
				
			||||||
 | 
					    if (ret < 0) {
 | 
				
			||||||
 | 
					        THROW_ERROR("failed to statfs the file");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (statfs_buf.f_type != expected_type) {
 | 
				
			||||||
 | 
					        THROW_ERROR("failed to check the f_type");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __test_fstatfs(const char *file_path, unsigned long expected_type) {
 | 
				
			||||||
 | 
					    struct statfs statfs_buf;
 | 
				
			||||||
 | 
					    int fd, ret;
 | 
				
			||||||
 | 
					    int flags = O_RDONLY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fd = open(file_path, flags);
 | 
				
			||||||
 | 
					    if (fd < 0) {
 | 
				
			||||||
 | 
					        THROW_ERROR("failed to open file");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    ret = fstatfs(fd, &statfs_buf);
 | 
				
			||||||
 | 
					    if (ret < 0) {
 | 
				
			||||||
 | 
					        THROW_ERROR("failed to fstatfs the file");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (statfs_buf.f_type != expected_type) {
 | 
				
			||||||
 | 
					        THROW_ERROR("failed to check the f_type");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    close(fd);
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef int(*test_statfs_func_t)(const char *, unsigned long);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int test_statfs_framework(test_statfs_func_t fn, const char *file_path,
 | 
				
			||||||
 | 
					                                 unsigned long expected_type) {
 | 
				
			||||||
 | 
					    if (create_file(file_path) < 0) {
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (fn(file_path, expected_type) < 0) {
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (remove_file(file_path) < 0) {
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define UNIONFS_MAGIC  0x2f8dbe2f
 | 
				
			||||||
 | 
					#define TMPFS_MAGIC    0x01021994
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int test_statfs_on_root() {
 | 
				
			||||||
 | 
					    const char *file_path = "/root/test_fs_statfs.txt";
 | 
				
			||||||
 | 
					    unsigned long expected_type = UNIONFS_MAGIC;
 | 
				
			||||||
 | 
					    return test_statfs_framework(__test_statfs, file_path, expected_type) +
 | 
				
			||||||
 | 
					           test_statfs_framework(__test_fstatfs, file_path, expected_type);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int test_statfs_on_dev_shm() {
 | 
				
			||||||
 | 
					    const char *file_path = "/dev/shm/test_fs_statfs.txt";
 | 
				
			||||||
 | 
					    unsigned long expected_type = TMPFS_MAGIC;
 | 
				
			||||||
 | 
					    return test_statfs_framework(__test_statfs, file_path, expected_type) +
 | 
				
			||||||
 | 
					           test_statfs_framework(__test_fstatfs, file_path, expected_type);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ============================================================================
 | 
				
			||||||
 | 
					// Test suite main
 | 
				
			||||||
 | 
					// ============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static test_case_t test_cases[] = {
 | 
				
			||||||
 | 
					    TEST_CASE(test_statfs_on_root),
 | 
				
			||||||
 | 
					    TEST_CASE(test_statfs_on_dev_shm),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, const char *argv[]) {
 | 
				
			||||||
 | 
					    return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user