Skip to content

Commit e743336

Browse files
committed
update readlink to return the path instead of mangling the buffer
1 parent ea10209 commit e743336

File tree

3 files changed

+19
-35
lines changed

3 files changed

+19
-35
lines changed

src/fcntl.rs

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
use {Error, Result, NixPath};
1+
use {Result, NixPath};
22
use errno::Errno;
33
use libc::{self, c_int, c_uint, c_char, size_t, ssize_t};
44
use sys::stat::Mode;
55
use std::os::raw;
66
use std::os::unix::io::RawFd;
7-
use std::ffi::OsStr;
8-
use std::os::unix::ffi::OsStrExt;
7+
use std::ffi::OsString;
8+
use std::os::unix::ffi::OsStringExt;
99

1010
#[cfg(any(target_os = "android", target_os = "linux"))]
1111
use std::ptr; // For splice and copy_file_range
@@ -177,36 +177,33 @@ pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(old_dirfd: Option<Ra
177177
Errno::result(res).map(drop)
178178
}
179179

180-
fn wrap_readlink_result(buffer: &mut[u8], res: ssize_t) -> Result<&OsStr> {
180+
fn wrap_readlink_result(v: &mut Vec<u8>, res: ssize_t) -> Result<OsString> {
181181
match Errno::result(res) {
182182
Err(err) => Err(err),
183183
Ok(len) => {
184-
if len < 0 {
185-
Err(Error::Sys(Errno::EINVAL))
186-
} else if (len as usize) > buffer.len() {
187-
Err(Error::Sys(Errno::ENAMETOOLONG))
188-
} else {
189-
Ok(OsStr::from_bytes(&buffer[..(len as usize)]))
190-
}
184+
unsafe { v.set_len(len as usize) }
185+
Ok(OsString::from_vec(v.to_vec()))
191186
}
192187
}
193188
}
194189

195-
pub fn readlink<'a, P: ?Sized + NixPath>(path: &P, buffer: &'a mut [u8]) -> Result<&'a OsStr> {
190+
pub fn readlink<'a, P: ?Sized + NixPath>(path: &P) -> Result<OsString> {
191+
let mut v = vec![0u8; libc::PATH_MAX as usize];
196192
let res = path.with_nix_path(|cstr| {
197-
unsafe { libc::readlink(cstr.as_ptr(), buffer.as_mut_ptr() as *mut c_char, buffer.len() as size_t) }
193+
unsafe { libc::readlink(cstr.as_ptr(), v.as_mut_ptr() as *mut c_char, v.len() as size_t) }
198194
})?;
199-
200-
wrap_readlink_result(buffer, res)
195+
196+
wrap_readlink_result(&mut v, res)
201197
}
202198

203199

204-
pub fn readlinkat<'a, P: ?Sized + NixPath>(dirfd: RawFd, path: &P, buffer: &'a mut [u8]) -> Result<&'a OsStr> {
200+
pub fn readlinkat<'a, P: ?Sized + NixPath>(dirfd: RawFd, path: &P) -> Result<OsString> {
201+
let mut v = vec![0u8; libc::PATH_MAX as usize];
205202
let res = path.with_nix_path(|cstr| {
206-
unsafe { libc::readlinkat(dirfd, cstr.as_ptr(), buffer.as_mut_ptr() as *mut c_char, buffer.len() as size_t) }
203+
unsafe { libc::readlinkat(dirfd, cstr.as_ptr(), v.as_mut_ptr() as *mut c_char, v.len() as size_t) }
207204
})?;
208205

209-
wrap_readlink_result(buffer, res)
206+
wrap_readlink_result(&mut v, res)
210207
}
211208

212209
/// Computes the raw fd consumed by a function of the form `*at`.

test/test_fcntl.rs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,8 @@ fn test_readlink() {
5858
Mode::empty()).unwrap();
5959
let expected_dir = src.to_str().unwrap();
6060

61-
// When the size of the buffer is bigger than the expected directory length
62-
let mut buf = vec![0; src.to_str().unwrap().len() + 1];
63-
assert_eq!(readlink(&dst, &mut buf).unwrap().to_str().unwrap(), expected_dir);
64-
assert_eq!(readlinkat(dirfd, "b", &mut buf).unwrap().to_str().unwrap(), expected_dir);
65-
66-
// When the size of the buffer is equal to the expected directory length
67-
let mut exact_buf = vec![0; src.to_str().unwrap().len()];
68-
assert_eq!(readlink(&dst, &mut exact_buf).unwrap().to_str().unwrap(), expected_dir);
69-
assert_eq!(readlinkat(dirfd, "b", &mut exact_buf).unwrap().to_str().unwrap(), expected_dir);
70-
71-
// When the size of the buffer is smaller than the expected directory length
72-
let mut small_buf = vec![0;0];
73-
assert_eq!(readlink(&dst, &mut small_buf).unwrap().to_str().unwrap(), "");
74-
assert_eq!(readlinkat(dirfd, "b", &mut small_buf).unwrap().to_str().unwrap(), "");
61+
assert_eq!(readlink(&dst).unwrap().to_str().unwrap(), expected_dir);
62+
assert_eq!(readlinkat(dirfd, "b").unwrap().to_str().unwrap(), expected_dir);
7563

7664
}
7765

test/test_unistd.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -576,14 +576,13 @@ fn test_canceling_alarm() {
576576

577577
#[test]
578578
fn test_symlinkat() {
579-
let mut buf = [0; 1024];
580579
let tempdir = tempfile::tempdir().unwrap();
581580

582581
let target = tempdir.path().join("a");
583582
let linkpath = tempdir.path().join("b");
584583
symlinkat(&target, None, &linkpath).unwrap();
585584
assert_eq!(
586-
readlink(&linkpath, &mut buf).unwrap().to_str().unwrap(),
585+
readlink(&linkpath).unwrap().to_str().unwrap(),
587586
target.to_str().unwrap()
588587
);
589588

@@ -592,7 +591,7 @@ fn test_symlinkat() {
592591
let linkpath = "d";
593592
symlinkat(target, Some(dirfd), linkpath).unwrap();
594593
assert_eq!(
595-
readlink(&tempdir.path().join(linkpath), &mut buf)
594+
readlink(&tempdir.path().join(linkpath))
596595
.unwrap()
597596
.to_str()
598597
.unwrap(),

0 commit comments

Comments
 (0)