Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce the reliance on PATH_MAX #27930

Merged
merged 3 commits into from
Aug 27, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions src/liblibc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3920,6 +3920,8 @@ pub mod consts {
pub const _SC_XBS5_ILP32_OFFBIG : c_int = 126;
pub const _SC_XBS5_LPBIG_OFFBIG : c_int = 128;

pub const _PC_NAME_MAX: c_int = 3;
pub const _PC_PATH_MAX: c_int = 4;
}
#[cfg(target_os = "nacl")]
pub mod sysconf {
Expand All @@ -3928,6 +3930,9 @@ pub mod consts {
pub static _SC_SENDMSG_MAX_SIZE : c_int = 0;
pub static _SC_NPROCESSORS_ONLN : c_int = 1;
pub static _SC_PAGESIZE : c_int = 2;

pub const _PC_NAME_MAX: c_int = 3;
pub const _PC_PATH_MAX: c_int = 4;
}

#[cfg(target_os = "android")]
Expand Down Expand Up @@ -3963,6 +3968,9 @@ pub mod consts {
pub const _SC_STREAM_MAX : c_int = 27;
pub const _SC_TZNAME_MAX : c_int = 28;
pub const _SC_PAGESIZE : c_int = 39;

pub const _PC_NAME_MAX: c_int = 4;
pub const _PC_PATH_MAX: c_int = 5;
}
}

Expand Down Expand Up @@ -4433,6 +4441,9 @@ pub mod consts {
pub const _SC_SEM_VALUE_MAX : c_int = 50;
pub const _SC_SIGQUEUE_MAX : c_int = 51;
pub const _SC_TIMER_MAX : c_int = 52;

pub const _PC_NAME_MAX: c_int = 4;
pub const _PC_PATH_MAX: c_int = 5;
}
}

Expand Down Expand Up @@ -4868,6 +4879,9 @@ pub mod consts {
pub const _SC_SYNCHRONIZED_IO : c_int = 75;
pub const _SC_TIMER_MAX : c_int = 93;
pub const _SC_TIMERS : c_int = 94;

pub const _PC_NAME_MAX: c_int = 4;
pub const _PC_PATH_MAX: c_int = 5;
}
}

