Add support for umask

This commit is contained in:
LI Qing 2021-08-06 11:58:03 +08:00 committed by Zongmin.Gu
parent 05d4c7d7db
commit 87c1c9a8b3
16 changed files with 195 additions and 38 deletions

2
deps/sefs vendored

@ -1 +1 @@
Subproject commit 41484829326a6bcbd92343f7c1bdcf4acf5a56f4 Subproject commit 8d999ffdf066cc0601c5a726ccfcca75437ced0b

@ -53,6 +53,17 @@ impl FileMode {
pub fn has_set_gid(&self) -> bool { pub fn has_set_gid(&self) -> bool {
self.contains(FileMode::S_ISGID) self.contains(FileMode::S_ISGID)
} }
/// Umask is FileMode & 0o777, only the file permission bits are used
pub fn to_umask(mut self) -> Self {
self.remove(Self::S_ISUID | Self::S_ISGID | Self::S_ISVTX);
self
}
/// Default umask is 0o022
pub fn default_umask() -> Self {
Self::S_IWGRP | Self::S_IWOTH
}
} }
pub fn do_fchmodat(fs_path: &FsPath, mode: FileMode) -> Result<()> { pub fn do_fchmodat(fs_path: &FsPath, mode: FileMode) -> Result<()> {

@ -1,12 +1,12 @@
use super::*; use super::*;
pub fn do_mkdirat(fs_path: &FsPath, mode: usize) -> Result<()> { pub fn do_mkdirat(fs_path: &FsPath, mode: FileMode) -> Result<()> {
debug!("mkdirat: fs_path: {:?}, mode: {:#o}", fs_path, mode); debug!("mkdirat: fs_path: {:?}, mode: {:#o}", fs_path, mode.bits());
let path = fs_path.to_abs_path()?; let path = fs_path.to_abs_path()?;
let (dir_path, file_name) = split_path(&path); let (dir_path, file_name) = split_path(&path);
let inode = {
let current = current!(); let current = current!();
let inode = {
let fs = current.fs().read().unwrap(); let fs = current.fs().read().unwrap();
fs.lookup_inode(dir_path)? fs.lookup_inode(dir_path)?
}; };
@ -16,6 +16,7 @@ pub fn do_mkdirat(fs_path: &FsPath, mode: usize) -> Result<()> {
if !inode.allow_write()? { if !inode.allow_write()? {
return_errno!(EPERM, "dir cannot be written"); return_errno!(EPERM, "dir cannot be written");
} }
inode.create(file_name, FileType::Dir, mode as u32)?; let masked_mode = mode & !current.process().umask();
inode.create(file_name, FileType::Dir, masked_mode.bits())?;
Ok(()) Ok(())
} }

@ -1,16 +1,19 @@
use super::*; use super::*;
pub fn do_openat(fs_path: &FsPath, flags: u32, mode: u32) -> Result<FileDesc> { pub fn do_openat(fs_path: &FsPath, flags: u32, mode: FileMode) -> Result<FileDesc> {
debug!( debug!(
"openat: fs_path: {:?}, flags: {:#o}, mode: {:#o}", "openat: fs_path: {:?}, flags: {:#o}, mode: {:#o}",
fs_path, flags, mode fs_path,
flags,
mode.bits()
); );
let path = fs_path.to_abs_path()?; let path = fs_path.to_abs_path()?;
let current = current!(); let current = current!();
let fs = current.fs().read().unwrap(); let fs = current.fs().read().unwrap();
let masked_mode = mode & !current.process().umask();
let file_ref: Arc<dyn File> = fs.open_file(&path, flags, mode)?; let file_ref: Arc<dyn File> = fs.open_file(&path, flags, masked_mode)?;
let fd = { let fd = {
let creation_flags = CreationFlags::from_bits_truncate(flags); let creation_flags = CreationFlags::from_bits_truncate(flags);

@ -44,7 +44,7 @@ impl FsView {
} }
/// Open a file on the process. But DO NOT add it to file table. /// Open a file on the process. But DO NOT add it to file table.
pub fn open_file(&self, path: &str, flags: u32, mode: u32) -> Result<Arc<dyn File>> { pub fn open_file(&self, path: &str, flags: u32, mode: FileMode) -> Result<Arc<dyn File>> {
let creation_flags = CreationFlags::from_bits_truncate(flags); let creation_flags = CreationFlags::from_bits_truncate(flags);
let inode = if creation_flags.no_follow_symlink() { let inode = if creation_flags.no_follow_symlink() {
match self.lookup_inode_no_follow(path) { match self.lookup_inode_no_follow(path) {
@ -73,7 +73,7 @@ impl FsView {
if !dir_inode.allow_write()? { if !dir_inode.allow_write()? {
return_errno!(EPERM, "file cannot be created"); return_errno!(EPERM, "file cannot be created");
} }
dir_inode.create(file_name, FileType::File, mode)? dir_inode.create(file_name, FileType::File, mode.bits())?
} }
Err(e) => return Err(e), Err(e) => return Err(e),
} }
@ -100,7 +100,7 @@ impl FsView {
if !dir_inode.allow_write()? { if !dir_inode.allow_write()? {
return_errno!(EPERM, "file cannot be created"); return_errno!(EPERM, "file cannot be created");
} }
dir_inode.create(file_name, FileType::File, mode)? dir_inode.create(file_name, FileType::File, mode.bits())?
} }
Err(e) => return Err(e), Err(e) => return Err(e),
} }

@ -134,7 +134,7 @@ impl INode for HNode {
Ok(()) Ok(())
} }
fn create(&self, name: &str, type_: FileType, mode: u32) -> Result<Arc<dyn INode>> { fn create(&self, name: &str, type_: FileType, mode: u16) -> Result<Arc<dyn INode>> {
let new_path = self.path.join(name); let new_path = self.path.join(name);
if new_path.exists() { if new_path.exists() {
return Err(FsError::EntryExist); return Err(FsError::EntryExist);

@ -97,25 +97,32 @@ pub fn do_timerfd_gettime(fd: FileDesc, curr_value_ptr: *mut itimerspec_t) -> Re
Ok(0) Ok(0)
} }
pub fn do_creat(path: *const i8, mode: u32) -> Result<isize> { pub fn do_creat(path: *const i8, mode: u16) -> Result<isize> {
let flags = let flags =
AccessMode::O_WRONLY as u32 | (CreationFlags::O_CREAT | CreationFlags::O_TRUNC).bits(); AccessMode::O_WRONLY as u32 | (CreationFlags::O_CREAT | CreationFlags::O_TRUNC).bits();
self::do_open(path, flags, mode) self::do_open(path, flags, mode)
} }
pub fn do_open(path: *const i8, flags: u32, mode: u32) -> Result<isize> { pub fn do_open(path: *const i8, flags: u32, mode: u16) -> Result<isize> {
self::do_openat(AT_FDCWD, path, flags, mode) self::do_openat(AT_FDCWD, path, flags, mode)
} }
pub fn do_openat(dirfd: i32, path: *const i8, flags: u32, mode: u32) -> Result<isize> { pub fn do_openat(dirfd: i32, path: *const i8, flags: u32, mode: u16) -> Result<isize> {
let path = from_user::clone_cstring_safely(path)? let path = from_user::clone_cstring_safely(path)?
.to_string_lossy() .to_string_lossy()
.into_owned(); .into_owned();
let fs_path = FsPath::new(&path, dirfd, false)?; let fs_path = FsPath::new(&path, dirfd, false)?;
let mode = FileMode::from_bits_truncate(mode);
let fd = file_ops::do_openat(&fs_path, flags, mode)?; let fd = file_ops::do_openat(&fs_path, flags, mode)?;
Ok(fd as isize) Ok(fd as isize)
} }
pub fn do_umask(mask: u16) -> Result<isize> {
let new_mask = FileMode::from_bits_truncate(mask).to_umask();
let old_mask = current!().process().set_umask(new_mask);
Ok(old_mask.bits() as isize)
}
pub fn do_close(fd: FileDesc) -> Result<isize> { pub fn do_close(fd: FileDesc) -> Result<isize> {
file_ops::do_close(fd)?; file_ops::do_close(fd)?;
Ok(0) Ok(0)
@ -414,15 +421,16 @@ pub fn do_renameat(
Ok(0) Ok(0)
} }
pub fn do_mkdir(path: *const i8, mode: usize) -> Result<isize> { pub fn do_mkdir(path: *const i8, mode: u16) -> Result<isize> {
self::do_mkdirat(AT_FDCWD, path, mode) self::do_mkdirat(AT_FDCWD, path, mode)
} }
pub fn do_mkdirat(dirfd: i32, path: *const i8, mode: usize) -> Result<isize> { pub fn do_mkdirat(dirfd: i32, path: *const i8, mode: u16) -> Result<isize> {
let path = from_user::clone_cstring_safely(path)? let path = from_user::clone_cstring_safely(path)?
.to_string_lossy() .to_string_lossy()
.into_owned(); .into_owned();
let fs_path = FsPath::new(&path, dirfd, false)?; let fs_path = FsPath::new(&path, dirfd, false)?;
let mode = FileMode::from_bits_truncate(mode);
file_ops::do_mkdirat(&fs_path, mode)?; file_ops::do_mkdirat(&fs_path, mode)?;
Ok(0) Ok(0)
} }

@ -3,8 +3,8 @@ use super::endpoint::{end_pair, Endpoint, RelayNotifier};
use super::*; use super::*;
use events::{Event, EventFilter, Notifier, Observer}; use events::{Event, EventFilter, Notifier, Observer};
use fs::channel::Channel; use fs::channel::Channel;
use fs::CreationFlags;
use fs::IoEvents; use fs::IoEvents;
use fs::{CreationFlags, FileMode};
use std::fmt; use std::fmt;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc; use std::sync::Arc;
@ -75,8 +75,11 @@ impl Stream {
let corresponding_inode_num = { let corresponding_inode_num = {
let current = current!(); let current = current!();
let fs = current.fs().read().unwrap(); let fs = current.fs().read().unwrap();
let file_ref = let file_ref = fs.open_file(
fs.open_file(path.path_str(), CreationFlags::O_CREAT.bits(), 0o777)?; path.path_str(),
CreationFlags::O_CREAT.bits(),
FileMode::from_bits(0o777).unwrap(),
)?;
file_ref.metadata()?.inode file_ref.metadata()?.inode
}; };
*inode_num = Some(corresponding_inode_num); *inode_num = Some(corresponding_inode_num);

@ -10,7 +10,7 @@ use super::task::Task;
use super::thread::{ThreadId, ThreadName}; use super::thread::{ThreadId, ThreadName};
use super::{table, task, ProcessRef, ThreadRef}; use super::{table, task, ProcessRef, ThreadRef};
use crate::fs::{ use crate::fs::{
CreationFlags, File, FileDesc, FileTable, FsView, HostStdioFds, StdinFile, StdoutFile, CreationFlags, File, FileDesc, FileMode, FileTable, FsView, HostStdioFds, StdinFile, StdoutFile,
}; };
use crate::prelude::*; use crate::prelude::*;
use crate::vm::ProcessVM; use crate::vm::ProcessVM;
@ -285,6 +285,7 @@ fn new_process_common(
process_builder process_builder
.vm(vm_ref) .vm(vm_ref)
.exec_path(&elf_path) .exec_path(&elf_path)
.umask(parent.umask())
.parent(parent) .parent(parent)
.task(task) .task(task)
.sched(sched_ref) .sched(sched_ref)
@ -339,12 +340,11 @@ fn init_files(
oflag, oflag,
fd, fd,
} => { } => {
let file_ref = let file_ref = current_ref.fs().read().unwrap().open_file(
current_ref path.as_str(),
.fs() oflag,
.read() FileMode::from_bits_truncate(mode as u16),
.unwrap() )?;
.open_file(path.as_str(), oflag, mode)?;
let creation_flags = CreationFlags::from_bits_truncate(oflag); let creation_flags = CreationFlags::from_bits_truncate(oflag);
cloned_file_table.put_at(fd, file_ref, creation_flags.must_close_on_spawn()); cloned_file_table.put_at(fd, file_ref, creation_flags.must_close_on_spawn());
} }

@ -5,6 +5,7 @@ use super::super::{
SchedAgentRef, SchedAgentRef,
}; };
use super::{Process, ProcessInner}; use super::{Process, ProcessInner};
use crate::fs::FileMode;
use crate::prelude::*; use crate::prelude::*;
use crate::signal::{SigDispositions, SigQueues, SigSet}; use crate::signal::{SigDispositions, SigQueues, SigSet};
@ -16,6 +17,7 @@ pub struct ProcessBuilder {
vm: Option<ProcessVMRef>, vm: Option<ProcessVMRef>,
// Optional fields, which have reasonable default values // Optional fields, which have reasonable default values
exec_path: Option<String>, exec_path: Option<String>,
umask: Option<FileMode>,
parent: Option<ProcessRef>, parent: Option<ProcessRef>,
no_parent: bool, no_parent: bool,
sig_dispositions: Option<SigDispositions>, sig_dispositions: Option<SigDispositions>,
@ -29,6 +31,7 @@ impl ProcessBuilder {
thread_builder: Some(thread_builder), thread_builder: Some(thread_builder),
vm: None, vm: None,
exec_path: None, exec_path: None,
umask: None,
parent: None, parent: None,
no_parent: false, no_parent: false,
sig_dispositions: None, sig_dispositions: None,
@ -45,6 +48,11 @@ impl ProcessBuilder {
self self
} }
pub fn umask(mut self, umask: FileMode) -> Self {
self.umask = Some(umask);
self
}
pub fn parent(mut self, parent: ProcessRef) -> Self { pub fn parent(mut self, parent: ProcessRef) -> Self {
self.parent = Some(parent); self.parent = Some(parent);
self self
@ -108,6 +116,7 @@ impl ProcessBuilder {
// Build a new process // Build a new process
let new_process = { let new_process = {
let exec_path = self.exec_path.take().unwrap_or_default(); let exec_path = self.exec_path.take().unwrap_or_default();
let umask = RwLock::new(self.umask.unwrap_or(FileMode::default_umask()));
let parent = self.parent.take().map(|parent| RwLock::new(parent)); let parent = self.parent.take().map(|parent| RwLock::new(parent));
let inner = SgxMutex::new(ProcessInner::new()); let inner = SgxMutex::new(ProcessInner::new());
let sig_dispositions = RwLock::new(self.sig_dispositions.unwrap_or_default()); let sig_dispositions = RwLock::new(self.sig_dispositions.unwrap_or_default());
@ -116,6 +125,7 @@ impl ProcessBuilder {
Arc::new(Process { Arc::new(Process {
pid, pid,
exec_path, exec_path,
umask,
parent, parent,
inner, inner,
sig_dispositions, sig_dispositions,

@ -2,6 +2,7 @@ use std::fmt;
use super::wait::WaitQueue; use super::wait::WaitQueue;
use super::{ForcedExitStatus, ProcessRef, TermStatus, ThreadRef}; use super::{ForcedExitStatus, ProcessRef, TermStatus, ThreadRef};
use crate::fs::FileMode;
use crate::prelude::*; use crate::prelude::*;
use crate::signal::{SigDispositions, SigNum, SigQueues}; use crate::signal::{SigDispositions, SigNum, SigQueues};
@ -18,6 +19,7 @@ pub struct Process {
// Mutable info // Mutable info
parent: Option<RwLock<ProcessRef>>, parent: Option<RwLock<ProcessRef>>,
inner: SgxMutex<ProcessInner>, inner: SgxMutex<ProcessInner>,
umask: RwLock<FileMode>,
// Signal // Signal
sig_dispositions: RwLock<SigDispositions>, sig_dispositions: RwLock<SigDispositions>,
sig_queues: RwLock<SigQueues>, sig_queues: RwLock<SigQueues>,
@ -99,6 +101,19 @@ impl Process {
&self.exec_path &self.exec_path
} }
/// Get the file mode creation mask
pub fn umask(&self) -> FileMode {
self.umask.read().unwrap().clone()
}
/// Set the file mode creation mask, return the previous value
pub fn set_umask(&self, new_mask: FileMode) -> FileMode {
let mut mask = self.umask.write().unwrap();
let old_mask = mask.clone();
*mask = new_mask;
old_mask
}
/// Get the signal queues for process-directed signals. /// Get the signal queues for process-directed signals.
pub fn sig_queues(&self) -> &RwLock<SigQueues> { pub fn sig_queues(&self) -> &RwLock<SigQueues> {
&self.sig_queues &self.sig_queues

@ -29,8 +29,9 @@ use crate::fs::{
do_lseek, do_lstat, do_mkdir, do_mkdirat, do_mount_rootfs, do_open, do_openat, do_pipe, do_lseek, do_lstat, do_mkdir, do_mkdirat, do_mount_rootfs, do_open, do_openat, do_pipe,
do_pipe2, do_pread, do_pwrite, do_read, do_readlink, do_readlinkat, do_readv, do_rename, do_pipe2, do_pread, do_pwrite, do_read, do_readlink, do_readlinkat, do_readv, do_rename,
do_renameat, do_rmdir, do_sendfile, do_stat, do_statfs, do_symlink, do_symlinkat, do_sync, do_renameat, do_rmdir, do_sendfile, do_stat, do_statfs, do_symlink, do_symlinkat, do_sync,
do_timerfd_create, do_timerfd_gettime, do_timerfd_settime, do_truncate, do_unlink, do_unlinkat, do_timerfd_create, do_timerfd_gettime, do_timerfd_settime, do_truncate, do_umask, do_unlink,
do_write, do_writev, iovec_t, AsTimer, File, FileDesc, FileRef, HostStdioFds, Stat, Statfs, do_unlinkat, do_write, do_writev, iovec_t, AsTimer, 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};
@ -89,7 +90,7 @@ macro_rules! process_syscall_table_with_callback {
// TODO: Unify the use of C types. For example, u8 or i8 or char_c for C string? // TODO: Unify the use of C types. For example, u8 or i8 or char_c for C string?
(Read = 0) => do_read(fd: FileDesc, buf: *mut u8, size: usize), (Read = 0) => do_read(fd: FileDesc, buf: *mut u8, size: usize),
(Write = 1) => do_write(fd: FileDesc, buf: *const u8, size: usize), (Write = 1) => do_write(fd: FileDesc, buf: *const u8, size: usize),
(Open = 2) => do_open(path: *const i8, flags: u32, mode: u32), (Open = 2) => do_open(path: *const i8, flags: u32, mode: u16),
(Close = 3) => do_close(fd: FileDesc), (Close = 3) => do_close(fd: FileDesc),
(Stat = 4) => do_stat(path: *const i8, stat_buf: *mut Stat), (Stat = 4) => do_stat(path: *const i8, stat_buf: *mut Stat),
(Fstat = 5) => do_fstat(fd: FileDesc, stat_buf: *mut Stat), (Fstat = 5) => do_fstat(fd: FileDesc, stat_buf: *mut Stat),
@ -170,9 +171,9 @@ macro_rules! process_syscall_table_with_callback {
(Chdir = 80) => do_chdir(path: *const i8), (Chdir = 80) => do_chdir(path: *const i8),
(Fchdir = 81) => do_fchdir(fd: FileDesc), (Fchdir = 81) => do_fchdir(fd: FileDesc),
(Rename = 82) => do_rename(oldpath: *const i8, newpath: *const i8), (Rename = 82) => do_rename(oldpath: *const i8, newpath: *const i8),
(Mkdir = 83) => do_mkdir(path: *const i8, mode: usize), (Mkdir = 83) => do_mkdir(path: *const i8, mode: u16),
(Rmdir = 84) => do_rmdir(path: *const i8), (Rmdir = 84) => do_rmdir(path: *const i8),
(Creat = 85) => do_creat(path: *const i8, mode: u32), (Creat = 85) => do_creat(path: *const i8, mode: u16),
(Link = 86) => do_link(oldpath: *const i8, newpath: *const i8), (Link = 86) => do_link(oldpath: *const i8, newpath: *const i8),
(Unlink = 87) => do_unlink(path: *const i8), (Unlink = 87) => do_unlink(path: *const i8),
(Symlink = 88) => do_symlink(target: *const i8, link_path: *const i8), (Symlink = 88) => do_symlink(target: *const i8, link_path: *const i8),
@ -182,7 +183,7 @@ macro_rules! process_syscall_table_with_callback {
(Chown = 92) => do_chown(path: *const i8, uid: u32, gid: u32), (Chown = 92) => do_chown(path: *const i8, uid: u32, gid: u32),
(Fchown = 93) => do_fchown(fd: FileDesc, uid: u32, gid: u32), (Fchown = 93) => do_fchown(fd: FileDesc, uid: u32, gid: u32),
(Lchown = 94) => do_lchown(path: *const i8, uid: u32, gid: u32), (Lchown = 94) => do_lchown(path: *const i8, uid: u32, gid: u32),
(Umask = 95) => handle_unsupported(), (Umask = 95) => do_umask(mask: u16),
(Gettimeofday = 96) => do_gettimeofday(tv_u: *mut timeval_t), (Gettimeofday = 96) => do_gettimeofday(tv_u: *mut timeval_t),
(Getrlimit = 97) => handle_unsupported(), (Getrlimit = 97) => handle_unsupported(),
(Getrusage = 98) => handle_unsupported(), (Getrusage = 98) => handle_unsupported(),
@ -344,8 +345,8 @@ macro_rules! process_syscall_table_with_callback {
(InotifyAddWatch = 254) => handle_unsupported(), (InotifyAddWatch = 254) => handle_unsupported(),
(InotifyRmWatch = 255) => handle_unsupported(), (InotifyRmWatch = 255) => handle_unsupported(),
(MigratePages = 256) => handle_unsupported(), (MigratePages = 256) => handle_unsupported(),
(Openat = 257) => do_openat(dirfd: i32, path: *const i8, flags: u32, mode: u32), (Openat = 257) => do_openat(dirfd: i32, path: *const i8, flags: u32, mode: u16),
(Mkdirat = 258) => do_mkdirat(dirfd: i32, path: *const i8, mode: usize), (Mkdirat = 258) => do_mkdirat(dirfd: i32, path: *const i8, mode: u16),
(Mknodat = 259) => handle_unsupported(), (Mknodat = 259) => handle_unsupported(),
(Fchownat = 260) => do_fchownat(dirfd: i32, path: *const i8, uid: u32, gid: u32, flags: i32), (Fchownat = 260) => do_fchownat(dirfd: i32, path: *const i8, uid: u32, gid: u32, flags: i32),
(Futimesat = 261) => handle_unsupported(), (Futimesat = 261) => handle_unsupported(),

@ -1,5 +1,5 @@
use super::*; use super::*;
use crate::fs::{AccessMode, CreationFlags, FsView}; use crate::fs::{AccessMode, CreationFlags, FileMode, FsView};
use resolv_conf::*; use resolv_conf::*;
use std::ffi::CStr; use std::ffi::CStr;
use std::str; use std::str;
@ -11,7 +11,7 @@ pub fn write_resolv_conf() -> Result<()> {
let resolv_conf_file = fs_view.open_file( let resolv_conf_file = fs_view.open_file(
RESOLV_CONF_PATH, RESOLV_CONF_PATH,
AccessMode::O_RDWR as u32 | CreationFlags::O_CREAT.bits() | CreationFlags::O_TRUNC.bits(), AccessMode::O_RDWR as u32 | CreationFlags::O_CREAT.bits() | CreationFlags::O_TRUNC.bits(),
0o666, FileMode::from_bits(0o666).unwrap(),
)?; )?;
let resolv_conf_str = RESOLV_CONF_STR.read().unwrap(); let resolv_conf_str = RESOLV_CONF_STR.read().unwrap();
match &*resolv_conf_str { match &*resolv_conf_str {

@ -19,7 +19,7 @@ TESTS ?= env empty hello_world malloc mmap file fs_perms getpid spawn sched pipe
truncate readdir mkdir open stat link symlink chmod chown tls pthread system_info resolv_conf rlimit \ truncate readdir mkdir open stat link symlink chmod chown tls pthread system_info resolv_conf 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 \ ioctl fcntl eventfd emulate_syscall access signal sysinfo prctl rename procfs wait \
spawn_attribute exec statfs spawn_attribute exec statfs umask
# 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

5
test/umask/Makefile Normal file

@ -0,0 +1,5 @@
include ../test_common.mk
EXTRA_C_FLAGS :=
EXTRA_LINK_FLAGS :=
BIN_ARGS :=

100
test/umask/main.c Normal file

@ -0,0 +1,100 @@
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include "test_fs.h"
// ============================================================================
// Helper function
// ============================================================================
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;
}
static int check_create_file_with_umask(const char *file_path, mode_t mask) {
mode_t mode = 00666;
int fd = creat(file_path, mode);
if (fd < 0) {
THROW_ERROR("failed to create file");
}
struct stat stat_buf;
if (fstat(fd, &stat_buf) < 0) {
THROW_ERROR("failed to stat file");
}
mode_t actual_mode = stat_buf.st_mode & 00777;
if (actual_mode != (mode & ~mask)) {
THROW_ERROR("failed to check the mode with umask(%o), actual_mode is: %o", mask,
actual_mode);
}
return 0;
}
// ============================================================================
// Test cases for umask
// ============================================================================
#define DEFAULT_UMASK (00022)
static int __test_create_file_with_default_umask(const char *file_path) {
if (check_create_file_with_umask(file_path, DEFAULT_UMASK) < 0) {
THROW_ERROR("failed to check default umask");
}
return 0;
}
static int __test_umask(const char *file_path) {
mode_t new_mask = 00066;
int old_mask = umask(new_mask);
if (old_mask != DEFAULT_UMASK) {
THROW_ERROR("failed to get correct default mask");
}
if (check_create_file_with_umask(file_path, new_mask) < 0) {
THROW_ERROR("failed to check default umask");
}
return 0;
}
typedef int(*test_file_func_t)(const char *);
static int test_file_framework(test_file_func_t fn) {
const char *file_path = "/root/test_filesystem_umask.txt";
if (fn(file_path) < 0) {
return -1;
}
if (remove_file(file_path) < 0) {
return -1;
}
return 0;
}
static int test_create_file_with_default_umask() {
return test_file_framework(__test_create_file_with_default_umask);
}
static int test_umask() {
return test_file_framework(__test_umask);
}
// ============================================================================
// Test suite main
// ============================================================================
static test_case_t test_cases[] = {
TEST_CASE(test_create_file_with_default_umask),
TEST_CASE(test_umask),
};
int main(int argc, const char *argv[]) {
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
}