Skip to content

Commit 5c774e0

Browse files
committed
rebased with develop
1 parent 9385a31 commit 5c774e0

File tree

2 files changed

+186
-24
lines changed

2 files changed

+186
-24
lines changed

src/safeposix/syscalls/fs_calls.rs

Lines changed: 101 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,12 +1396,45 @@ impl Cage {
13961396
}
13971397

13981398
//------------------------------------STATFS SYSCALL------------------------------------
1399+
/// ### Description
1400+
///
1401+
/// `statfs_syscall` retrieves file system status information for the file
1402+
/// system containing the file specified by `path` and populates the
1403+
/// provided `databuf` with this information.
1404+
///
1405+
/// ### Arguments
1406+
///
1407+
/// It accepts two parameters:
1408+
/// * `path` - A string slice that specifies the file path for which file
1409+
/// system status information is to be retrieved.
1410+
/// * `databuf` - A mutable reference to a `FSData` struct where the file
1411+
/// system status will be stored.
1412+
///
1413+
/// ### Returns
1414+
///
1415+
/// For a successful call, the return value will be 0. On error, a negative
1416+
/// errno is returned to indicate the error.
1417+
///
1418+
/// ### Errors
1419+
///
1420+
/// * `ENOENT` - The file specified by `path` does not exist or the path is
1421+
/// invalid.
1422+
///
1423+
/// ### Panics
1424+
///
1425+
/// * There are no panics that can happen in this function.
1426+
///
1427+
/// For more detailed description of all the commands and return values,
1428+
/// refer to the statfs man page [here](https://man7.org/linux/man-pages/man2/statfs.2.html).
13991429
14001430
pub fn statfs_syscall(&self, path: &str, databuf: &mut FSData) -> i32 {
1431+
//convert the path to an absolute path of type `PathBuf`
14011432
let truepath = normpath(convpath(path), self);
14021433

14031434
//Walk the file tree to get inode from path
14041435
if let Some(inodenum) = metawalk(truepath.as_path()) {
1436+
// won't panic since check for inode number in table is already happening in
1437+
// above 'metawalk' function
14051438
let _inodeobj = FS_METADATA.inodetable.get(&inodenum).unwrap();
14061439

14071440
//populate the dev id field -- can be done outside of the helper
@@ -1415,35 +1448,80 @@ impl Cage {
14151448
}
14161449

14171450
//------------------------------------FSTATFS SYSCALL------------------------------------
1451+
/// ### Description
1452+
///
1453+
/// `fstatfs_syscall` retrieves file system status information for the file
1454+
/// system containing the file specified by the file descriptor `fd` and
1455+
/// populates the provided `databuf` with this information.
1456+
///
1457+
/// ### Arguments
1458+
///
1459+
/// It accepts two parameters:
1460+
/// * `fd` - The file descriptor that refers to the open file.
1461+
/// * `databuf` - A mutable reference to a `FSData` struct where the file
1462+
/// system status will be stored.
1463+
///
1464+
/// ### Returns
1465+
///
1466+
/// For a successful call, the return value will be 0. On error, a negative
1467+
/// errno is returned to indicate the error.
1468+
///
1469+
/// ### Errors
1470+
///
1471+
/// * `EBADF` - The file descriptor `fd` is either invalid or it refers to a
1472+
/// socket, stream, pipe, or epoll file descriptor, which are not
1473+
/// supported by this function.
1474+
///
1475+
/// ### Panics
1476+
///
1477+
/// * If the file descriptor provided isn't in the appropriate range, this
1478+
/// function can panic.
1479+
///
1480+
/// For more detailed description of all the commands and return values,
1481+
/// refer to the statfs man page [here](https://man7.org/linux/man-pages/man2/statfs.2.html).
14181482
14191483
pub fn fstatfs_syscall(&self, fd: i32, databuf: &mut FSData) -> i32 {
1484+
// BUG: If the provided file descriptor is out of bounds, get_filedescriptor
1485+
// returns Err(), unwrapping on which produces a 'panic!'
1486+
// otherwise, file descriptor table entry is stored in 'checkedfd'
14201487
let checkedfd = self.get_filedescriptor(fd).unwrap();
14211488
let unlocked_fd = checkedfd.read();
1489+
14221490
if let Some(filedesc_enum) = &*unlocked_fd {
14231491
//populate the dev id field -- can be done outside of the helper
14241492
databuf.f_fsid = FS_METADATA.dev_id;
14251493

14261494
match filedesc_enum {
1495+
// if the fd points to a normal file descriptor
14271496
File(normalfile_filedesc_obj) => {
1497+
// won't panic since we have already checked that the entries exist
1498+
// in the FS_METADATA inode table
14281499
let _inodeobj = FS_METADATA
14291500
.inodetable
14301501
.get(&normalfile_filedesc_obj.inode)
14311502
.unwrap();
14321503

1504+
// populate the databuf using a helper function
14331505
return Self::_istatfs_helper(self, databuf);
14341506
}
1507+
1508+
// if the fd points to a socket, pipe, stream, or epoll file descriptor
14351509
Socket(_) | Pipe(_) | Stream(_) | Epoll(_) => {
14361510
return syscall_error(
14371511
Errno::EBADF,
14381512
"fstatfs",
1439-
"can't fstatfs on socket, stream, pipe, or epollfd",
1513+
"can't fstatfs on sockets, streams, pipes, or epoll fds",
14401514
);
14411515
}
14421516
}
1517+
} else {
1518+
return syscall_error(Errno::EBADF, "statfs", "invalid file descriptor");
14431519
}
1444-
return syscall_error(Errno::EBADF, "statfs", "invalid file descriptor");
14451520
}
14461521

1522+
// These values have (probably) been picked up from the previously used
1523+
// environment, and have been working fine till now for our purposes
1524+
// TODO: Figure out how to populate the databuf values properly
14471525
pub fn _istatfs_helper(&self, databuf: &mut FSData) -> i32 {
14481526
databuf.f_type = 0xBEEFC0DE; //unassigned
14491527
databuf.f_bsize = 4096;
@@ -5306,16 +5384,19 @@ impl Cage {
53065384

53075385
/// ### Description
53085386
///
5309-
/// `shmget_syscall` returns the shared memory segment identifier associated with a particular `key`
5310-
/// If a key doesn't exist, shmget creates a new memory segment and attaches it to the key.
5311-
/// Traditionally if the value of the key equals `IPC_PRIVATE`, we also create a new memory segment which
5312-
/// is not associated with a key during this syscall,
5313-
/// but for our implementaion, we return an error and only create a new memory
5314-
/// segment when the IPC_CREAT flag is specified in the`shmflag` argument.
5387+
/// `shmget_syscall` returns the shared memory segment identifier associated
5388+
/// with a particular `key` If a key doesn't exist, shmget creates a new
5389+
/// memory segment and attaches it to the key. Traditionally if the
5390+
/// value of the key equals `IPC_PRIVATE`, we also create a new memory
5391+
/// segment which is not associated with a key during this syscall,
5392+
/// but for our implementaion, we return an error and only create a new
5393+
/// memory segment when the IPC_CREAT flag is specified in the`shmflag`
5394+
/// argument.
53155395
///
53165396
/// ### Returns
53175397
///
5318-
/// An 32 bit integer which represens the identifier of the memory segment associated with the key
5398+
/// An 32 bit integer which represens the identifier of the memory segment
5399+
/// associated with the key
53195400
///
53205401
/// ### Arguments
53215402
///
@@ -5324,20 +5405,22 @@ impl Cage {
53245405
/// `shmflag` : mode flags which indicate whether to create a new key or not
53255406
/// The `shmflag` is composed of the following
53265407
/// * IPC_CREAT - specify that the system call creates a new segment
5327-
/// * IPC_EXCL - this flag is used with IPC_CREAT to cause this function to fail when IPC_CREAT is also used
5328-
/// and the key passed has a memory segment associated with it.
5408+
/// * IPC_EXCL - this flag is used with IPC_CREAT to cause this function to
5409+
/// fail when IPC_CREAT is also used and the key passed has a memory
5410+
/// segment associated with it.
53295411
///
53305412
/// ### Errors
53315413
///
53325414
/// * ENOENT : the key equals the `IPC_PRIVATE` constant
5333-
/// * EEXIST : key exists and yet either `IPC_CREAT` or `IPC_EXCL` are passed as flags
5415+
/// * EEXIST : key exists and yet either `IPC_CREAT` or `IPC_EXCL` are
5416+
/// passed as flags
53345417
/// * ENOENT : key did not exist and the `IPC_CREAT` flag was not passed
5335-
/// * EINVAL : the size passed was less than the minimum size of segment or greater than the maximum possible size
5418+
/// * EINVAL : the size passed was less than the minimum size of segment or
5419+
/// greater than the maximum possible size
53365420
///
53375421
/// ### Panics
53385422
///
53395423
/// There are no cases where the function directly panics
5340-
///
53415424
pub fn shmget_syscall(&self, key: i32, size: usize, shmflg: i32) -> i32 {
53425425
//Check if the key passed equals the IPC_PRIVATE flag
53435426
if key == IPC_PRIVATE {
@@ -5349,7 +5432,8 @@ impl Cage {
53495432
// data of the shm table
53505433
let metadata = &SHM_METADATA;
53515434

5352-
// Check if there exists a memory segment associated with the key passed as argument
5435+
// Check if there exists a memory segment associated with the key passed as
5436+
// argument
53535437
match metadata.shmkeyidtable.entry(key) {
53545438
// If there exists a memory segment at that key
53555439
interface::RustHashEntry::Occupied(occupied) => {
@@ -5375,8 +5459,8 @@ impl Cage {
53755459
);
53765460
}
53775461

5378-
// If memory segment doesn't exist and IPC_CREAT was specified - we create a new memory segment
5379-
// Check if the size passed is a valid value
5462+
// If memory segment doesn't exist and IPC_CREAT was specified - we create a new
5463+
// memory segment Check if the size passed is a valid value
53805464
if (size as u32) < SHMMIN || (size as u32) > SHMMAX {
53815465
return syscall_error(
53825466
Errno::EINVAL,

src/tests/fs_tests.rs

Lines changed: 85 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4034,7 +4034,6 @@ pub mod fs_tests {
40344034

40354035
assert_eq!(cage.close_syscall(fd), 0);
40364036
assert_eq!(cage.exit_syscall(EXIT_SUCCESS), EXIT_SUCCESS);
4037-
40384037
lindrustfinalize();
40394038
}
40404039

@@ -4048,7 +4047,8 @@ pub mod fs_tests {
40484047
let shmid = cage.shmget_syscall(33123, 1024, IPC_CREAT);
40494048
assert_eq!(shmid, 4);
40504049

4051-
// Check error upon asking for a valid key and passing the IPC_CREAT and IPC_EXCL flag
4050+
// Check error upon asking for a valid key and passing the IPC_CREAT and
4051+
// IPC_EXCL flag
40524052
assert_eq!(
40534053
cage.shmget_syscall(key, 1024, IPC_CREAT | IPC_EXCL),
40544054
-(Errno::EEXIST as i32)
@@ -4060,10 +4060,12 @@ pub mod fs_tests {
40604060
-(Errno::ENOENT as i32)
40614061
);
40624062

4063-
// Check if the function returns a correct shmid upon asking with a key that we know exists
4063+
// Check if the function returns a correct shmid upon asking with a key that we
4064+
// know exists
40644065
assert_eq!(cage.shmget_syscall(key, 1024, 0666), shmid);
40654066

4066-
// Check if the function returns the correct error when we don't pass IPC_CREAT for a key that doesn't exist
4067+
// Check if the function returns the correct error when we don't pass IPC_CREAT
4068+
// for a key that doesn't exist
40674069
assert_eq!(
40684070
cage.shmget_syscall(123456, 1024, 0),
40694071
-(Errno::ENOENT as i32)
@@ -4408,7 +4410,7 @@ pub mod fs_tests {
44084410
assert_eq!(cage.exit_syscall(EXIT_SUCCESS), EXIT_SUCCESS);
44094411
lindrustfinalize();
44104412
}
4411-
4413+
44124414
#[test]
44134415
pub fn ut_lind_fs_stat_syscall_tests() {
44144416
// acquiring a lock on TESTMUTEX prevents other tests from running concurrently,
@@ -4477,7 +4479,6 @@ pub mod fs_tests {
44774479

44784480
let mut statdata = StatData::default();
44794481

4480-
44814482
// test out whether an error is output for a non existent fd (1000)
44824483
// (ENOENT[-2])
44834484
let non_existent_fd = 1000;
@@ -4522,7 +4523,7 @@ pub mod fs_tests {
45224523
let socket = interface::GenSockaddr::Unix(sockaddr);
45234524
assert_eq!(cage.bind_syscall(socketfd, &socket), 0);
45244525

4525-
// Errno::EOPNOTSUPP : -95
4526+
// Errno::EOPNOTSUPP : -95
45264527
assert_eq!(cage.fstat_syscall(socketfd, &mut statdata), -95);
45274528

45284529
// Clean up
@@ -4533,4 +4534,81 @@ pub mod fs_tests {
45334534
lindrustfinalize();
45344535
return;
45354536
}
4537+
4538+
#[test]
4539+
pub fn ut_lind_fs_statfs_syscall_tests() {
4540+
// acquiring a lock on TESTMUTEX prevents other tests from running concurrently,
4541+
// and also performs clean env setup
4542+
let _thelock = setup::lock_and_init();
4543+
4544+
let cage = interface::cagetable_getref(1);
4545+
let mut fsdata = FSData::default();
4546+
4547+
// test out whether an error is output for a non existent file path
4548+
// (ENOENT[-2])
4549+
assert_eq!(
4550+
cage.statfs_syscall("non_existent_file_path", &mut fsdata),
4551+
syscall_error(Errno::ENOENT, "stat", "test_failure")
4552+
);
4553+
4554+
// setting up inode object "/tmp/generic" for testing statfs_syscall
4555+
let generic_path = "/tmp/generic";
4556+
let creat_fd = cage.creat_syscall(generic_path, S_IRWXA);
4557+
assert!(creat_fd > 0);
4558+
assert_eq!(cage.statfs_syscall(generic_path, &mut fsdata), 0);
4559+
4560+
lindrustfinalize();
4561+
return;
4562+
}
4563+
4564+
#[test]
4565+
pub fn ut_lind_fs_fstatfs_syscall_tests() {
4566+
//acquiring a lock on TESTMUTEX prevents other tests from running concurrently,
4567+
// and also performs clean env setup
4568+
let _thelock = setup::lock_and_init();
4569+
4570+
let cage = interface::cagetable_getref(1);
4571+
4572+
let mut fsdata = FSData::default();
4573+
4574+
// test out whether an error is output for a non existent fd (1000)
4575+
// (ENOENT[-2])
4576+
let non_existent_fd = 1000;
4577+
assert_eq!(
4578+
cage.fstatfs_syscall(non_existent_fd, &mut fsdata),
4579+
syscall_error(Errno::EBADF, "stat", "test_failure")
4580+
);
4581+
4582+
// setting up generic inode object "/tmp/generic" for testing fstat_syscall with
4583+
// a generic file
4584+
let generic_path = "/tmp/generic";
4585+
let creat_fd = cage.creat_syscall(generic_path, S_IRWXA);
4586+
assert!(creat_fd > 0);
4587+
assert_eq!(cage.fstatfs_syscall(creat_fd, &mut fsdata), 0);
4588+
4589+
// setting up socket inode object with path "/socket.sock" for testing
4590+
// fstat_syscall with a socket
4591+
let socketfile_path = "/socket.sock";
4592+
4593+
let socketfd = cage.socket_syscall(AF_UNIX, SOCK_STREAM, 0);
4594+
assert!(socketfd > 0);
4595+
4596+
let sockaddr = interface::new_sockaddr_unix(AF_UNIX as u16, socketfile_path.as_bytes());
4597+
let socket = interface::GenSockaddr::Unix(sockaddr);
4598+
assert_eq!(cage.bind_syscall(socketfd, &socket), 0);
4599+
4600+
// Errno::EBADF : -9
4601+
assert_eq!(
4602+
cage.fstatfs_syscall(socketfd, &mut fsdata),
4603+
syscall_error(Errno::EBADF, "stat", "test_failure")
4604+
);
4605+
4606+
// Clean up
4607+
assert_eq!(cage.close_syscall(socketfd), 0);
4608+
4609+
cage.unlink_syscall(socketfile_path);
4610+
4611+
lindrustfinalize();
4612+
return;
4613+
}
45364614
}

0 commit comments

Comments
 (0)