summary refs log tree commit diff
path: root/sys_util/src/lib.rs
diff options
context:
space:
mode:
authorDaniel Verkamp <dverkamp@chromium.org>2018-08-17 09:05:14 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-09-05 01:25:49 -0700
commit0e8f6fa96e454f8db36787eda91327e32e1b159a (patch)
tree5b3915d3d40ff885e6423d760726d1a3aadf30da /sys_util/src/lib.rs
parentcaa2e5a4ac45c5e107b6802db99c158083321bc4 (diff)
downloadcrosvm-0e8f6fa96e454f8db36787eda91327e32e1b159a.tar
crosvm-0e8f6fa96e454f8db36787eda91327e32e1b159a.tar.gz
crosvm-0e8f6fa96e454f8db36787eda91327e32e1b159a.tar.bz2
crosvm-0e8f6fa96e454f8db36787eda91327e32e1b159a.tar.lz
crosvm-0e8f6fa96e454f8db36787eda91327e32e1b159a.tar.xz
crosvm-0e8f6fa96e454f8db36787eda91327e32e1b159a.tar.zst
crosvm-0e8f6fa96e454f8db36787eda91327e32e1b159a.zip
sys_util: add safe wrapper for fallocate()
BUG=chromium:850998
TEST=None

Change-Id: I1b6864f7d508cf7f24248a8cc9783af2d8b00891
Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1187016
Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com>
Reviewed-by: Stephen Barber <smbarber@chromium.org>
Diffstat (limited to 'sys_util/src/lib.rs')
-rw-r--r--sys_util/src/lib.rs45
1 files changed, 45 insertions, 0 deletions
diff --git a/sys_util/src/lib.rs b/sys_util/src/lib.rs
index 30b293d..1d0ff1a 100644
--- a/sys_util/src/lib.rs
+++ b/sys_util/src/lib.rs
@@ -151,6 +151,51 @@ pub fn flock(file: &AsRawFd, op: FlockOperation, nonblocking: bool) -> Result<()
     }
 }
 
+/// The operation to perform with `fallocate`.
+pub enum FallocateMode {
+    PunchHole,
+    ZeroRange,
+}
+
+/// Safe wrapper for `fallocate()`.
+pub fn fallocate(
+    file: &AsRawFd,
+    mode: FallocateMode,
+    keep_size: bool,
+    offset: u64,
+    len: u64
+) -> Result<()> {
+    let offset = if offset > libc::off_t::max_value() as u64 {
+        return Err(Error::new(libc::EINVAL));
+    } else {
+        offset as libc::off_t
+    };
+
+    let len = if len > libc::off_t::max_value() as u64 {
+        return Err(Error::new(libc::EINVAL));
+    } else {
+        len as libc::off_t
+    };
+
+    let mut mode = match mode {
+        FallocateMode::PunchHole => libc::FALLOC_FL_PUNCH_HOLE,
+        FallocateMode::ZeroRange => libc::FALLOC_FL_ZERO_RANGE,
+    };
+
+    if keep_size {
+        mode |= libc::FALLOC_FL_KEEP_SIZE;
+    }
+
+    // Safe since we pass in a valid fd and fallocate mode, validate offset and len,
+    // and check the return value.
+    let ret = unsafe { libc::fallocate(file.as_raw_fd(), mode, offset, len) };
+    if ret < 0 {
+        errno_result()
+    } else {
+        Ok(())
+    }
+}
+
 /// Reaps a child process that has terminated.
 ///
 /// Returns `Ok(pid)` where `pid` is the process that was reaped or `Ok(0)` if none of the children