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) |         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 { |     fn as_any(&self) -> &dyn Any { | ||||||
|         self |         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::*; | use super::*; | ||||||
| 
 | 
 | ||||||
| pub use self::dev_null::DevNull; | 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_sgx::DevSgx; | ||||||
| pub use self::dev_zero::DevZero; | pub use self::dev_zero::DevZero; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -8,6 +8,7 @@ use std::fmt; | |||||||
| use std::io::{Read, Seek, SeekFrom, Write}; | use std::io::{Read, Seek, SeekFrom, Write}; | ||||||
| use std::mem::MaybeUninit; | use std::mem::MaybeUninit; | ||||||
| 
 | 
 | ||||||
|  | pub use self::dev_fs::AsDevRandom; | ||||||
| pub use self::file::{File, FileRef}; | pub use self::file::{File, FileRef}; | ||||||
| pub use self::file_ops::{AccessMode, CreationFlags, Stat, StatusFlags}; | pub use self::file_ops::{AccessMode, CreationFlags, Stat, StatusFlags}; | ||||||
| pub use self::file_ops::{Flock, FlockType}; | pub use self::file_ops::{Flock, FlockType}; | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| use super::*; | use super::*; | ||||||
| use fs::{File, FileDesc, FileRef}; | use fs::{AsDevRandom, File, FileDesc, FileRef}; | ||||||
| use std::any::Any; | use std::any::Any; | ||||||
| use std::collections::btree_map::BTreeMap; | use std::collections::btree_map::BTreeMap; | ||||||
| use std::fmt; | use std::fmt; | ||||||
| @ -143,6 +143,8 @@ pub fn do_poll(polls: &mut [libc::pollfd], timeout: c_int) -> Result<usize> { | |||||||
|             poll.revents &= poll.events; |             poll.revents &= poll.events; | ||||||
|             warn!("poll unix socket is unimplemented, spin for read"); |             warn!("poll unix socket is unimplemented, spin for read"); | ||||||
|             return Ok(1); |             return Ok(1); | ||||||
|  |         } else if let Ok(dev_random) = file_ref.as_dev_random() { | ||||||
|  |             return Ok(dev_random.poll(poll)?); | ||||||
|         } else { |         } else { | ||||||
|             return_errno!(EBADF, "not a socket"); |             return_errno!(EBADF, "not a socket"); | ||||||
|         } |         } | ||||||
|  | |||||||
| @ -1,4 +1,7 @@ | |||||||
|  | #include <sys/stat.h> | ||||||
|  | #include <sys/types.h> | ||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
|  | #include <poll.h> | ||||||
| #include <unistd.h> | #include <unistd.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| #include "test.h" | #include "test.h" | ||||||
| @ -67,6 +70,44 @@ int test_dev_urandom() { | |||||||
|     return 0; |     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() { | int test_dev_arandom() { | ||||||
|     if (check_file_readable("/dev/arandom")) { |     if (check_file_readable("/dev/arandom")) { | ||||||
|         THROW_ERROR("failed to read from /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_zero), | ||||||
|     TEST_CASE(test_dev_random), |     TEST_CASE(test_dev_random), | ||||||
|     TEST_CASE(test_dev_urandom), |     TEST_CASE(test_dev_urandom), | ||||||
|  |     TEST_CASE(test_dev_urandom_fstat), | ||||||
|  |     TEST_CASE(test_dev_urandom_poll), | ||||||
|     TEST_CASE(test_dev_arandom), |     TEST_CASE(test_dev_arandom), | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user