@@ -1928,16 +1928,32 @@ impl Cage {
19281928 }
19291929
19301930 //------------------------------------FCNTL SYSCALL------------------------------------
1931+
1932+ //fcntl performs operations, like returning or setting file status flags,
1933+ //duplicating a file descriptor, etc., on an open file descriptor
1934+ //it accepts three parameters: fd - an open file descriptor, cmd - an operation to be performed on fd,
1935+ //and arg - an optional argument (whether or not arg is required is determined by cmd)
1936+ //for a successful call, the return value depends on the operation and can be one of: zero, the new file descriptor,
1937+ //value of file descriptor flags, value of status flags, etc.
1938+ //for more detailed description of all the commands and return values, see
1939+ //https://linux.die.net/man/2/fcntl
19311940
19321941 pub fn fcntl_syscall ( & self , fd : i32 , cmd : i32 , arg : i32 ) -> i32 {
1942+ //BUG
1943+ //if the provided file descriptor is out of bounds, get_filedescriptor returns Err(),
1944+ //unwrapping on which produces a 'panic!'
1945+ //otherwise, file descriptor table entry is stored in 'checkedfd'
19331946 let checkedfd = self . get_filedescriptor ( fd) . unwrap ( ) ;
19341947 let mut unlocked_fd = checkedfd. write ( ) ;
1935- if let Some ( filedesc_enum) = & mut * unlocked_fd {
1948+ if let Some ( filedesc_enum) = & mut * unlocked_fd {
1949+ //'flags' consists of bitwise-or'd access mode, file creation, and file status flags
1950+ //to retrieve a particular flag, it can bitwise-and'd with 'flags'
19361951 let flags = match filedesc_enum {
19371952 Epoll ( obj) => & mut obj. flags ,
19381953 Pipe ( obj) => & mut obj. flags ,
19391954 Stream ( obj) => & mut obj. flags ,
19401955 File ( obj) => & mut obj. flags ,
1956+ //not clear why running F_SETFL on Socket type requires special treatment
19411957 Socket ( ref mut sockfdobj) => {
19421958 if cmd == F_SETFL && arg >= 0 {
19431959 let sock_tmp = sockfdobj. handle . clone ( ) ;
@@ -1946,10 +1962,10 @@ impl Cage {
19461962 if let Some ( ins) = & mut sockhandle. innersocket {
19471963 let fcntlret;
19481964 if arg & O_NONBLOCK == O_NONBLOCK {
1949- //set for non-blocking I/O
1965+ //set non-blocking I/O
19501966 fcntlret = ins. set_nonblocking ( ) ;
19511967 } else {
1952- //clear non- blocking I/O
1968+ //set blocking I/O
19531969 fcntlret = ins. set_blocking ( ) ;
19541970 }
19551971 if fcntlret < 0 {
@@ -1974,41 +1990,54 @@ impl Cage {
19741990 //matching the tuple
19751991 match ( cmd, arg) {
19761992 //because the arg parameter is not used in certain commands, it can be anything (..)
1993+ //F_GETFD returns file descriptor flags only, meaning that access mode flags
1994+ //and file status flags are excluded
1995+ //F_SETFD is used to set file descriptor flags only, meaning that any changes to access mode flags
1996+ //or file status flags should be ignored
1997+ //currently, O_CLOEXEC is the only defined file descriptor flag, thus only this flag is
1998+ //masked when using F_GETFD or F_SETFD
19771999 ( F_GETFD , ..) => * flags & O_CLOEXEC ,
1978- // set the flags but make sure that the flags are valid
19792000 ( F_SETFD , arg) if arg >= 0 => {
19802001 if arg & O_CLOEXEC != 0 {
2002+ //if O_CLOEXEC flag is set to 1 in 'arg', 'flags' is updated by setting its O_CLOEXEC bit to 1
19812003 * flags |= O_CLOEXEC ;
19822004 } else {
2005+ //if O_CLOEXEC flag is set to 0 in 'arg', 'flags' is updated by setting its O_CLOEXEC bit to 0
19832006 * flags &= !O_CLOEXEC ;
19842007 }
19852008 0
19862009 }
2010+ //F_GETFL should return file access mode and file status flags, which means that
2011+ //file creation flags should be masked out
19872012 ( F_GETFL , ..) => {
1988- //for get, we just need to return the flags
1989- * flags & !O_CLOEXEC
2013+ * flags & !( O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC )
19902014 }
2015+ //F_SETFL is used to set file status flags, thus any changes to file access mode and file
2016+ //creation flags should be ignored (see F_SETFL command in the man page for fcntl for the reference)
19912017 ( F_SETFL , arg) if arg >= 0 => {
1992- * flags |= arg;
2018+ //valid changes are extracted by ignoring changes to file access mode and file creation flags
2019+ let valid_changes = arg & !( O_RDWRFLAGS | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC ) ;
2020+ //access mode and creation flags are extracted and other flags are set to 0 to update them
2021+ let acc_and_creation_flags = * flags & ( O_RDWRFLAGS | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC ) ;
2022+ //valid changes are combined with the old file access mode and file creation flags
2023+ * flags = valid_changes | acc_and_creation_flags;
19932024 0
19942025 }
19952026 ( F_DUPFD , arg) if arg >= 0 => self . _dup2_helper ( & filedesc_enum, arg, false ) ,
1996- //TO DO: implement. this one is saying get the signals
2027+ //TO DO: F_GETOWN and F_SETOWN commands are not implemented yet
19972028 ( F_GETOWN , ..) => {
1998- 0 //TO DO: traditional SIGIO behavior
2029+ 0
19992030 }
20002031 ( F_SETOWN , arg) if arg >= 0 => {
2001- 0 //this would return the PID if positive and the process group if negative,
2002- //either way do nothing and return success
2032+ 0
20032033 }
2004- _ => syscall_error (
2005- Errno :: EINVAL ,
2006- "fcntl" ,
2007- "Arguments provided do not match implemented parameters" ,
2008- ) ,
2034+ _ => {
2035+ let err_msg = format ! ( "Arguments pair ({}, {}) does not match implemented parameters" , cmd, arg) ;
2036+ syscall_error ( Errno :: EINVAL , "fcntl" , & err_msg)
2037+ } ,
20092038 }
20102039 } else {
2011- syscall_error ( Errno :: EBADF , "fcntl" , "Invalid file descriptor" )
2040+ syscall_error ( Errno :: EBADF , "fcntl" , "File descriptor is out of range " )
20122041 }
20132042 }
20142043
0 commit comments