Add fstat() and poll() for the random device
This commit is contained in:
		
							parent
							
								
									9f1fa883df
								
							
						
					
					
						commit
						bbd4cd9be2
					
				| @ -41,7 +41,54 @@ impl File for DevRandom { | ||||
|         Ok(total_nbytes) | ||||
|     } | ||||
| 
 | ||||
|     fn metadata(&self) -> Result<Metadata> { | ||||
|         Ok(Metadata { | ||||
|             dev: 0, | ||||
|             inode: 0, | ||||
|             size: 0, | ||||
|             blk_size: 0, | ||||
|             blocks: 0, | ||||
|             atime: Timespec { sec: 0, nsec: 0 }, | ||||
|             mtime: Timespec { sec: 0, nsec: 0 }, | ||||
|             ctime: Timespec { sec: 0, nsec: 0 }, | ||||
|             type_: FileType::CharDevice, | ||||
|             mode: 0444, | ||||
|             nlinks: 0, | ||||
|             uid: 0, | ||||
|             gid: 0, | ||||
|             rdev: 0, | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
|     fn as_any(&self) -> &dyn Any { | ||||
|         self | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl DevRandom { | ||||
|     pub fn poll(&self, fd: &mut libc::pollfd) -> Result<usize> { | ||||
|         // Just support POLLIN event, because the device is read-only currently
 | ||||
|         let (num, revents_option) = if (fd.events & libc::POLLIN) != 0 { | ||||
|             (1, Some(libc::POLLIN)) | ||||
|         } else { | ||||
|             // Device is not ready
 | ||||
|             (0, None) | ||||
|         }; | ||||
|         if let Some(revents) = revents_option { | ||||
|             fd.revents = revents; | ||||
|         } | ||||
|         Ok(num) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub trait AsDevRandom { | ||||
|     fn as_dev_random(&self) -> Result<&DevRandom>; | ||||
| } | ||||
| 
 | ||||
| impl AsDevRandom for FileRef { | ||||
|     fn as_dev_random(&self) -> Result<&DevRandom> { | ||||
|         self.as_any() | ||||
|             .downcast_ref::<DevRandom>() | ||||
|             .ok_or_else(|| errno!(EBADF, "not random device")) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| use super::*; | ||||
| 
 | ||||
| pub use self::dev_null::DevNull; | ||||
| pub use self::dev_random::DevRandom; | ||||
| pub use self::dev_random::{AsDevRandom, DevRandom}; | ||||
| pub use self::dev_sgx::DevSgx; | ||||
| pub use self::dev_zero::DevZero; | ||||
| 
 | ||||
|  | ||||
| @ -8,6 +8,7 @@ use std::fmt; | ||||
| use std::io::{Read, Seek, SeekFrom, Write}; | ||||
| use std::mem::MaybeUninit; | ||||
| 
 | ||||
| pub use self::dev_fs::AsDevRandom; | ||||
| pub use self::file::{File, FileRef}; | ||||
| pub use self::file_ops::{AccessMode, CreationFlags, Stat, StatusFlags}; | ||||
| pub use self::file_ops::{Flock, FlockType}; | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| use super::*; | ||||
| use fs::{File, FileDesc, FileRef}; | ||||
| use fs::{AsDevRandom, File, FileDesc, FileRef}; | ||||
| use std::any::Any; | ||||
| use std::collections::btree_map::BTreeMap; | ||||
| use std::fmt; | ||||
| @ -143,6 +143,8 @@ pub fn do_poll(polls: &mut [libc::pollfd], timeout: c_int) -> Result<usize> { | ||||
|             poll.revents &= poll.events; | ||||
|             warn!("poll unix socket is unimplemented, spin for read"); | ||||
|             return Ok(1); | ||||
|         } else if let Ok(dev_random) = file_ref.as_dev_random() { | ||||
|             return Ok(dev_random.poll(poll)?); | ||||
|         } else { | ||||
|             return_errno!(EBADF, "not a socket"); | ||||
|         } | ||||
|  | ||||
| @ -1,4 +1,7 @@ | ||||
| #include <sys/stat.h> | ||||
| #include <sys/types.h> | ||||
| #include <fcntl.h> | ||||
| #include <poll.h> | ||||
| #include <unistd.h> | ||||
| #include <stdio.h> | ||||
| #include "test.h" | ||||
| @ -67,6 +70,44 @@ int test_dev_urandom() { | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int test_dev_urandom_fstat() { | ||||
|     int fd; | ||||
|     struct stat stat_buf; | ||||
| 
 | ||||
|     if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { | ||||
|         THROW_ERROR("failed to open the file"); | ||||
|     } | ||||
|     if (fstat(fd, &stat_buf) < 0) { | ||||
|         close(fd); | ||||
|         THROW_ERROR("failed to fstat the file"); | ||||
|     } | ||||
|     close(fd); | ||||
|     if ((stat_buf.st_mode & S_IFMT) != S_IFCHR) { | ||||
|         THROW_ERROR("not a character device"); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int test_dev_urandom_poll() { | ||||
|     int fd; | ||||
|     struct pollfd fds; | ||||
| 
 | ||||
|     if ((fd = open("/dev/urandom", O_RDONLY)) < 0) { | ||||
|         THROW_ERROR("failed to open the file"); | ||||
|     } | ||||
|     fds.fd = fd; | ||||
|     fds.events = POLLIN; | ||||
|     if (poll(&fds, 1, 5) <= 0) { | ||||
|         close(fd); | ||||
|         THROW_ERROR("failed to poll or file is not ready"); | ||||
|     } | ||||
|     close(fd); | ||||
|     if (fds.revents != POLLIN) { | ||||
|         THROW_ERROR("not expected returned events"); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int test_dev_arandom() { | ||||
|     if (check_file_readable("/dev/arandom")) { | ||||
|         THROW_ERROR("failed to read from /dev/arandom"); | ||||
| @ -83,6 +124,8 @@ static test_case_t test_cases[] = { | ||||
|     TEST_CASE(test_dev_zero), | ||||
|     TEST_CASE(test_dev_random), | ||||
|     TEST_CASE(test_dev_urandom), | ||||
|     TEST_CASE(test_dev_urandom_fstat), | ||||
|     TEST_CASE(test_dev_urandom_poll), | ||||
|     TEST_CASE(test_dev_arandom), | ||||
| }; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user