readdir: return error instead of failing on invalid UTF-16
Fixes #15279 Signed-off-by: Peter Atashian <retep998@gmail.com>
This commit is contained in:
parent
82c052794d
commit
d3ec0674bb
@ -249,7 +249,7 @@
|
||||
#[cfg(windows)] pub use types::os::arch::extra::{LARGE_INTEGER, LPVOID, LONG};
|
||||
#[cfg(windows)] pub use types::os::arch::extra::{time64_t, OVERLAPPED, LPCWSTR};
|
||||
#[cfg(windows)] pub use types::os::arch::extra::{LPOVERLAPPED, SIZE_T, LPDWORD};
|
||||
#[cfg(windows)] pub use types::os::arch::extra::{SECURITY_ATTRIBUTES};
|
||||
#[cfg(windows)] pub use types::os::arch::extra::{SECURITY_ATTRIBUTES, WIN32_FIND_DATAW};
|
||||
#[cfg(windows)] pub use funcs::c95::string::{wcslen};
|
||||
#[cfg(windows)] pub use funcs::posix88::stat_::{wstat, wutime, wchmod, wrmdir};
|
||||
#[cfg(windows)] pub use funcs::bsd43::{closesocket};
|
||||
@ -1638,6 +1638,22 @@ pub struct WSAPROTOCOL_INFO {
|
||||
pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
|
||||
|
||||
pub type GROUP = c_uint;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct WIN32_FIND_DATAW {
|
||||
pub dwFileAttributes: DWORD,
|
||||
pub ftCreationTime: FILETIME,
|
||||
pub ftLastAccessTime: FILETIME,
|
||||
pub ftLastWriteTime: FILETIME,
|
||||
pub nFileSizeHigh: DWORD,
|
||||
pub nFileSizeLow: DWORD,
|
||||
pub dwReserved0: DWORD,
|
||||
pub dwReserved1: DWORD,
|
||||
pub cFileName: [wchar_t, ..260], // #define MAX_PATH 260
|
||||
pub cAlternateFileName: [wchar_t, ..14],
|
||||
}
|
||||
|
||||
pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4763,7 +4779,7 @@ pub mod kernel32 {
|
||||
LPMEMORY_BASIC_INFORMATION,
|
||||
LPSYSTEM_INFO, HANDLE, LPHANDLE,
|
||||
LARGE_INTEGER, PLARGE_INTEGER,
|
||||
LPFILETIME};
|
||||
LPFILETIME, LPWIN32_FIND_DATAW};
|
||||
|
||||
extern "system" {
|
||||
pub fn GetEnvironmentVariableW(n: LPCWSTR,
|
||||
@ -4793,9 +4809,9 @@ pub fn GetCurrentDirectoryW(nBufferLength: DWORD,
|
||||
-> DWORD;
|
||||
pub fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL;
|
||||
pub fn GetLastError() -> DWORD;
|
||||
pub fn FindFirstFileW(fileName: LPCWSTR, findFileData: HANDLE)
|
||||
pub fn FindFirstFileW(fileName: LPCWSTR, findFileData: LPWIN32_FIND_DATAW)
|
||||
-> HANDLE;
|
||||
pub fn FindNextFileW(findFile: HANDLE, findFileData: HANDLE)
|
||||
pub fn FindNextFileW(findFile: HANDLE, findFileData: LPWIN32_FIND_DATAW)
|
||||
-> BOOL;
|
||||
pub fn FindClose(findFile: HANDLE) -> BOOL;
|
||||
pub fn DuplicateHandle(hSourceProcessHandle: HANDLE,
|
||||
|
@ -11,8 +11,7 @@
|
||||
//! Blocking Windows-based file I/O
|
||||
|
||||
use alloc::arc::Arc;
|
||||
use libc::{c_int, c_void};
|
||||
use libc;
|
||||
use libc::{mod, c_int};
|
||||
use std::c_str::CString;
|
||||
use std::mem;
|
||||
use std::os::windows::fill_utf16_buf_and_decode;
|
||||
@ -20,7 +19,6 @@
|
||||
use std::rt::rtio;
|
||||
use std::rt::rtio::{IoResult, IoError};
|
||||
use std::str;
|
||||
use std::vec;
|
||||
|
||||
pub type fd_t = libc::c_int;
|
||||
|
||||
@ -344,8 +342,6 @@ pub fn mkdir(p: &CString, _mode: uint) -> IoResult<()> {
|
||||
}
|
||||
|
||||
pub fn readdir(p: &CString) -> IoResult<Vec<CString>> {
|
||||
use std::rt::libc_heap::malloc_raw;
|
||||
|
||||
fn prune(root: &CString, dirs: Vec<Path>) -> Vec<CString> {
|
||||
let root = unsafe { CString::new(root.as_ptr(), false) };
|
||||
let root = Path::new(root);
|
||||
@ -355,38 +351,35 @@ fn prune(root: &CString, dirs: Vec<Path>) -> Vec<CString> {
|
||||
}).map(|path| root.join(path).to_c_str()).collect()
|
||||
}
|
||||
|
||||
extern {
|
||||
fn rust_list_dir_wfd_size() -> libc::size_t;
|
||||
fn rust_list_dir_wfd_fp_buf(wfd: *mut libc::c_void) -> *const u16;
|
||||
}
|
||||
let star = Path::new(unsafe {
|
||||
CString::new(p.as_ptr(), false)
|
||||
}).join("*");
|
||||
let path = try!(to_utf16(&star.to_c_str()));
|
||||
|
||||
unsafe {
|
||||
let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint);
|
||||
let find_handle = libc::FindFirstFileW(path.as_ptr(),
|
||||
wfd_ptr as libc::HANDLE);
|
||||
let mut wfd = mem::zeroed();
|
||||
let find_handle = libc::FindFirstFileW(path.as_ptr(), &mut wfd);
|
||||
if find_handle != libc::INVALID_HANDLE_VALUE {
|
||||
let mut paths = vec!();
|
||||
let mut more_files = 1 as libc::c_int;
|
||||
let mut paths = vec![];
|
||||
let mut more_files = 1 as libc::BOOL;
|
||||
while more_files != 0 {
|
||||
let fp_buf = rust_list_dir_wfd_fp_buf(wfd_ptr as *mut c_void);
|
||||
if fp_buf as uint == 0 {
|
||||
fail!("os::list_dir() failure: got null ptr from wfd");
|
||||
} else {
|
||||
let fp_vec = vec::raw::from_buf(fp_buf, libc::wcslen(fp_buf) as uint);
|
||||
let fp_trimmed = str::truncate_utf16_at_nul(fp_vec.as_slice());
|
||||
let fp_str = String::from_utf16(fp_trimmed)
|
||||
.expect("rust_list_dir_wfd_fp_buf returned invalid UTF-16");
|
||||
paths.push(Path::new(fp_str));
|
||||
{
|
||||
let filename = str::truncate_utf16_at_nul(wfd.cFileName);
|
||||
match String::from_utf16(filename) {
|
||||
Some(filename) => paths.push(Path::new(filename)),
|
||||
None => {
|
||||
assert!(libc::FindClose(find_handle) != 0);
|
||||
return Err(IoError {
|
||||
code: super::c::ERROR_ILLEGAL_CHARACTER as uint,
|
||||
extra: 0,
|
||||
detail: Some(format!("path was not valid UTF-16: {}", filename)),
|
||||
})
|
||||
}, // FIXME #12056: Convert the UCS-2 to invalid utf-8 instead of erroring
|
||||
}
|
||||
}
|
||||
more_files = libc::FindNextFileW(find_handle,
|
||||
wfd_ptr as libc::HANDLE);
|
||||
more_files = libc::FindNextFileW(find_handle, &mut wfd);
|
||||
}
|
||||
assert!(libc::FindClose(find_handle) != 0);
|
||||
libc::free(wfd_ptr as *mut c_void);
|
||||
Ok(prune(p, paths))
|
||||
} else {
|
||||
Err(super::last_error())
|
||||
|
@ -100,33 +100,6 @@ rust_list_dir_val(struct dirent* entry_ptr) {
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t
|
||||
#if defined(__WIN32__)
|
||||
rust_list_dir_wfd_size() {
|
||||
return sizeof(WIN32_FIND_DATAW);
|
||||
}
|
||||
#else
|
||||
rust_list_dir_wfd_size() {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void*
|
||||
#if defined(__WIN32__)
|
||||
rust_list_dir_wfd_fp_buf(WIN32_FIND_DATAW* wfd) {
|
||||
if(wfd == NULL) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return wfd->cFileName;
|
||||
}
|
||||
}
|
||||
#else
|
||||
rust_list_dir_wfd_fp_buf(void* wfd) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int32_t tm_sec;
|
||||
int32_t tm_min;
|
||||
|
Loading…
Reference in New Issue
Block a user