Skip to content

Commit 4e9dd25

Browse files
committed
Merge #729
729: Refactor statvfs module r=Susurrus * Use upstream libc FFI declarations and constants * Use more Rust-y interface of returning entire struct versus passing it as an argument to (f)statvfs. * Replace field accesses with accessor methods * Flatten vfs module into parent * Remove all non-libc-based interfaces for working with the statvfs struct
2 parents 087aece + 6ae3f31 commit 4e9dd25

File tree

2 files changed

+124
-141
lines changed

2 files changed

+124
-141
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
2323
([#647](https://github.com/nix-rust/nix/pull/647))
2424
- Exposed `unistd::setresuid` and `unistd::setresgid` on FreeBSD and OpenBSD
2525
([#721](https://github.com/nix-rust/nix/pull/721))
26+
- Refactored the `statvfs` module removing extraneous API functions and the
27+
`statvfs::vfs` module. Additionally `(f)statvfs()` now return the struct
28+
directly. And the returned `Statvfs` struct now exposes its data through
29+
accessor methods. ([#729](https://github.com/nix-rust/nix/pull/729))
2630

2731
# Fixed
2832
- Fix compilation and tests for OpenBSD targets

src/sys/statvfs.rs

+120-141
Original file line numberDiff line numberDiff line change
@@ -1,161 +1,142 @@
1-
//! FFI for statvfs functions
1+
//! Get filesystem statistics
22
//!
3-
//! See the `vfs::Statvfs` struct for some rusty wrappers
3+
//! See [the man pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html)
4+
//! for more details.
5+
use std::mem;
6+
use std::os::unix::io::AsRawFd;
7+
8+
use libc::{self, c_ulong};
49

510
use {Errno, Result, NixPath};
6-
use std::os::unix::io::AsRawFd;
711

8-
pub mod vfs {
9-
//! Structs related to the `statvfs` and `fstatvfs` functions
10-
//!
11-
//! The `Statvfs` struct has some wrappers methods around the `statvfs` and
12-
//! `fstatvfs` calls.
13-
14-
use libc::{c_ulong,c_int};
15-
use std::os::unix::io::AsRawFd;
16-
use {Result, NixPath};
17-
18-
use super::{statvfs, fstatvfs};
19-
20-
bitflags!(
21-
/// Mount Flags
22-
#[repr(C)]
23-
#[derive(Default)]
24-
pub struct FsFlags: c_ulong {
25-
/// Read Only
26-
const RDONLY = 1;
27-
/// Do not allow the set-uid bits to have an effect
28-
const NOSUID = 2;
29-
/// Do not interpret character or block-special devices
30-
const NODEV = 4;
31-
/// Do not allow execution of binaries on the filesystem
32-
const NOEXEC = 8;
33-
/// All IO should be done synchronously
34-
const SYNCHRONOUS = 16;
35-
/// Allow mandatory locks on the filesystem
36-
const MANDLOCK = 64;
37-
const WRITE = 128;
38-
const APPEND = 256;
39-
const IMMUTABLE = 512;
40-
/// Do not update access times on files
41-
const NOATIME = 1024;
42-
/// Do not update access times on files
43-
const NODIRATIME = 2048;
44-
/// Update access time relative to modify/change time
45-
const RELATIME = 4096;
46-
}
47-
);
48-
49-
/// The posix statvfs struct
50-
///
51-
/// http://linux.die.net/man/2/statvfs
12+
bitflags!(
13+
/// File system mount Flags
5214
#[repr(C)]
53-
#[derive(Debug,Copy,Clone)]
54-
pub struct Statvfs {
55-
/// Filesystem block size. This is the value that will lead to
56-
/// most efficient use of the filesystem
57-
pub f_bsize: c_ulong,
58-
/// Fragment Size -- actual minimum unit of allocation on this
59-
/// filesystem
60-
pub f_frsize: c_ulong,
61-
/// Total number of blocks on the filesystem
62-
pub f_blocks: u64,
63-
/// Number of unused blocks on the filesystem, including those
64-
/// reserved for root
65-
pub f_bfree: u64,
66-
/// Number of blocks available to non-root users
67-
pub f_bavail: u64,
68-
/// Total number of inodes available on the filesystem
69-
pub f_files: u64,
70-
/// Number of inodes available on the filesystem
71-
pub f_ffree: u64,
72-
/// Number of inodes available to non-root users
73-
pub f_favail: u64,
74-
/// File System ID
75-
pub f_fsid: c_ulong,
76-
/// Mount Flags
77-
pub f_flag: FsFlags,
78-
/// Maximum filename length
79-
pub f_namemax: c_ulong,
80-
/// Reserved extra space, OS-dependent
81-
f_spare: [c_int; 6],
82-
}
83-
84-
impl Statvfs {
85-
/// Create a new `Statvfs` object and fill it with information about
86-
/// the mount that contains `path`
87-
pub fn for_path<P: ?Sized + NixPath>(path: &P) -> Result<Statvfs> {
88-
let mut stat = Statvfs::default();
89-
let res = statvfs(path, &mut stat);
90-
res.map(|_| stat)
91-
}
92-
93-
/// Replace information in this struct with information about `path`
94-
pub fn update_with_path<P: ?Sized + NixPath>(&mut self, path: &P) -> Result<()> {
95-
statvfs(path, self)
96-
}
97-
98-
/// Create a new `Statvfs` object and fill it with information from fd
99-
pub fn for_fd<T: AsRawFd>(fd: &T) -> Result<Statvfs> {
100-
let mut stat = Statvfs::default();
101-
let res = fstatvfs(fd, &mut stat);
102-
res.map(|_| stat)
103-
}
104-
105-
/// Replace information in this struct with information about `fd`
106-
pub fn update_with_fd<T: AsRawFd>(&mut self, fd: &T) -> Result<()> {
107-
fstatvfs(fd, self)
108-
}
109-
}
110-
111-
impl Default for Statvfs {
112-
/// Create a statvfs object initialized to all zeros
113-
fn default() -> Self {
114-
Statvfs {
115-
f_bsize: 0,
116-
f_frsize: 0,
117-
f_blocks: 0,
118-
f_bfree: 0,
119-
f_bavail: 0,
120-
f_files: 0,
121-
f_ffree: 0,
122-
f_favail: 0,
123-
f_fsid: 0,
124-
f_flag: FsFlags::default(),
125-
f_namemax: 0,
126-
f_spare: [0, 0, 0, 0, 0, 0],
127-
}
128-
}
15+
#[derive(Default)]
16+
pub struct FsFlags: c_ulong {
17+
/// Read Only
18+
const RDONLY = libc::ST_RDONLY;
19+
/// Do not allow the set-uid bits to have an effect
20+
const NOSUID = libc::ST_NOSUID;
21+
/// Do not interpret character or block-special devices
22+
#[cfg(any(target_os = "android", target_os = "linux"))]
23+
const NODEV = libc::ST_NODEV;
24+
/// Do not allow execution of binaries on the filesystem
25+
#[cfg(any(target_os = "android", target_os = "linux"))]
26+
const NOEXEC = libc::ST_NOEXEC;
27+
/// All IO should be done synchronously
28+
#[cfg(any(target_os = "android", target_os = "linux"))]
29+
const SYNCHRONOUS = libc::ST_SYNCHRONOUS;
30+
/// Allow mandatory locks on the filesystem
31+
#[cfg(any(target_os = "android", target_os = "linux"))]
32+
const MANDLOCK = libc::ST_MANDLOCK;
33+
/// Write on file/directory/symlink
34+
#[cfg(any(target_os = "android", target_os = "linux"))]
35+
const WRITE = libc::ST_WRITE;
36+
/// Append-only file
37+
#[cfg(any(target_os = "android", target_os = "linux"))]
38+
const APPEND = libc::ST_APPEND;
39+
/// Immutable file
40+
#[cfg(any(target_os = "android", target_os = "linux"))]
41+
const IMMUTABLE = libc::ST_IMMUTABLE;
42+
/// Do not update access times on files
43+
#[cfg(any(target_os = "android", target_os = "linux"))]
44+
const NOATIME = libc::ST_NOATIME;
45+
/// Do not update access times on files
46+
#[cfg(any(target_os = "android", target_os = "linux"))]
47+
const NODIRATIME = libc::ST_NODIRATIME;
48+
/// Update access time relative to modify/change time
49+
#[cfg(any(target_os = "android", all(target_os = "linux", not(target_env = "musl"))))]
50+
const RELATIME = libc::ST_RELATIME;
51+
}
52+
);
53+
54+
/// Wrapper around the POSIX `statvfs` struct
55+
///
56+
/// For more information see the [`statvfs(3)` man pages](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_statvfs.h.html).
57+
// FIXME: Replace with repr(transparent)
58+
#[repr(C)]
59+
pub struct Statvfs(libc::statvfs);
60+
61+
impl Statvfs {
62+
/// get the file system block size
63+
pub fn block_size(&self) -> libc::c_ulong {
64+
self.0.f_bsize
12965
}
130-
}
13166

132-
mod ffi {
133-
use libc::{c_char, c_int};
134-
use sys::statvfs::vfs;
67+
/// Get the fundamental file system block size
68+
pub fn fragment_size(&self) -> libc::c_ulong {
69+
self.0.f_frsize
70+
}
13571

136-
extern {
137-
pub fn statvfs(path: * const c_char, buf: *mut vfs::Statvfs) -> c_int;
138-
pub fn fstatvfs(fd: c_int, buf: *mut vfs::Statvfs) -> c_int;
72+
/// Get the number of blocks.
73+
///
74+
/// Units are in units of `fragment_size()`
75+
pub fn blocks(&self) -> libc::fsblkcnt_t {
76+
self.0.f_blocks
77+
}
78+
79+
/// Get the number of free blocks in the file system
80+
pub fn blocks_free(&self) -> libc::fsblkcnt_t {
81+
self.0.f_bfree
13982
}
83+
84+
/// Get the number of free blocks for unprivileged users
85+
pub fn blocks_available(&self) -> libc::fsblkcnt_t {
86+
self.0.f_bavail
87+
}
88+
89+
/// Get the total number of file inodes
90+
pub fn files(&self) -> libc::fsfilcnt_t {
91+
self.0.f_files
92+
}
93+
94+
/// Get the number of free file inodes
95+
pub fn files_free(&self) -> libc::fsfilcnt_t {
96+
self.0.f_ffree
97+
}
98+
99+
/// Get the number of free file inodes for unprivileged users
100+
pub fn files_available(&self) -> libc::fsfilcnt_t {
101+
self.0.f_favail
102+
}
103+
104+
/// Get the file system id
105+
pub fn filesystem_id(&self) -> c_ulong {
106+
self.0.f_fsid
107+
}
108+
109+
/// Get the mount flags
110+
pub fn flags(&self) -> FsFlags {
111+
FsFlags::from_bits_truncate(self.0.f_flag)
112+
}
113+
114+
/// Get the maximum filename length
115+
pub fn name_max(&self) -> libc::c_ulong {
116+
self.0.f_namemax
117+
}
118+
140119
}
141120

142-
/// Fill an existing `Statvfs` object with information about the `path`
143-
pub fn statvfs<P: ?Sized + NixPath>(path: &P, stat: &mut vfs::Statvfs) -> Result<()> {
121+
/// Return a `Statvfs` object with information about the `path`
122+
pub fn statvfs<P: ?Sized + NixPath>(path: &P) -> Result<Statvfs> {
144123
unsafe {
145124
Errno::clear();
125+
let mut stat: Statvfs = mem::uninitialized();
146126
let res = try!(
147-
path.with_nix_path(|path| ffi::statvfs(path.as_ptr(), stat))
127+
path.with_nix_path(|path| libc::statvfs(path.as_ptr(), &mut stat.0))
148128
);
149129

150-
Errno::result(res).map(drop)
130+
Errno::result(res).map(|_| stat)
151131
}
152132
}
153133

154-
/// Fill an existing `Statvfs` object with information about `fd`
155-
pub fn fstatvfs<T: AsRawFd>(fd: &T, stat: &mut vfs::Statvfs) -> Result<()> {
134+
/// Return a `Statvfs` object with information about `fd`
135+
pub fn fstatvfs<T: AsRawFd>(fd: &T) -> Result<Statvfs> {
156136
unsafe {
157137
Errno::clear();
158-
Errno::result(ffi::fstatvfs(fd.as_raw_fd(), stat)).map(drop)
138+
let mut stat: Statvfs = mem::uninitialized();
139+
Errno::result(libc::fstatvfs(fd.as_raw_fd(), &mut stat.0)).map(|_| stat)
159140
}
160141
}
161142

@@ -166,14 +147,12 @@ mod test {
166147

167148
#[test]
168149
fn statvfs_call() {
169-
let mut stat = vfs::Statvfs::default();
170-
statvfs("/".as_bytes(), &mut stat).unwrap()
150+
statvfs("/".as_bytes()).unwrap();
171151
}
172152

173153
#[test]
174154
fn fstatvfs_call() {
175-
let mut stat = vfs::Statvfs::default();
176155
let root = File::open("/").unwrap();
177-
fstatvfs(&root, &mut stat).unwrap()
156+
fstatvfs(&root).unwrap();
178157
}
179158
}

0 commit comments

Comments
 (0)