Expand Down Expand Up @@ -5379,6 +5393,9 @@ pub mod consts {
pub const _SC_TRACE_SYS_MAX : c_int = 129;
pub const _SC_TRACE_USER_EVENT_MAX : c_int = 130;
pub const _SC_PASS_MAX : c_int = 131;

pub const _PC_NAME_MAX: c_int = 4;
pub const _PC_PATH_MAX: c_int = 5;
}
}
}
Expand Down Expand Up @@ -5835,8 +5852,6 @@ pub mod funcs {
use types::os::arch::posix88::{gid_t, off_t, pid_t};
use types::os::arch::posix88::{ssize_t, uid_t};

pub const _PC_NAME_MAX: c_int = 4;

#[cfg(not(target_os = "nacl"))]
extern {
pub fn access(path: *const c_char, amode: c_int) -> c_int;
Expand Down
45 changes: 30 additions & 15 deletions src/libstd/sys/unix/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,13 +376,19 @@ impl fmt::Debug for File {

#[cfg(target_os = "macos")]
fn get_path(fd: c_int) -> Option<PathBuf> {
// FIXME: The use of PATH_MAX is generally not encouraged, but it
// is inevitable in this case because OS X defines `fcntl` with
// `F_GETPATH` in terms of `MAXPATHLEN`, and there are no
// alternatives. If a better method is invented, it should be used
// instead.
let mut buf = vec![0;libc::PATH_MAX as usize];
let n = unsafe { libc::fcntl(fd, libc::F_GETPATH, buf.as_ptr()) };
if n == -1 {
return None;
}
let l = buf.iter().position(|&c| c == 0).unwrap();
buf.truncate(l as usize);
buf.shrink_to_fit();
Some(PathBuf::from(OsString::from_vec(buf)))
}

Expand Down Expand Up @@ -466,18 +472,27 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
pub fn readlink(p: &Path) -> io::Result<PathBuf> {
let c_path = try!(cstr(p));
let p = c_path.as_ptr();
let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) };
if len < 0 {
len = 1024; // FIXME: read PATH_MAX from C ffi?
}
let mut buf: Vec<u8> = Vec::with_capacity(len as usize);
unsafe {
let n = try!(cvt({
libc::readlink(p, buf.as_ptr() as *mut c_char, len as size_t)
}));
buf.set_len(n as usize);

let mut buf = Vec::with_capacity(256);

loop {
let buf_read = try!(cvt(unsafe {
libc::readlink(p, buf.as_mut_ptr() as *mut _, buf.capacity() as libc::size_t)
})) as usize;

unsafe { buf.set_len(buf_read); }

if buf_read != buf.capacity() {
buf.shrink_to_fit();

return Ok(PathBuf::from(OsString::from_vec(buf)));
}

// Trigger the internal buffer resizing logic of `Vec` by requiring
// more space than the current capacity. The length is guaranteed to be
// the same as the capacity due to the if statement above.
buf.reserve(1);
}
Ok(PathBuf::from(OsString::from_vec(buf)))
}

pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
Expand Down Expand Up @@ -514,15 +529,15 @@ pub fn lstat(p: &Path) -> io::Result<FileAttr> {

pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
let path = try!(CString::new(p.as_os_str().as_bytes()));
let mut buf = vec![0u8; 16 * 1024];
let buf;
unsafe {
let r = c::realpath(path.as_ptr(), buf.as_mut_ptr() as *mut _);
let r = c::realpath(path.as_ptr(), ptr::null_mut());
if r.is_null() {
return Err(io::Error::last_os_error())
}
buf = CStr::from_ptr(r).to_bytes().to_vec();
libc::free(r as *mut _);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I'm a bit too pedantic, but do you think it might be a good idea to place an RAII guard on this? I believe CStr::from_ptr(r).to_bytes().to_vec() will not panic currently, but if it changes the behavior in the future (e.g. to_vec() panics rather than aborting in case of OOM), the manually allocated memory will be leaked. Do we have to be concerned about this kind of situations? How much overhead an RAII guard incur?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An RAII guard shouldn't have much overhead, but it's not really necessary so it's fine to not worry about this.

}
let p = buf.iter().position(|i| *i == 0).unwrap();
buf.truncate(p);
Ok(PathBuf::from(OsString::from_vec(buf)))
}

Expand Down
12 changes: 7 additions & 5 deletions src/libstd/sys/unix/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ use sys::c;
use sys::fd;
use vec;

const GETCWD_BUF_BYTES: usize = 2048;
const TMPBUF_SZ: usize = 128;

/// Returns the platform-specific value of errno
Expand Down Expand Up @@ -94,11 +93,9 @@ pub fn error_string(errno: i32) -> String {
}

pub fn getcwd() -> io::Result<PathBuf> {
let mut buf = Vec::new();
let mut n = GETCWD_BUF_BYTES;
let mut buf = Vec::with_capacity(512);
loop {
unsafe {
buf.reserve(n);
let ptr = buf.as_mut_ptr() as *mut libc::c_char;
if !libc::getcwd(ptr, buf.capacity() as libc::size_t).is_null() {
let len = CStr::from_ptr(buf.as_ptr() as *const libc::c_char).to_bytes().len();
Expand All @@ -111,7 +108,12 @@ pub fn getcwd() -> io::Result<PathBuf> {
return Err(error);
}
}
n *= 2;

// Trigger the internal buffer resizing logic of `Vec` by requiring
// more space than the current capacity.
let cap = buf.capacity();
buf.set_len(cap);
buf.reserve(1);
}
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/rt/rust_builtin.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,11 @@ const char * rust_current_exe()
char **paths;
size_t sz;
int i;
char buf[2*PATH_MAX], exe[2*PATH_MAX];
/* If `PATH_MAX` is defined on the platform, `realpath` will truncate the
* resolved path up to `PATH_MAX`. While this can make the resolution fail if
* the executable is placed in a deep path, the usage of a buffer whose
* length depends on `PATH_MAX` is still memory safe. */
char buf[2*PATH_MAX], exe[PATH_MAX];

if (self != NULL)
return self;
Expand Down