Skip to content

Commit 1bca805

Browse files
authored
Merge branch 'master' into timerfd-file-leak
2 parents c33fa74 + 661738c commit 1bca805

16 files changed

+251
-161
lines changed

.cirrus.yml

+4
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ task:
157157
- name: Linux s390x
158158
env:
159159
TARGET: s390x-unknown-linux-gnu
160+
- name: Linux x32
161+
env:
162+
TARGET: x86_64-unknown-linux-gnux32
163+
CHECK_TESTS: true
160164
- name: NetBSD x86_64
161165
env:
162166
TARGET: x86_64-unknown-netbsd

CHANGELOG.md

+14
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,24 @@ This project adheres to [Semantic Versioning](http://semver.org/).
55

66
## [Unreleased] - ReleaseDate
77
### Added
8+
9+
- Added a `passwd` field to `Group` (#[1338](https://github.com/nix-rust/nix/pull/1338))
810
- Added `mremap` (#[1306](https://github.com/nix-rust/nix/pull/1306))
911
- Added `personality` (#[1331](https://github.com/nix-rust/nix/pull/1331))
1012
- Added limited Fuchsia support (#[1285](https://github.com/nix-rust/nix/pull/1285))
1113
- Added `getpeereid` (#[1342](https://github.com/nix-rust/nix/pull/1342))
14+
- Implemented `IntoIterator` for `Dir`
15+
(#[1333](https://github.com/nix-rust/nix/pull/1333)).
16+
### Changed
17+
1218
### Fixed
1319
- `TimerFd` now closes the underlying fd on drop.
1420
([#1381](https://github.com/nix-rust/nix/pull/1381))
21+
- Define `*_MAGIC` filesystem constants on Linux s390x
22+
(#[1372](https://github.com/nix-rust/nix/pull/1372))
23+
- mqueue, sysinfo, timespec, statfs, test_ptrace_syscall() on x32
24+
(#[1366](https://github.com/nix-rust/nix/pull/1366))
25+
1526
### Changed
1627

1728
- Minimum supported Rust version is now 1.40.0.
@@ -25,6 +36,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
2536

2637
### Removed
2738

39+
- `Dir`, `SignalFd`, and `PtyMaster` are no longer `Clone`.
40+
(#[1382](https://github.com/nix-rust/nix/pull/1382))
41+
2842
- Removed `SockLevel`, which hasn't been used for a few years
2943
(#[1362](https://github.com/nix-rust/nix/pull/1362))
3044
- Removed both `Copy` and `Clone` from `TimerFd`.

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ targets = [
3131
]
3232

3333
[dependencies]
34-
libc = { version = "0.2.78", features = [ "extra_traits" ] }
34+
libc = { version = "0.2.82", features = [ "extra_traits" ] }
3535
bitflags = "1.1"
3636
cfg-if = "1.0"
3737

@@ -46,7 +46,7 @@ tempfile = "3.0.5"
4646
semver = "0.9.0"
4747

4848
[target.'cfg(any(target_os = "android", target_os = "linux"))'.dev-dependencies]
49-
caps = "0.3.1"
49+
caps = "0.5.1"
5050

5151
[target.'cfg(target_os = "freebsd")'.dev-dependencies]
5252
sysctl = "0.1"

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ Tier 2:
8383
Tier 3:
8484
* x86_64-fuchsia
8585
* x86_64-unknown-redox
86+
* x86_64-unknown-linux-gnux32
8687

8788
## Usage
8889

src/dir.rs

+65-21
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use libc::{dirent, readdir_r};
2525
/// * returns entries for `.` (current directory) and `..` (parent directory).
2626
/// * returns entries' names as a `CStr` (no allocation or conversion beyond whatever libc
2727
/// does).
28-
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
28+
#[derive(Debug, Eq, Hash, PartialEq)]
2929
pub struct Dir(
3030
ptr::NonNull<libc::DIR>
3131
);
@@ -85,7 +85,32 @@ impl AsRawFd for Dir {
8585

8686
impl Drop for Dir {
8787
fn drop(&mut self) {
88-
unsafe { libc::closedir(self.0.as_ptr()) };
88+
let e = Errno::result(unsafe { libc::closedir(self.0.as_ptr()) });
89+
if !std::thread::panicking() && e == Err(Error::Sys(Errno::EBADF)) {
90+
panic!("Closing an invalid file descriptor!");
91+
};
92+
}
93+
}
94+
95+
fn next(dir: &mut Dir) -> Option<Result<Entry>> {
96+
unsafe {
97+
// Note: POSIX specifies that portable applications should dynamically allocate a
98+
// buffer with room for a `d_name` field of size `pathconf(..., _PC_NAME_MAX)` plus 1
99+
// for the NUL byte. It doesn't look like the std library does this; it just uses
100+
// fixed-sized buffers (and libc's dirent seems to be sized so this is appropriate).
101+
// Probably fine here too then.
102+
let mut ent = std::mem::MaybeUninit::<dirent>::uninit();
103+
let mut result = ptr::null_mut();
104+
if let Err(e) = Errno::result(
105+
readdir_r(dir.0.as_ptr(), ent.as_mut_ptr(), &mut result))
106+
{
107+
return Some(Err(e));
108+
}
109+
if result.is_null() {
110+
return None;
111+
}
112+
assert_eq!(result, ent.as_mut_ptr());
113+
Some(Ok(Entry(ent.assume_init())))
89114
}
90115
}
91116

@@ -96,25 +121,7 @@ impl<'d> Iterator for Iter<'d> {
96121
type Item = Result<Entry>;
97122

98123
fn next(&mut self) -> Option<Self::Item> {
99-
unsafe {
100-
// Note: POSIX specifies that portable applications should dynamically allocate a
101-
// buffer with room for a `d_name` field of size `pathconf(..., _PC_NAME_MAX)` plus 1
102-
// for the NUL byte. It doesn't look like the std library does this; it just uses
103-
// fixed-sized buffers (and libc's dirent seems to be sized so this is appropriate).
104-
// Probably fine here too then.
105-
let mut ent = std::mem::MaybeUninit::<dirent>::uninit();
106-
let mut result = ptr::null_mut();
107-
if let Err(e) = Errno::result(
108-
readdir_r((self.0).0.as_ptr(), ent.as_mut_ptr(), &mut result))
109-
{
110-
return Some(Err(e));
111-
}
112-
if result.is_null() {
113-
return None;
114-
}
115-
assert_eq!(result, ent.as_mut_ptr());
116-
Some(Ok(Entry(ent.assume_init())))
117-
}
124+
next(self.0)
118125
}
119126
}
120127

@@ -124,6 +131,43 @@ impl<'d> Drop for Iter<'d> {
124131
}
125132
}
126133

134+
/// The return type of [Dir::into_iter]
135+
#[derive(Debug, Eq, Hash, PartialEq)]
136+
pub struct OwningIter(Dir);
137+
138+
impl Iterator for OwningIter {
139+
type Item = Result<Entry>;
140+
141+
fn next(&mut self) -> Option<Self::Item> {
142+
next(&mut self.0)
143+
}
144+
}
145+
146+
impl IntoIterator for Dir {
147+
type Item = Result<Entry>;
148+
type IntoIter = OwningIter;
149+
150+
/// Creates a owning iterator, that is, one that takes ownership of the
151+
/// `Dir`. The `Dir` cannot be used after calling this. This can be useful
152+
/// when you have a function that both creates a `Dir` instance and returns
153+
/// an `Iterator`.
154+
///
155+
/// Example:
156+
///
157+
/// ```
158+
/// use nix::{dir::Dir, fcntl::OFlag, sys::stat::Mode};
159+
/// use std::{iter::Iterator, string::String};
160+
///
161+
/// fn ls_upper(dirname: &str) -> impl Iterator<Item=String> {
162+
/// let d = Dir::open(dirname, OFlag::O_DIRECTORY, Mode::S_IXUSR).unwrap();
163+
/// d.into_iter().map(|x| x.unwrap().file_name().as_ref().to_string_lossy().to_ascii_uppercase())
164+
/// }
165+
/// ```
166+
fn into_iter(self) -> Self::IntoIter {
167+
OwningIter(self)
168+
}
169+
}
170+
127171
/// A directory entry, similar to `std::fs::DirEntry`.
128172
///
129173
/// Note that unlike the std version, this may represent the `.` or `..` entries.

src/mqueue.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
use crate::Result;
66
use crate::errno::Errno;
77

8-
use libc::{self, c_char, c_long, mqd_t, size_t};
8+
use libc::{self, c_char, mqd_t, size_t};
99
use std::ffi::CString;
1010
use crate::sys::stat::Mode;
1111
use std::mem;
@@ -34,11 +34,18 @@ pub struct MqAttr {
3434
mq_attr: libc::mq_attr,
3535
}
3636

37+
// x32 compatibility
38+
// See https://sourceware.org/bugzilla/show_bug.cgi?id=21279
39+
#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
40+
pub type mq_attr_member_t = i64;
41+
#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
42+
pub type mq_attr_member_t = libc::c_long;
43+
3744
impl MqAttr {
38-
pub fn new(mq_flags: c_long,
39-
mq_maxmsg: c_long,
40-
mq_msgsize: c_long,
41-
mq_curmsgs: c_long)
45+
pub fn new(mq_flags: mq_attr_member_t,
46+
mq_maxmsg: mq_attr_member_t,
47+
mq_msgsize: mq_attr_member_t,
48+
mq_curmsgs: mq_attr_member_t)
4249
-> MqAttr
4350
{
4451
let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
@@ -52,7 +59,7 @@ impl MqAttr {
5259
}
5360
}
5461

55-
pub fn flags(&self) -> c_long {
62+
pub fn flags(&self) -> mq_attr_member_t {
5663
self.mq_attr.mq_flags
5764
}
5865
}
@@ -150,7 +157,7 @@ pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result<MqAttr> {
150157
/// Returns the old attributes
151158
pub fn mq_set_nonblock(mqd: mqd_t) -> Result<MqAttr> {
152159
let oldattr = mq_getattr(mqd)?;
153-
let newattr = MqAttr::new(c_long::from(MQ_OFlag::O_NONBLOCK.bits()),
160+
let newattr = MqAttr::new(mq_attr_member_t::from(MQ_OFlag::O_NONBLOCK.bits()),
154161
oldattr.mq_attr.mq_maxmsg,
155162
oldattr.mq_attr.mq_msgsize,
156163
oldattr.mq_attr.mq_curmsgs);

src/pty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub struct ForkptyResult {
4343
/// While this datatype is a thin wrapper around `RawFd`, it enforces that the available PTY
4444
/// functions are given the correct file descriptor. Additionally this type implements `Drop`,
4545
/// so that when it's consumed or goes out of scope, it's automatically cleaned-up.
46-
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
46+
#[derive(Debug, Eq, Hash, PartialEq)]
4747
pub struct PtyMaster(RawFd);
4848

4949
impl AsRawFd for PtyMaster {

src/sys/signalfd.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result<RawFd> {
7979
/// Err(err) => (), // some error happend
8080
/// }
8181
/// ```
82-
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
82+
#[derive(Debug, Eq, Hash, PartialEq)]
8383
pub struct SignalFd(RawFd);
8484

8585
impl SignalFd {
@@ -116,7 +116,10 @@ impl SignalFd {
116116

117117
impl Drop for SignalFd {
118118
fn drop(&mut self) {
119-
let _ = unistd::close(self.0);
119+
let e = unistd::close(self.0);
120+
if !std::thread::panicking() && e == Err(Error::Sys(Errno::EBADF)) {
121+
panic!("Closing an invalid file descriptor!");
122+
};
120123
}
121124
}
122125

0 commit comments

Comments
 (0)