Skip to content

Commit 3c468ed

Browse files
committed
std: Remove the as_utf16_p functions
These functions are all much better expressed via RAII using the to_utf16() method on strings. This refactoring also takes this opportunity to properly handle when filenames aren't valid unicode when passed through to the windows I/O layer by properly returning I/O errors. All previous users of the `as_utf16_p` or `as_utf16_mut_p` functions will need to convert their code to using `foo.to_utf16().append_one(0)` to get a null-terminated utf16 string. [breaking-change]
1 parent 8e9e484 commit 3c468ed

File tree

7 files changed

+175
-186
lines changed

7 files changed

+175
-186
lines changed

src/libnative/io/c_win32.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ extern "system" {
6969
pub mod compat {
7070
use std::intrinsics::{atomic_store_relaxed, transmute};
7171
use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
72-
use std::os::win32::as_utf16_p;
7372

7473
extern "system" {
7574
fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
@@ -80,12 +79,11 @@ pub mod compat {
8079
// This way, calling a function in this compatibility layer (after it's loaded) shouldn't
8180
// be any slower than a regular DLL call.
8281
unsafe fn store_func<T: Copy>(ptr: *mut T, module: &str, symbol: &str, fallback: T) {
83-
as_utf16_p(module, |module| {
84-
symbol.with_c_str(|symbol| {
85-
let handle = GetModuleHandleW(module);
86-
let func: Option<T> = transmute(GetProcAddress(handle, symbol));
87-
atomic_store_relaxed(ptr, func.unwrap_or(fallback))
88-
})
82+
let module = module.to_utf16().append_one(0);
83+
symbol.with_c_str(|symbol| {
84+
let handle = GetModuleHandleW(module.as_ptr());
85+
let func: Option<T> = transmute(GetProcAddress(handle, symbol));
86+
atomic_store_relaxed(ptr, func.unwrap_or(fallback))
8987
})
9088
}
9189

src/libnative/io/file_win32.rs

+62-52
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use libc::{c_int, c_void};
1515
use libc;
1616
use std::c_str::CString;
1717
use std::mem;
18-
use std::os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
18+
use std::os::win32::fill_utf16_buf_and_decode;
1919
use std::ptr;
2020
use std::rt::rtio;
2121
use std::rt::rtio::IoResult;
@@ -253,6 +253,17 @@ impl Drop for Inner {
253253
}
254254
}
255255

256+
pub fn to_utf16(s: &CString) -> IoResult<Vec<u16>> {
257+
match s.as_str() {
258+
Some(s) => Ok(s.to_utf16().append_one(0)),
259+
None => Err(IoError {
260+
code: libc::ERROR_INVALID_NAME as uint,
261+
extra: 0,
262+
detail: Some("valid unicode input required".to_str()),
263+
})
264+
}
265+
}
266+
256267
pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess)
257268
-> IoResult<FileDesc> {
258269
// Flags passed to open_osfhandle
@@ -299,15 +310,16 @@ pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess)
299310
// Compat with unix, this allows opening directories (see libuv)
300311
dwFlagsAndAttributes |= libc::FILE_FLAG_BACKUP_SEMANTICS;
301312

302-
let handle = as_utf16_p(path.as_str().unwrap(), |buf| unsafe {
303-
libc::CreateFileW(buf,
313+
let path = try!(to_utf16(path));
314+
let handle = unsafe {
315+
libc::CreateFileW(path.as_ptr(),
304316
dwDesiredAccess,
305317
dwShareMode,
306318
ptr::mut_null(),
307319
dwCreationDisposition,
308320
dwFlagsAndAttributes,
309321
ptr::mut_null())
310-
});
322+
};
311323
if handle == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
312324
Err(super::last_error())
313325
} else {
@@ -324,11 +336,10 @@ pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess)
324336
}
325337

326338
pub fn mkdir(p: &CString, _mode: uint) -> IoResult<()> {
339+
let p = try!(to_utf16(p));
327340
super::mkerr_winbool(unsafe {
328341
// FIXME: turn mode into something useful? #2623
329-
as_utf16_p(p.as_str().unwrap(), |buf| {
330-
libc::CreateDirectoryW(buf, ptr::mut_null())
331-
})
342+
libc::CreateDirectoryW(p.as_ptr(), ptr::mut_null())
332343
})
333344
}
334345

@@ -351,9 +362,11 @@ pub fn readdir(p: &CString) -> IoResult<Vec<CString>> {
351362
let star = Path::new(unsafe {
352363
CString::new(p.with_ref(|p| p), false)
353364
}).join("*");
354-
as_utf16_p(star.as_str().unwrap(), |path_ptr| unsafe {
365+
let path = try!(to_utf16(&star.to_c_str()));
366+
367+
unsafe {
355368
let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint);
356-
let find_handle = libc::FindFirstFileW(path_ptr, wfd_ptr as libc::HANDLE);
369+
let find_handle = libc::FindFirstFileW(path.as_ptr(), wfd_ptr as libc::HANDLE);
357370
if find_handle as libc::c_int != libc::INVALID_HANDLE_VALUE {
358371
let mut paths = vec!();
359372
let mut more_files = 1 as libc::c_int;
@@ -377,37 +390,35 @@ pub fn readdir(p: &CString) -> IoResult<Vec<CString>> {
377390
} else {
378391
Err(super::last_error())
379392
}
380-
})
393+
}
381394
}
382395

383396
pub fn unlink(p: &CString) -> IoResult<()> {
397+
let p = try!(to_utf16(p));
384398
super::mkerr_winbool(unsafe {
385-
as_utf16_p(p.as_str().unwrap(), |buf| {
386-
libc::DeleteFileW(buf)
387-
})
399+
libc::DeleteFileW(p.as_ptr())
388400
})
389401
}
390402

391403
pub fn rename(old: &CString, new: &CString) -> IoResult<()> {
404+
let old = try!(to_utf16(old));
405+
let new = try!(to_utf16(new));
392406
super::mkerr_winbool(unsafe {
393-
as_utf16_p(old.as_str().unwrap(), |old| {
394-
as_utf16_p(new.as_str().unwrap(), |new| {
395-
libc::MoveFileExW(old, new, libc::MOVEFILE_REPLACE_EXISTING)
396-
})
397-
})
407+
libc::MoveFileExW(old.as_ptr(), new.as_ptr(),
408+
libc::MOVEFILE_REPLACE_EXISTING)
398409
})
399410
}
400411

401412
pub fn chmod(p: &CString, mode: uint) -> IoResult<()> {
402-
super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
403-
libc::wchmod(p, mode as libc::c_int)
404-
}))
413+
let p = try!(to_utf16(p));
414+
super::mkerr_libc(unsafe {
415+
libc::wchmod(p.as_ptr(), mode.bits() as libc::c_int)
416+
})
405417
}
406418

