std: Implement CString-related RFCs
This commit is an implementation of [RFC 592][r592] and [RFC 840][r840]. These two RFCs tweak the behavior of `CString` and add a new `CStr` unsized slice type to the module. [r592]: https://github.com/rust-lang/rfcs/blob/master/text/0592-c-str-deref.md [r840]: https://github.com/rust-lang/rfcs/blob/master/text/0840-no-panic-in-c-string.md The new `CStr` type is only constructable via two methods: 1. By `deref`'ing from a `CString` 2. Unsafely via `CStr::from_ptr` The purpose of `CStr` is to be an unsized type which is a thin pointer to a `libc::c_char` (currently it is a fat pointer slice due to implementation limitations). Strings from C can be safely represented with a `CStr` and an appropriate lifetime as well. Consumers of `&CString` should now consume `&CStr` instead to allow producers to pass in C-originating strings instead of just Rust-allocated strings. A new constructor was added to `CString`, `new`, which takes `T: IntoBytes` instead of separate `from_slice` and `from_vec` methods (both have been deprecated in favor of `new`). The `new` method returns a `Result` instead of panicking. The error variant contains the relevant information about where the error happened and bytes (if present). Conversions are provided to the `io::Error` and `old_io::IoError` types via the `FromError` trait which translate to `InvalidInput`. This is a breaking change due to the modification of existing `#[unstable]` APIs and new deprecation, and more detailed information can be found in the two RFCs. Notable breakage includes: * All construction of `CString` now needs to use `new` and handle the outgoing `Result`. * Usage of `CString` as a byte slice now explicitly needs a `.as_bytes()` call. * The `as_slice*` methods have been removed in favor of just having the `as_bytes*` methods. Closes #22469 Closes #22470 [breaking-change]
This commit is contained in:
parent
dfc5c0f1e8
commit
1860ee521a
40 changed files with 555 additions and 290 deletions
|
@ -12,7 +12,7 @@
|
|||
|
||||
use prelude::v1::*;
|
||||
|
||||
use ffi::{self, CString};
|
||||
use ffi::{CString, CStr};
|
||||
use old_io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
|
||||
use old_io::{IoResult, FileStat, SeekStyle};
|
||||
use old_io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
|
||||
|
@ -151,8 +151,8 @@ impl Drop for FileDesc {
|
|||
}
|
||||
}
|
||||
|
||||
fn cstr(path: &Path) -> CString {
|
||||
CString::from_slice(path.as_vec())
|
||||
fn cstr(path: &Path) -> IoResult<CString> {
|
||||
Ok(try!(CString::new(path.as_vec())))
|
||||
}
|
||||
|
||||
pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
|
||||
|
@ -170,7 +170,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
|
|||
libc::S_IRUSR | libc::S_IWUSR),
|
||||
};
|
||||
|
||||
let path = cstr(path);
|
||||
let path = try!(cstr(path));
|
||||
match retry(|| unsafe { libc::open(path.as_ptr(), flags, mode) }) {
|
||||
-1 => Err(super::last_error()),
|
||||
fd => Ok(FileDesc::new(fd, true)),
|
||||
|
@ -178,7 +178,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
|
|||
}
|
||||
|
||||
pub fn mkdir(p: &Path, mode: uint) -> IoResult<()> {
|
||||
let p = cstr(p);
|
||||
let p = try!(cstr(p));
|
||||
mkerr_libc(unsafe { libc::mkdir(p.as_ptr(), mode as libc::mode_t) })
|
||||
}
|
||||
|
||||
|
@ -203,7 +203,7 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> {
|
|||
let mut buf = Vec::<u8>::with_capacity(size as uint);
|
||||
let ptr = buf.as_mut_ptr() as *mut dirent_t;
|
||||
|
||||
let p = CString::from_slice(p.as_vec());
|
||||
let p = try!(CString::new(p.as_vec()));
|
||||
let dir_ptr = unsafe {opendir(p.as_ptr())};
|
||||
|
||||
if dir_ptr as uint != 0 {
|
||||
|
@ -212,7 +212,7 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> {
|
|||
while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } {
|
||||
if entry_ptr.is_null() { break }
|
||||
paths.push(unsafe {
|
||||
Path::new(ffi::c_str_to_bytes(&rust_list_dir_val(entry_ptr)))
|
||||
Path::new(CStr::from_ptr(rust_list_dir_val(entry_ptr)).to_bytes())
|
||||
});
|
||||
}
|
||||
assert_eq!(unsafe { closedir(dir_ptr) }, 0);
|
||||
|
@ -223,39 +223,39 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> {
|
|||
}
|
||||
|
||||
pub fn unlink(p: &Path) -> IoResult<()> {
|
||||
let p = cstr(p);
|
||||
let p = try!(cstr(p));
|
||||
mkerr_libc(unsafe { libc::unlink(p.as_ptr()) })
|
||||
}
|
||||
|
||||
pub fn rename(old: &Path, new: &Path) -> IoResult<()> {
|
||||
let old = cstr(old);
|
||||
let new = cstr(new);
|
||||
let old = try!(cstr(old));
|
||||
let new = try!(cstr(new));
|
||||
mkerr_libc(unsafe {
|
||||
libc::rename(old.as_ptr(), new.as_ptr())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn chmod(p: &Path, mode: uint) -> IoResult<()> {
|
||||
let p = cstr(p);
|
||||
let p = try!(cstr(p));
|
||||
mkerr_libc(retry(|| unsafe {
|
||||
libc::chmod(p.as_ptr(), mode as libc::mode_t)
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn rmdir(p: &Path) -> IoResult<()> {
|
||||
let p = cstr(p);
|
||||
let p = try!(cstr(p));
|
||||
mkerr_libc(unsafe { libc::rmdir(p.as_ptr()) })
|
||||
}
|
||||
|
||||
pub fn chown(p: &Path, uid: int, gid: int) -> IoResult<()> {
|
||||
let p = cstr(p);
|
||||
let p = try!(cstr(p));
|
||||
mkerr_libc(retry(|| unsafe {
|
||||
libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t)
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn readlink(p: &Path) -> IoResult<Path> {
|
||||
let c_path = cstr(p);
|
||||
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 == -1 {
|
||||
|
@ -276,14 +276,14 @@ pub fn readlink(p: &Path) -> IoResult<Path> {
|
|||
}
|
||||
|
||||
pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
|
||||
let src = cstr(src);
|
||||
let dst = cstr(dst);
|
||||
let src = try!(cstr(src));
|
||||
let dst = try!(cstr(dst));
|
||||
mkerr_libc(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) })
|
||||
}
|
||||
|
||||
pub fn link(src: &Path, dst: &Path) -> IoResult<()> {
|
||||
let src = cstr(src);
|
||||
let dst = cstr(dst);
|
||||
let src = try!(cstr(src));
|
||||
let dst = try!(cstr(dst));
|
||||
mkerr_libc(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })
|
||||
}
|
||||
|
||||
|
@ -331,7 +331,7 @@ fn mkstat(stat: &libc::stat) -> FileStat {
|
|||
}
|
||||
|
||||
pub fn stat(p: &Path) -> IoResult<FileStat> {
|
||||
let p = cstr(p);
|
||||
let p = try!(cstr(p));
|
||||
let mut stat: libc::stat = unsafe { mem::zeroed() };
|
||||
match unsafe { libc::stat(p.as_ptr(), &mut stat) } {
|
||||
0 => Ok(mkstat(&stat)),
|
||||
|
@ -340,7 +340,7 @@ pub fn stat(p: &Path) -> IoResult<FileStat> {
|
|||
}
|
||||
|
||||
pub fn lstat(p: &Path) -> IoResult<FileStat> {
|
||||
let p = cstr(p);
|
||||
let p = try!(cstr(p));
|
||||
let mut stat: libc::stat = unsafe { mem::zeroed() };
|
||||
match unsafe { libc::lstat(p.as_ptr(), &mut stat) } {
|
||||
0 => Ok(mkstat(&stat)),
|
||||
|
@ -349,7 +349,7 @@ pub fn lstat(p: &Path) -> IoResult<FileStat> {
|
|||
}
|
||||
|
||||
pub fn utime(p: &Path, atime: u64, mtime: u64) -> IoResult<()> {
|
||||
let p = cstr(p);
|
||||
let p = try!(cstr(p));
|
||||
let buf = libc::utimbuf {
|
||||
actime: (atime / 1000) as libc::time_t,
|
||||
modtime: (mtime / 1000) as libc::time_t,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue