pub mod compat {
use std::intrinsics::{atomic_store_relaxed, transmute};
use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
- use std::os::win32::as_utf16_p;
extern "system" {
fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
// This way, calling a function in this compatibility layer (after it's loaded) shouldn't
// be any slower than a regular DLL call.
unsafe fn store_func<T: Copy>(ptr: *mut T, module: &str, symbol: &str, fallback: T) {
- as_utf16_p(module, |module| {
- symbol.with_c_str(|symbol| {
- let handle = GetModuleHandleW(module);
- let func: Option<T> = transmute(GetProcAddress(handle, symbol));
- atomic_store_relaxed(ptr, func.unwrap_or(fallback))
- })
+ let module = module.to_utf16().append_one(0);
+ symbol.with_c_str(|symbol| {
+ let handle = GetModuleHandleW(module.as_ptr());
+ let func: Option<T> = transmute(GetProcAddress(handle, symbol));
+ atomic_store_relaxed(ptr, func.unwrap_or(fallback))
})
}
use libc;
use std::c_str::CString;
use std::mem;
-use std::os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
+use std::os::win32::fill_utf16_buf_and_decode;
use std::ptr;
use std::rt::rtio;
use std::rt::rtio::IoResult;
}
}
+pub fn to_utf16(s: &CString) -> IoResult<Vec<u16>> {
+ match s.as_str() {
+ Some(s) => Ok(s.to_utf16().append_one(0)),
+ None => Err(IoError {
+ code: libc::ERROR_INVALID_NAME as uint,
+ extra: 0,
+ detail: Some("valid unicode input required".to_str()),
+ })
+ }
+}
+
pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess)
-> IoResult<FileDesc> {
// Flags passed to open_osfhandle
// Compat with unix, this allows opening directories (see libuv)
dwFlagsAndAttributes |= libc::FILE_FLAG_BACKUP_SEMANTICS;
- let handle = as_utf16_p(path.as_str().unwrap(), |buf| unsafe {
- libc::CreateFileW(buf,
+ let path = try!(to_utf16(path));
+ let handle = unsafe {
+ libc::CreateFileW(path.as_ptr(),
dwDesiredAccess,
dwShareMode,
ptr::mut_null(),
dwCreationDisposition,
dwFlagsAndAttributes,
ptr::mut_null())
- });
+ };
if handle == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
Err(super::last_error())
} else {
}
pub fn mkdir(p: &CString, _mode: uint) -> IoResult<()> {
+ let p = try!(to_utf16(p));
super::mkerr_winbool(unsafe {
// FIXME: turn mode into something useful? #2623
- as_utf16_p(p.as_str().unwrap(), |buf| {
- libc::CreateDirectoryW(buf, ptr::mut_null())
- })
+ libc::CreateDirectoryW(p.as_ptr(), ptr::mut_null())
})
}
let star = Path::new(unsafe {
CString::new(p.with_ref(|p| p), false)
}).join("*");
- as_utf16_p(star.as_str().unwrap(), |path_ptr| unsafe {
+ 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_ptr, wfd_ptr as libc::HANDLE);
+ let find_handle = libc::FindFirstFileW(path.as_ptr(), wfd_ptr as libc::HANDLE);
if find_handle as libc::c_int != libc::INVALID_HANDLE_VALUE {
let mut paths = vec!();
let mut more_files = 1 as libc::c_int;
} else {
Err(super::last_error())
}
- })
+ }
}
pub fn unlink(p: &CString) -> IoResult<()> {
+ let p = try!(to_utf16(p));
super::mkerr_winbool(unsafe {
- as_utf16_p(p.as_str().unwrap(), |buf| {
- libc::DeleteFileW(buf)
- })
+ libc::DeleteFileW(p.as_ptr())
})
}
pub fn rename(old: &CString, new: &CString) -> IoResult<()> {
+ let old = try!(to_utf16(old));
+ let new = try!(to_utf16(new));
super::mkerr_winbool(unsafe {
- as_utf16_p(old.as_str().unwrap(), |old| {
- as_utf16_p(new.as_str().unwrap(), |new| {
- libc::MoveFileExW(old, new, libc::MOVEFILE_REPLACE_EXISTING)
- })
- })
+ libc::MoveFileExW(old.as_ptr(), new.as_ptr(),
+ libc::MOVEFILE_REPLACE_EXISTING)
})
}
pub fn chmod(p: &CString, mode: uint) -> IoResult<()> {
- super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
- libc::wchmod(p, mode as libc::c_int)
- }))
+ let p = try!(to_utf16(p));
+ super::mkerr_libc(unsafe {
+ libc::wchmod(p.as_ptr(), mode.bits() as libc::c_int)
+ })
}
pub fn rmdir(p: &CString) -> IoResult<()> {
- super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
- libc::wrmdir(p)
- }))
+ let p = try!(to_utf16(p));
+ super::mkerr_libc(unsafe { libc::wrmdir(p.as_ptr()) })
}
pub fn chown(_p: &CString, _uid: int, _gid: int) -> IoResult<()> {
pub fn readlink(p: &CString) -> IoResult<CString> {
// FIXME: I have a feeling that this reads intermediate symlinks as well.
use io::c::compat::kernel32::GetFinalPathNameByHandleW;
+ let p = try!(to_utf16(p));
let handle = unsafe {
- as_utf16_p(p.as_str().unwrap(), |p| {
- libc::CreateFileW(p,
- libc::GENERIC_READ,
- libc::FILE_SHARE_READ,
- ptr::mut_null(),
- libc::OPEN_EXISTING,
- libc::FILE_ATTRIBUTE_NORMAL,
- ptr::mut_null())
- })
+ libc::CreateFileW(p.as_ptr(),
+ libc::GENERIC_READ,
+ libc::FILE_SHARE_READ,
+ ptr::mut_null(),
+ libc::OPEN_EXISTING,
+ libc::FILE_ATTRIBUTE_NORMAL,
+ ptr::mut_null())
};
if handle as int == libc::INVALID_HANDLE_VALUE as int {
return Err(super::last_error())
pub fn symlink(src: &CString, dst: &CString) -> IoResult<()> {
use io::c::compat::kernel32::CreateSymbolicLinkW;
- super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| {
- as_utf16_p(dst.as_str().unwrap(), |dst| {
- unsafe { CreateSymbolicLinkW(dst, src, 0) }
- }) as libc::BOOL
- }))
+ let src = try!(to_utf16(src));
+ let dst = try!(to_utf16(dst));
+ super::mkerr_winbool(unsafe {
+ CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), 0) as libc::BOOL
+ })
}
pub fn link(src: &CString, dst: &CString) -> IoResult<()> {
- super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| {
- as_utf16_p(dst.as_str().unwrap(), |dst| {
- unsafe { libc::CreateHardLinkW(dst, src, ptr::mut_null()) }
- })
- }))
+ let src = try!(to_utf16(src));
+ let dst = try!(to_utf16(dst));
+ super::mkerr_winbool(unsafe {
+ libc::CreateHardLinkW(dst.as_ptr(), src.as_ptr(), ptr::mut_null())
+ })
}
fn mkstat(stat: &libc::stat) -> rtio::FileStat {
pub fn stat(p: &CString) -> IoResult<rtio::FileStat> {
let mut stat: libc::stat = unsafe { mem::zeroed() };
- as_utf16_p(p.as_str().unwrap(), |up| {
- match unsafe { libc::wstat(up, &mut stat) } {
- 0 => Ok(mkstat(&stat)),
- _ => Err(super::last_error()),
- }
- })
+ let p = try!(to_utf16(p));
+ match unsafe { libc::wstat(p.as_ptr(), &mut stat) } {
+ 0 => Ok(mkstat(&stat)),
+ _ => Err(super::last_error()),
+ }
}
pub fn lstat(_p: &CString) -> IoResult<rtio::FileStat> {
actime: (atime / 1000) as libc::time64_t,
modtime: (mtime / 1000) as libc::time64_t,
};
- super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
- libc::wutime(p, &buf)
- }))
+ let p = try!(to_utf16(p));
+ super::mkerr_libc(unsafe {
+ libc::wutime(p.as_ptr(), &buf)
+ })
}
use libc;
use std::c_str::CString;
use std::mem;
-use std::os::win32::as_utf16_p;
use std::os;
use std::ptr;
use std::rt::rtio;
use super::c;
use super::util;
+use super::file::to_utf16;
struct Event(libc::HANDLE);
}
pub fn connect(addr: &CString, timeout: Option<u64>) -> IoResult<UnixStream> {
- as_utf16_p(addr.as_str().unwrap(), |p| {
- let start = ::io::timer::now();
- loop {
- match UnixStream::try_connect(p) {
- Some(handle) => {
- let inner = Inner::new(handle);
- let mut mode = libc::PIPE_TYPE_BYTE |
- libc::PIPE_READMODE_BYTE |
- libc::PIPE_WAIT;
- let ret = unsafe {
- libc::SetNamedPipeHandleState(inner.handle,
- &mut mode,
- ptr::mut_null(),
- ptr::mut_null())
- };
- return if ret == 0 {
- Err(super::last_error())
- } else {
- Ok(UnixStream {
- inner: Arc::new(inner),
- read: None,
- write: None,
- read_deadline: 0,
- write_deadline: 0,
- })
- }
+ let addr = try!(to_utf16(addr));
+ let start = ::io::timer::now();
+ loop {
+ match UnixStream::try_connect(addr.as_ptr()) {
+ Some(handle) => {
+ let inner = Inner::new(handle);
+ let mut mode = libc::PIPE_TYPE_BYTE |
+ libc::PIPE_READMODE_BYTE |
+ libc::PIPE_WAIT;
+ let ret = unsafe {
+ libc::SetNamedPipeHandleState(inner.handle,
+ &mut mode,
+ ptr::mut_null(),
+ ptr::mut_null())
+ };
+ return if ret == 0 {
+ Err(super::last_error())
+ } else {
+ Ok(UnixStream {
+ inner: Arc::new(inner),
+ read: None,
+ write: None,
+ read_deadline: 0,
+ write_deadline: 0,
+ })
}
- None => {}
}
+ None => {}
+ }
- // On windows, if you fail to connect, you may need to call the
- // `WaitNamedPipe` function, and this is indicated with an error
- // code of ERROR_PIPE_BUSY.
- let code = unsafe { libc::GetLastError() };
- if code as int != libc::ERROR_PIPE_BUSY as int {
- return Err(super::last_error())
- }
+ // On windows, if you fail to connect, you may need to call the
+ // `WaitNamedPipe` function, and this is indicated with an error
+ // code of ERROR_PIPE_BUSY.
+ let code = unsafe { libc::GetLastError() };
+ if code as int != libc::ERROR_PIPE_BUSY as int {
+ return Err(super::last_error())
+ }
- match timeout {
- Some(timeout) => {
- let now = ::io::timer::now();
- let timed_out = (now - start) >= timeout || unsafe {
- let ms = (timeout - (now - start)) as libc::DWORD;
- libc::WaitNamedPipeW(p, ms) == 0
- };
- if timed_out {
- return Err(util::timeout("connect timed out"))
- }
+ match timeout {
+ Some(timeout) => {
+ let now = ::io::timer::now();
+ let timed_out = (now - start) >= timeout || unsafe {
+ let ms = (timeout - (now - start)) as libc::DWORD;
+ libc::WaitNamedPipeW(addr.as_ptr(), ms) == 0
+ };
+ if timed_out {
+ return Err(util::timeout("connect timed out"))
}
+ }
- // An example I found on microsoft's website used 20
- // seconds, libuv uses 30 seconds, hence we make the
- // obvious choice of waiting for 25 seconds.
- None => {
- if unsafe { libc::WaitNamedPipeW(p, 25000) } == 0 {
- return Err(super::last_error())
- }
+ // An example I found on microsoft's website used 20
+ // seconds, libuv uses 30 seconds, hence we make the
+ // obvious choice of waiting for 25 seconds.
+ None => {
+ if unsafe { libc::WaitNamedPipeW(addr.as_ptr(), 25000) } == 0 {
+ return Err(super::last_error())
}
}
}
- })
+ }
}
fn handle(&self) -> libc::HANDLE { self.inner.handle }
// Although we technically don't need the pipe until much later, we
// create the initial handle up front to test the validity of the name
// and such.
- as_utf16_p(addr.as_str().unwrap(), |p| {
- let ret = unsafe { pipe(p, true) };
- if ret == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
- Err(super::last_error())
- } else {
- Ok(UnixListener { handle: ret, name: addr.clone() })
- }
- })
+ let addr_v = try!(to_utf16(addr));
+ let ret = unsafe { pipe(addr_v.as_ptr(), true) };
+ if ret == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
+ Err(super::last_error())
+ } else {
+ Ok(UnixListener { handle: ret, name: addr.clone() })
+ }
}
pub fn native_listen(self) -> IoResult<UnixAcceptor> {
// using the original server pipe.
let handle = self.listener.handle;
+ let name = try!(to_utf16(&self.listener.name));
+
// Once we've got a "server handle", we need to wait for a client to
// connect. The ConnectNamedPipe function will block this thread until
// someone on the other end connects. This function can "fail" if a
// Now that we've got a connected client to our handle, we need to
// create a second server pipe. If this fails, we disconnect the
// connected client and return an error (see comments above).
- let new_handle = as_utf16_p(self.listener.name.as_str().unwrap(), |p| {
- unsafe { pipe(p, false) }
- });
+ let new_handle = unsafe { pipe(name.as_ptr(), false) };
if new_handle == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
let ret = Err(super::last_error());
// If our disconnection fails, then there's not really a whole lot
lpSecurityDescriptor: ptr::mut_null(),
bInheritHandle: 1,
};
- *slot = os::win32::as_utf16_p("NUL", |filename| {
- libc::CreateFileW(filename,
- access,
- libc::FILE_SHARE_READ |
- libc::FILE_SHARE_WRITE,
- &mut sa,
- libc::OPEN_EXISTING,
- 0,
- ptr::mut_null())
- });
+ let filename = "NUL".to_utf16().append_one(0);
+ *slot = libc::CreateFileW(filename.as_ptr(),
+ access,
+ libc::FILE_SHARE_READ |
+ libc::FILE_SHARE_WRITE,
+ &mut sa,
+ libc::OPEN_EXISTING,
+ 0,
+ ptr::mut_null());
if *slot == INVALID_HANDLE_VALUE as libc::HANDLE {
return Err(super::last_error())
}
with_envp(cfg.env, |envp| {
with_dirp(cfg.cwd, |dirp| {
- os::win32::as_mut_utf16_p(cmd_str.as_slice(), |cmdp| {
- let created = CreateProcessW(ptr::null(),
- cmdp,
- ptr::mut_null(),
- ptr::mut_null(),
- TRUE,
- flags, envp, dirp,
- &mut si, &mut pi);
- if created == FALSE {
- create_err = Some(super::last_error());
- }
- })
+ let mut cmd_str = cmd_str.to_utf16().append_one(0);
+ let created = CreateProcessW(ptr::null(),
+ cmd_str.as_mut_ptr(),
+ ptr::mut_null(),
+ ptr::mut_null(),
+ TRUE,
+ flags, envp, dirp,
+ &mut si, &mut pi);
+ if created == FALSE {
+ create_err = Some(super::last_error());
+ }
})
});
Some(dir) => {
let dir_str = dir.as_str()
.expect("expected workingdirectory to be utf-8 encoded");
- os::win32::as_utf16_p(dir_str, cb)
+ let dir_str = dir_str.to_utf16().append_one(0);
+ cb(dir_str.as_ptr())
},
None => cb(ptr::null())
}
mod imp {
use libc;
use std::mem;
- use std::os::win32::as_utf16_p;
use std::os;
use std::ptr;
impl Lock {
pub fn new(p: &Path) -> Lock {
- let handle = as_utf16_p(p.as_str().unwrap(), |p| unsafe {
- libc::CreateFileW(p,
+ let p_16 = p.as_str().unwrap().to_utf16().append_one(0);
+ let handle = unsafe {
+ libc::CreateFileW(p_16.as_ptr(),
libc::FILE_GENERIC_READ |
libc::FILE_GENERIC_WRITE,
libc::FILE_SHARE_READ |
libc::CREATE_ALWAYS,
libc::FILE_ATTRIBUTE_NORMAL,
ptr::mut_null())
- });
+ };
if handle as uint == libc::INVALID_HANDLE_VALUE as uint {
fail!("create file error: {}", os::last_os_error());
}
use os::TMPBUF_SZ;
use slice::{MutableVector, ImmutableVector};
use string::String;
- use str::{StrSlice, StrAllocating};
+ use str::StrSlice;
use str;
use vec::Vec;
return res;
}
}
-
- pub fn as_utf16_p<T>(s: &str, f: |*u16| -> T) -> T {
- as_mut_utf16_p(s, |t| { f(t as *u16) })
- }
-
- pub fn as_mut_utf16_p<T>(s: &str, f: |*mut u16| -> T) -> T {
- let mut t = s.to_utf16();
- // Null terminate before passing on.
- t.push(0u16);
- f(t.as_mut_ptr())
- }
}
/*
pub fn getenv(n: &str) -> Option<String> {
unsafe {
with_env_lock(|| {
- use os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
- as_utf16_p(n, |u| {
- fill_utf16_buf_and_decode(|buf, sz| {
- libc::GetEnvironmentVariableW(u, buf, sz)
- })
+ use os::win32::{fill_utf16_buf_and_decode};
+ let n = n.to_utf16().append_one(0);
+ fill_utf16_buf_and_decode(|buf, sz| {
+ libc::GetEnvironmentVariableW(n.as_ptr(), buf, sz)
})
})
}
/// Sets the environment variable `n` to the value `v` for the currently running
/// process
pub fn setenv(n: &str, v: &str) {
+ let n = n.to_utf16().append_one(0);
+ let v = v.to_utf16().append_one(0);
unsafe {
with_env_lock(|| {
- use os::win32::as_utf16_p;
- as_utf16_p(n, |nbuf| {
- as_utf16_p(v, |vbuf| {
- libc::SetEnvironmentVariableW(nbuf, vbuf);
- })
- })
+ libc::SetEnvironmentVariableW(n.as_ptr(), v.as_ptr());
})
}
}
}
#[cfg(windows)]
fn _unsetenv(n: &str) {
+ let n = n.to_utf16().append_one(0);
unsafe {
with_env_lock(|| {
- use os::win32::as_utf16_p;
- as_utf16_p(n, |nbuf| {
- libc::SetEnvironmentVariableW(nbuf, ptr::null());
- })
+ libc::SetEnvironmentVariableW(n.as_ptr(), ptr::null());
})
}
}
#[cfg(windows)]
fn chdir(p: &Path) -> bool {
+ let p = match p.as_str() {
+ Some(s) => s.to_utf16().append_one(0),
+ None => return false,
+ };
unsafe {
- use os::win32::as_utf16_p;
- return as_utf16_p(p.as_str().unwrap(), |buf| {
- libc::SetCurrentDirectoryW(buf) != (0 as libc::BOOL)
- });
+ libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL)
}
}
#[cfg(target_os = "win32")]
pub mod dl {
+ use c_str::ToCStr;
use libc;
use os;
use ptr;
use result::{Ok, Err, Result};
- use string::String;
+ use str::StrAllocating;
use str;
- use c_str::ToCStr;
+ use string::String;
pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
// Windows expects Unicode data
let filename_cstr = filename.to_c_str();
let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap();
- os::win32::as_utf16_p(filename_str, |raw_name| {
- LoadLibraryW(raw_name as *libc::c_void) as *u8
- })
+ let filename_str = filename_str.to_utf16().append_one(0);
+ LoadLibraryW(filename_str.as_ptr() as *libc::c_void) as *u8
}
pub unsafe fn open_internal() -> *u8 {