407419
pub fn rmdir(p: &CString) -> IoResult<()> {
408-
super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
409-
libc::wrmdir(p)
410-
}))
420+
let p = try!(to_utf16(p));
421+
super::mkerr_libc(unsafe { libc::wrmdir(p.as_ptr()) })
411422
}
412423

413424
pub fn chown(_p: &CString, _uid: int, _gid: int) -> IoResult<()> {
@@ -418,16 +429,15 @@ pub fn chown(_p: &CString, _uid: int, _gid: int) -> IoResult<()> {
418429
pub fn readlink(p: &CString) -> IoResult<CString> {
419430
// FIXME: I have a feeling that this reads intermediate symlinks as well.
420431
use io::c::compat::kernel32::GetFinalPathNameByHandleW;
432+
let p = try!(to_utf16(p));
421433
let handle = unsafe {
422-
as_utf16_p(p.as_str().unwrap(), |p| {
423-
libc::CreateFileW(p,
424-
libc::GENERIC_READ,
425-
libc::FILE_SHARE_READ,
426-
ptr::mut_null(),
427-
libc::OPEN_EXISTING,
428-
libc::FILE_ATTRIBUTE_NORMAL,
429-
ptr::mut_null())
430-
})
434+
libc::CreateFileW(p.as_ptr(),
435+
libc::GENERIC_READ,
436+
libc::FILE_SHARE_READ,
437+
ptr::mut_null(),
438+
libc::OPEN_EXISTING,
439+
libc::FILE_ATTRIBUTE_NORMAL,
440+
ptr::mut_null())
431441
};
432442
if handle as int == libc::INVALID_HANDLE_VALUE as int {
433443
return Err(super::last_error())
@@ -453,19 +463,19 @@ pub fn readlink(p: &CString) -> IoResult<CString> {
453463

454464
pub fn symlink(src: &CString, dst: &CString) -> IoResult<()> {
455465
use io::c::compat::kernel32::CreateSymbolicLinkW;
456-
super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| {
457-
as_utf16_p(dst.as_str().unwrap(), |dst| {
458-
unsafe { CreateSymbolicLinkW(dst, src, 0) }
459-
}) as libc::BOOL
460-
}))
466+
let src = try!(to_utf16(src));
467+
let dst = try!(to_utf16(dst));
468+
super::mkerr_winbool(unsafe {
469+
CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), 0) as libc::BOOL
470+
})
461471
}
462472

463473
pub fn link(src: &CString, dst: &CString) -> IoResult<()> {
464-
super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| {
465-
as_utf16_p(dst.as_str().unwrap(), |dst| {
466-
unsafe { libc::CreateHardLinkW(dst, src, ptr::mut_null()) }
467-
})
468-
}))
474+
let src = try!(to_utf16(src));
475+
let dst = try!(to_utf16(dst));
476+
super::mkerr_winbool(unsafe {
477+
libc::CreateHardLinkW(dst.as_ptr(), src.as_ptr(), ptr::mut_null())
478+
})
469479
}
470480

471481
fn mkstat(stat: &libc::stat) -> rtio::FileStat {
@@ -491,12 +501,11 @@ fn mkstat(stat: &libc::stat) -> rtio::FileStat {
491501

492502
pub fn stat(p: &CString) -> IoResult<rtio::FileStat> {
493503
let mut stat: libc::stat = unsafe { mem::zeroed() };
494-
as_utf16_p(p.as_str().unwrap(), |up| {
495-
match unsafe { libc::wstat(up, &mut stat) } {
496-
0 => Ok(mkstat(&stat)),
497-
_ => Err(super::last_error()),
498-
}
499-
})
504+
let p = try!(to_utf16(p));
505+
match unsafe { libc::wstat(p.as_ptr(), &mut stat) } {
506+
0 => Ok(mkstat(&stat)),
507+
_ => Err(super::last_error()),
508+
}
500509
}
501510

502511
pub fn lstat(_p: &CString) -> IoResult<rtio::FileStat> {
@@ -509,7 +518,8 @@ pub fn utime(p: &CString, atime: u64, mtime: u64) -> IoResult<()> {
509518
actime: (atime / 1000) as libc::time64_t,
510519
modtime: (mtime / 1000) as libc::time64_t,
511520
};
512-
super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
513-
libc::wutime(p, &buf)
514-
}))
521+
let p = try!(to_utf16(p));
522+
super::mkerr_libc(unsafe {
523+
libc::wutime(p.as_ptr(), &buf)
524+
})
515525
}

0 commit comments

Comments
 (0)