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:
Alex Crichton 2015-02-17 22:47:40 -08:00
parent dfc5c0f1e8
commit 1860ee521a
40 changed files with 555 additions and 290 deletions

View File

@ -435,7 +435,7 @@ extern {
} }
fn main() { fn main() {
let prompt = CString::from_slice(b"[my-awesome-shell] $"); let prompt = CString::new("[my-awesome-shell] $").unwrap();
unsafe { unsafe {
rl_prompt = prompt.as_ptr(); rl_prompt = prompt.as_ptr();

View File

@ -744,7 +744,7 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
} }
} }
unsafe { unsafe {
let buf = CString::from_slice(filename.as_vec()); let buf = CString::new(filename.as_vec()).unwrap();
let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr()); let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
if mb as int == 0 { if mb as int == 0 {
return Err(format!("error reading library: '{}'", return Err(format!("error reading library: '{}'",

View File

@ -30,7 +30,7 @@ impl ArchiveRO {
/// raised. /// raised.
pub fn open(dst: &Path) -> Option<ArchiveRO> { pub fn open(dst: &Path) -> Option<ArchiveRO> {
unsafe { unsafe {
let s = CString::from_slice(dst.as_vec()); let s = CString::new(dst.as_vec()).unwrap();
let ar = ::LLVMRustOpenArchive(s.as_ptr()); let ar = ::LLVMRustOpenArchive(s.as_ptr());
if ar.is_null() { if ar.is_null() {
None None
@ -44,7 +44,7 @@ impl ArchiveRO {
pub fn read<'a>(&'a self, file: &str) -> Option<&'a [u8]> { pub fn read<'a>(&'a self, file: &str) -> Option<&'a [u8]> {
unsafe { unsafe {
let mut size = 0 as libc::size_t; let mut size = 0 as libc::size_t;
let file = CString::from_slice(file.as_bytes()); let file = CString::new(file).unwrap();
let ptr = ::LLVMRustArchiveReadSection(self.ptr, file.as_ptr(), let ptr = ::LLVMRustArchiveReadSection(self.ptr, file.as_ptr(),
&mut size); &mut size);
if ptr.is_null() { if ptr.is_null() {

View File

@ -2149,7 +2149,7 @@ impl Drop for TargetData {
} }
pub fn mk_target_data(string_rep: &str) -> TargetData { pub fn mk_target_data(string_rep: &str) -> TargetData {
let string_rep = CString::from_slice(string_rep.as_bytes()); let string_rep = CString::new(string_rep).unwrap();
TargetData { TargetData {
lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) } lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) }
} }

View File

@ -140,7 +140,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
// Internalize everything but the reachable symbols of the current module // Internalize everything but the reachable symbols of the current module
let cstrs: Vec<CString> = reachable.iter().map(|s| { let cstrs: Vec<CString> = reachable.iter().map(|s| {
CString::from_slice(s.as_bytes()) CString::new(s.clone()).unwrap()
}).collect(); }).collect();
let arr: Vec<*const libc::c_char> = cstrs.iter().map(|c| c.as_ptr()).collect(); let arr: Vec<*const libc::c_char> = cstrs.iter().map(|c| c.as_ptr()).collect();
let ptr = arr.as_ptr(); let ptr = arr.as_ptr();

View File

@ -22,7 +22,7 @@ use syntax::codemap;
use syntax::diagnostic; use syntax::diagnostic;
use syntax::diagnostic::{Emitter, Handler, Level, mk_handler}; use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
use std::ffi::{self, CString}; use std::ffi::{CStr, CString};
use std::old_io::Command; use std::old_io::Command;
use std::old_io::fs; use std::old_io::fs;
use std::iter::Unfold; use std::iter::Unfold;
@ -49,7 +49,7 @@ pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! {
if cstr == ptr::null() { if cstr == ptr::null() {
handler.fatal(&msg[]); handler.fatal(&msg[]);
} else { } else {
let err = ffi::c_str_to_bytes(&cstr); let err = CStr::from_ptr(cstr).to_bytes();
let err = String::from_utf8_lossy(err).to_string(); let err = String::from_utf8_lossy(err).to_string();
libc::free(cstr as *mut _); libc::free(cstr as *mut _);
handler.fatal(&format!("{}: {}", handler.fatal(&format!("{}: {}",
@ -67,7 +67,7 @@ pub fn write_output_file(
output: &Path, output: &Path,
file_type: llvm::FileType) { file_type: llvm::FileType) {
unsafe { unsafe {
let output_c = CString::from_slice(output.as_vec()); let output_c = CString::new(output.as_vec()).unwrap();
let result = llvm::LLVMRustWriteOutputFile( let result = llvm::LLVMRustWriteOutputFile(
target, pm, m, output_c.as_ptr(), file_type); target, pm, m, output_c.as_ptr(), file_type);
if !result { if !result {
@ -221,13 +221,13 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
let triple = &sess.target.target.llvm_target[]; let triple = &sess.target.target.llvm_target[];
let tm = unsafe { let tm = unsafe {
let triple = CString::from_slice(triple.as_bytes()); let triple = CString::new(triple.as_bytes()).unwrap();
let cpu = match sess.opts.cg.target_cpu { let cpu = match sess.opts.cg.target_cpu {
Some(ref s) => &**s, Some(ref s) => &**s,
None => &*sess.target.target.options.cpu None => &*sess.target.target.options.cpu
}; };
let cpu = CString::from_slice(cpu.as_bytes()); let cpu = CString::new(cpu.as_bytes()).unwrap();
let features = CString::from_slice(target_feature(sess).as_bytes()); let features = CString::new(target_feature(sess).as_bytes()).unwrap();
llvm::LLVMRustCreateTargetMachine( llvm::LLVMRustCreateTargetMachine(
triple.as_ptr(), cpu.as_ptr(), features.as_ptr(), triple.as_ptr(), cpu.as_ptr(), features.as_ptr(),
code_model, code_model,
@ -380,7 +380,7 @@ unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_vo
} }
llvm::diagnostic::Optimization(opt) => { llvm::diagnostic::Optimization(opt) => {
let pass_name = str::from_utf8(ffi::c_str_to_bytes(&opt.pass_name)) let pass_name = str::from_utf8(CStr::from_ptr(opt.pass_name).to_bytes())
.ok() .ok()
.expect("got a non-UTF8 pass name from LLVM"); .expect("got a non-UTF8 pass name from LLVM");
let enabled = match cgcx.remark { let enabled = match cgcx.remark {
@ -424,7 +424,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
if config.emit_no_opt_bc { if config.emit_no_opt_bc {
let ext = format!("{}.no-opt.bc", name_extra); let ext = format!("{}.no-opt.bc", name_extra);
let out = output_names.with_extension(&ext); let out = output_names.with_extension(&ext);
let out = CString::from_slice(out.as_vec()); let out = CString::new(out.as_vec()).unwrap();
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
} }
@ -440,7 +440,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
// If we're verifying or linting, add them to the function pass // If we're verifying or linting, add them to the function pass
// manager. // manager.
let addpass = |pass: &str| { let addpass = |pass: &str| {
let pass = CString::from_slice(pass.as_bytes()); let pass = CString::new(pass).unwrap();
llvm::LLVMRustAddPass(fpm, pass.as_ptr()) llvm::LLVMRustAddPass(fpm, pass.as_ptr())
}; };
if !config.no_verify { assert!(addpass("verify")); } if !config.no_verify { assert!(addpass("verify")); }
@ -453,7 +453,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
} }
for pass in &config.passes { for pass in &config.passes {
let pass = CString::from_slice(pass.as_bytes()); let pass = CString::new(pass.clone()).unwrap();
if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) { if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
cgcx.handler.warn(&format!("unknown pass {:?}, ignoring", pass)); cgcx.handler.warn(&format!("unknown pass {:?}, ignoring", pass));
} }
@ -477,7 +477,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
if config.emit_lto_bc { if config.emit_lto_bc {
let name = format!("{}.lto.bc", name_extra); let name = format!("{}.lto.bc", name_extra);
let out = output_names.with_extension(&name); let out = output_names.with_extension(&name);
let out = CString::from_slice(out.as_vec()); let out = CString::new(out.as_vec()).unwrap();
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
} }
}, },
@ -511,7 +511,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
if config.emit_bc { if config.emit_bc {
let ext = format!("{}.bc", name_extra); let ext = format!("{}.bc", name_extra);
let out = output_names.with_extension(&ext); let out = output_names.with_extension(&ext);
let out = CString::from_slice(out.as_vec()); let out = CString::new(out.as_vec()).unwrap();
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
} }
@ -519,7 +519,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
if config.emit_ir { if config.emit_ir {
let ext = format!("{}.ll", name_extra); let ext = format!("{}.ll", name_extra);
let out = output_names.with_extension(&ext); let out = output_names.with_extension(&ext);
let out = CString::from_slice(out.as_vec()); let out = CString::new(out.as_vec()).unwrap();
with_codegen(tm, llmod, config.no_builtins, |cpm| { with_codegen(tm, llmod, config.no_builtins, |cpm| {
llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr()); llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
}) })
@ -1004,7 +1004,7 @@ unsafe fn configure_llvm(sess: &Session) {
let mut llvm_args = Vec::new(); let mut llvm_args = Vec::new();
{ {
let mut add = |arg: &str| { let mut add = |arg: &str| {
let s = CString::from_slice(arg.as_bytes()); let s = CString::new(arg).unwrap();
llvm_args.push(s.as_ptr()); llvm_args.push(s.as_ptr());
llvm_c_strs.push(s); llvm_c_strs.push(s);
}; };

View File

@ -120,8 +120,8 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
ast::AsmIntel => llvm::AD_Intel ast::AsmIntel => llvm::AD_Intel
}; };
let asm = CString::from_slice(ia.asm.as_bytes()); let asm = CString::new(ia.asm.as_bytes()).unwrap();
let constraints = CString::from_slice(constraints.as_bytes()); let constraints = CString::new(constraints).unwrap();
let r = InlineAsmCall(bcx, let r = InlineAsmCall(bcx,
asm.as_ptr(), asm.as_ptr(),
constraints.as_ptr(), constraints.as_ptr(),

View File

@ -86,7 +86,7 @@ use util::nodemap::NodeMap;
use arena::TypedArena; use arena::TypedArena;
use libc::{c_uint, uint64_t}; use libc::{c_uint, uint64_t};
use std::ffi::{self, CString}; use std::ffi::{CStr, CString};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::collections::HashSet; use std::collections::HashSet;
use std::mem; use std::mem;
@ -186,7 +186,7 @@ impl<'a, 'tcx> Drop for StatRecorder<'a, 'tcx> {
pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv, pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
ty: Type, output: ty::FnOutput) -> ValueRef { ty: Type, output: ty::FnOutput) -> ValueRef {
let buf = CString::from_slice(name.as_bytes()); let buf = CString::new(name).unwrap();
let llfn: ValueRef = unsafe { let llfn: ValueRef = unsafe {
llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf.as_ptr(), ty.to_ref()) llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf.as_ptr(), ty.to_ref())
}; };
@ -340,7 +340,7 @@ pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId,
None => () None => ()
} }
unsafe { unsafe {
let buf = CString::from_slice(name.as_bytes()); let buf = CString::new(name.clone()).unwrap();
let c = llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf.as_ptr()); let c = llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf.as_ptr());
// Thread-local statics in some other crate need to *always* be linked // Thread-local statics in some other crate need to *always* be linked
// against in a thread-local fashion, so we need to be sure to apply the // against in a thread-local fashion, so we need to be sure to apply the
@ -2788,7 +2788,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
&format!("Illegal null byte in export_name \ &format!("Illegal null byte in export_name \
value: `{}`", sym)[]); value: `{}`", sym)[]);
} }
let buf = CString::from_slice(sym.as_bytes()); let buf = CString::new(sym.clone()).unwrap();
let g = llvm::LLVMAddGlobal(ccx.llmod(), llty, let g = llvm::LLVMAddGlobal(ccx.llmod(), llty,
buf.as_ptr()); buf.as_ptr());
@ -2826,7 +2826,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
&sect)[]); &sect)[]);
} }
unsafe { unsafe {
let buf = CString::from_slice(sect.as_bytes()); let buf = CString::new(sect.as_bytes()).unwrap();
llvm::LLVMSetSection(v, buf.as_ptr()); llvm::LLVMSetSection(v, buf.as_ptr());
} }
}, },
@ -2993,7 +2993,7 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> {
let name = format!("rust_metadata_{}_{}", let name = format!("rust_metadata_{}_{}",
cx.link_meta().crate_name, cx.link_meta().crate_name,
cx.link_meta().crate_hash); cx.link_meta().crate_hash);
let buf = CString::from_vec(name.into_bytes()); let buf = CString::new(name).unwrap();
let llglobal = unsafe { let llglobal = unsafe {
llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(), llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(),
buf.as_ptr()) buf.as_ptr())
@ -3001,7 +3001,7 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> {
unsafe { unsafe {
llvm::LLVMSetInitializer(llglobal, llconst); llvm::LLVMSetInitializer(llglobal, llconst);
let name = loader::meta_section_name(cx.sess().target.target.options.is_like_osx); let name = loader::meta_section_name(cx.sess().target.target.options.is_like_osx);
let name = CString::from_slice(name.as_bytes()); let name = CString::new(name).unwrap();
llvm::LLVMSetSection(llglobal, name.as_ptr()) llvm::LLVMSetSection(llglobal, name.as_ptr())
} }
return metadata; return metadata;
@ -3039,8 +3039,8 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
continue continue
} }
let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val)) let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
.to_vec(); .to_bytes().to_vec();
declared.insert(name); declared.insert(name);
} }
} }
@ -3056,8 +3056,8 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
continue continue
} }
let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val)) let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
.to_vec(); .to_bytes().to_vec();
if !declared.contains(&name) && if !declared.contains(&name) &&
!reachable.contains(str::from_utf8(&name).unwrap()) { !reachable.contains(str::from_utf8(&name).unwrap()) {
llvm::SetLinkage(val, llvm::InternalLinkage); llvm::SetLinkage(val, llvm::InternalLinkage);

View File

@ -431,7 +431,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
if name.is_empty() { if name.is_empty() {
llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname()) llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname())
} else { } else {
let name = CString::from_slice(name.as_bytes()); let name = CString::new(name).unwrap();
llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(),
name.as_ptr()) name.as_ptr())
} }
@ -786,7 +786,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let comment_text = format!("{} {}", "#", let comment_text = format!("{} {}", "#",
sanitized.replace("\n", "\n\t# ")); sanitized.replace("\n", "\n\t# "));
self.count_insn("inlineasm"); self.count_insn("inlineasm");
let comment_text = CString::from_vec(comment_text.into_bytes()); let comment_text = CString::new(comment_text).unwrap();
let asm = unsafe { let asm = unsafe {
llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(), llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(),
comment_text.as_ptr(), noname(), False, comment_text.as_ptr(), noname(), False,

View File

@ -488,7 +488,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
opt_node_id: Option<ast::NodeId>) opt_node_id: Option<ast::NodeId>)
-> Block<'a, 'tcx> { -> Block<'a, 'tcx> {
unsafe { unsafe {
let name = CString::from_slice(name.as_bytes()); let name = CString::new(name).unwrap();
let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
self.llfn, self.llfn,
name.as_ptr()); name.as_ptr());
@ -761,7 +761,7 @@ pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef {
pub fn C_floating(s: &str, t: Type) -> ValueRef { pub fn C_floating(s: &str, t: Type) -> ValueRef {
unsafe { unsafe {
let s = CString::from_slice(s.as_bytes()); let s = CString::new(s).unwrap();
llvm::LLVMConstRealOfString(t.to_ref(), s.as_ptr()) llvm::LLVMConstRealOfString(t.to_ref(), s.as_ptr())
} }
} }
@ -839,7 +839,8 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
!null_terminated as Bool); !null_terminated as Bool);
let gsym = token::gensym("str"); let gsym = token::gensym("str");
let buf = CString::from_vec(format!("str{}", gsym.usize()).into_bytes()); let buf = CString::new(format!("str{}", gsym.usize()));
let buf = buf.unwrap();
let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr()); let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr());
llvm::LLVMSetInitializer(g, sc); llvm::LLVMSetInitializer(g, sc);
llvm::LLVMSetGlobalConstant(g, True); llvm::LLVMSetGlobalConstant(g, True);

View File

@ -225,15 +225,15 @@ impl<'a, 'tcx> Iterator for CrateContextMaybeIterator<'a, 'tcx> {
unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) { unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
let llcx = llvm::LLVMContextCreate(); let llcx = llvm::LLVMContextCreate();
let mod_name = CString::from_slice(mod_name.as_bytes()); let mod_name = CString::new(mod_name).unwrap();
let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx); let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
let data_layout = &*sess.target.target.data_layout; let data_layout = sess.target.target.data_layout.as_bytes();
let data_layout = CString::from_slice(data_layout.as_bytes()); let data_layout = CString::new(data_layout).unwrap();
llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr()); llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
let llvm_target = &*sess.target.target.llvm_target; let llvm_target = sess.target.target.llvm_target.as_bytes();
let llvm_target = CString::from_slice(llvm_target.as_bytes()); let llvm_target = CString::new(llvm_target).unwrap();
llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
(llcx, llmod) (llcx, llmod)
} }

View File

@ -809,8 +809,8 @@ pub fn create_global_var_metadata(cx: &CrateContext,
namespace_node.mangled_name_of_contained_item(&var_name[]); namespace_node.mangled_name_of_contained_item(&var_name[]);
let var_scope = namespace_node.scope; let var_scope = namespace_node.scope;
let var_name = CString::from_slice(var_name.as_bytes()); let var_name = CString::new(var_name).unwrap();
let linkage_name = CString::from_slice(linkage_name.as_bytes()); let linkage_name = CString::new(linkage_name).unwrap();
unsafe { unsafe {
llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx), llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
var_scope, var_scope,
@ -1379,8 +1379,8 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id); let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
let function_name = CString::from_slice(function_name.as_bytes()); let function_name = CString::new(function_name).unwrap();
let linkage_name = CString::from_slice(linkage_name.as_bytes()); let linkage_name = CString::new(linkage_name).unwrap();
let fn_metadata = unsafe { let fn_metadata = unsafe {
llvm::LLVMDIBuilderCreateFunction( llvm::LLVMDIBuilderCreateFunction(
DIB(cx), DIB(cx),
@ -1501,7 +1501,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let ident = special_idents::type_self; let ident = special_idents::type_self;
let ident = token::get_ident(ident); let ident = token::get_ident(ident);
let name = CString::from_slice(ident.as_bytes()); let name = CString::new(ident.as_bytes()).unwrap();
let param_metadata = unsafe { let param_metadata = unsafe {
llvm::LLVMDIBuilderCreateTemplateTypeParameter( llvm::LLVMDIBuilderCreateTemplateTypeParameter(
DIB(cx), DIB(cx),
@ -1535,7 +1535,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
if cx.sess().opts.debuginfo == FullDebugInfo { if cx.sess().opts.debuginfo == FullDebugInfo {
let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP); let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
let ident = token::get_ident(ident); let ident = token::get_ident(ident);
let name = CString::from_slice(ident.as_bytes()); let name = CString::new(ident.as_bytes()).unwrap();
let param_metadata = unsafe { let param_metadata = unsafe {
llvm::LLVMDIBuilderCreateTemplateTypeParameter( llvm::LLVMDIBuilderCreateTemplateTypeParameter(
DIB(cx), DIB(cx),
@ -1601,7 +1601,7 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
path_bytes.insert(1, prefix[1]); path_bytes.insert(1, prefix[1]);
} }
CString::from_vec(path_bytes) CString::new(path_bytes).unwrap()
} }
_ => fallback_path(cx) _ => fallback_path(cx)
} }
@ -1614,8 +1614,8 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
(option_env!("CFG_VERSION")).expect("CFG_VERSION")); (option_env!("CFG_VERSION")).expect("CFG_VERSION"));
let compile_unit_name = compile_unit_name.as_ptr(); let compile_unit_name = compile_unit_name.as_ptr();
let work_dir = CString::from_slice(work_dir.as_vec()); let work_dir = CString::new(work_dir.as_vec()).unwrap();
let producer = CString::from_slice(producer.as_bytes()); let producer = CString::new(producer).unwrap();
let flags = "\0"; let flags = "\0";
let split_name = "\0"; let split_name = "\0";
return unsafe { return unsafe {
@ -1632,7 +1632,7 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
}; };
fn fallback_path(cx: &CrateContext) -> CString { fn fallback_path(cx: &CrateContext) -> CString {
CString::from_slice(cx.link_meta().crate_name.as_bytes()) CString::new(cx.link_meta().crate_name.clone()).unwrap()
} }
} }
@ -1658,7 +1658,7 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
CapturedVariable => (0, DW_TAG_auto_variable) CapturedVariable => (0, DW_TAG_auto_variable)
}; };
let name = CString::from_slice(name.as_bytes()); let name = CString::new(name.as_bytes()).unwrap();
match (variable_access, [].as_slice()) { match (variable_access, [].as_slice()) {
(DirectVariable { alloca }, address_operations) | (DirectVariable { alloca }, address_operations) |
(IndirectVariable {alloca, address_operations}, _) => { (IndirectVariable {alloca, address_operations}, _) => {
@ -1724,8 +1724,8 @@ fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
full_path full_path
}; };
let file_name = CString::from_slice(file_name.as_bytes()); let file_name = CString::new(file_name).unwrap();
let work_dir = CString::from_slice(work_dir.as_bytes()); let work_dir = CString::new(work_dir).unwrap();
let file_metadata = unsafe { let file_metadata = unsafe {
llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name.as_ptr(), llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name.as_ptr(),
work_dir.as_ptr()) work_dir.as_ptr())
@ -1800,7 +1800,7 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let llvm_type = type_of::type_of(cx, t); let llvm_type = type_of::type_of(cx, t);
let (size, align) = size_and_align_of(cx, llvm_type); let (size, align) = size_and_align_of(cx, llvm_type);
let name = CString::from_slice(name.as_bytes()); let name = CString::new(name).unwrap();
let ty_metadata = unsafe { let ty_metadata = unsafe {
llvm::LLVMDIBuilderCreateBasicType( llvm::LLVMDIBuilderCreateBasicType(
DIB(cx), DIB(cx),
@ -1820,7 +1820,7 @@ fn pointer_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let pointer_llvm_type = type_of::type_of(cx, pointer_type); let pointer_llvm_type = type_of::type_of(cx, pointer_type);
let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type); let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
let name = compute_debuginfo_type_name(cx, pointer_type, false); let name = compute_debuginfo_type_name(cx, pointer_type, false);
let name = CString::from_slice(name.as_bytes()); let name = CString::new(name).unwrap();
let ptr_metadata = unsafe { let ptr_metadata = unsafe {
llvm::LLVMDIBuilderCreatePointerType( llvm::LLVMDIBuilderCreatePointerType(
DIB(cx), DIB(cx),
@ -2445,7 +2445,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
.iter() .iter()
.map(|v| { .map(|v| {
let token = token::get_name(v.name); let token = token::get_name(v.name);
let name = CString::from_slice(token.as_bytes()); let name = CString::new(token.as_bytes()).unwrap();
unsafe { unsafe {
llvm::LLVMDIBuilderCreateEnumerator( llvm::LLVMDIBuilderCreateEnumerator(
DIB(cx), DIB(cx),
@ -2475,7 +2475,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
codemap::DUMMY_SP); codemap::DUMMY_SP);
let discriminant_name = get_enum_discriminant_name(cx, enum_def_id); let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
let name = CString::from_slice(discriminant_name.as_bytes()); let name = CString::new(discriminant_name.as_bytes()).unwrap();
let discriminant_type_metadata = unsafe { let discriminant_type_metadata = unsafe {
llvm::LLVMDIBuilderCreateEnumerationType( llvm::LLVMDIBuilderCreateEnumerationType(
DIB(cx), DIB(cx),
@ -2518,8 +2518,8 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
.borrow() .borrow()
.get_unique_type_id_as_string(unique_type_id); .get_unique_type_id_as_string(unique_type_id);
let enum_name = CString::from_slice(enum_name.as_bytes()); let enum_name = CString::new(enum_name).unwrap();
let unique_type_id_str = CString::from_slice(unique_type_id_str.as_bytes()); let unique_type_id_str = CString::new(unique_type_id_str.as_bytes()).unwrap();
let enum_metadata = unsafe { let enum_metadata = unsafe {
llvm::LLVMDIBuilderCreateUnionType( llvm::LLVMDIBuilderCreateUnionType(
DIB(cx), DIB(cx),
@ -2644,7 +2644,8 @@ fn set_members_of_composite_type(cx: &CrateContext,
ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i) ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
}; };
let member_name = CString::from_slice(member_description.name.as_bytes()); let member_name = member_description.name.as_bytes();
let member_name = CString::new(member_name).unwrap();
unsafe { unsafe {
llvm::LLVMDIBuilderCreateMemberType( llvm::LLVMDIBuilderCreateMemberType(
DIB(cx), DIB(cx),
@ -2681,8 +2682,8 @@ fn create_struct_stub(cx: &CrateContext,
let unique_type_id_str = debug_context(cx).type_map let unique_type_id_str = debug_context(cx).type_map
.borrow() .borrow()
.get_unique_type_id_as_string(unique_type_id); .get_unique_type_id_as_string(unique_type_id);
let name = CString::from_slice(struct_type_name.as_bytes()); let name = CString::new(struct_type_name).unwrap();
let unique_type_id = CString::from_slice(unique_type_id_str.as_bytes()); let unique_type_id = CString::new(unique_type_id_str.as_bytes()).unwrap();
let metadata_stub = unsafe { let metadata_stub = unsafe {
// LLVMDIBuilderCreateStructType() wants an empty array. A null // LLVMDIBuilderCreateStructType() wants an empty array. A null
// pointer will lead to hard to trace and debug LLVM assertions // pointer will lead to hard to trace and debug LLVM assertions
@ -3971,8 +3972,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTree
None => ptr::null_mut() None => ptr::null_mut()
}; };
let namespace_name = token::get_name(name); let namespace_name = token::get_name(name);
let namespace_name = CString::from_slice(namespace_name let namespace_name = CString::new(namespace_name.as_bytes()).unwrap();
.as_bytes());
let scope = unsafe { let scope = unsafe {
llvm::LLVMDIBuilderCreateNameSpace( llvm::LLVMDIBuilderCreateNameSpace(
DIB(cx), DIB(cx),
@ -4020,7 +4020,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTree
/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker. /// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext) { pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext) {
if needs_gdb_debug_scripts_section(ccx) { if needs_gdb_debug_scripts_section(ccx) {
let empty = CString::from_slice(b""); let empty = CString::new(b"").unwrap();
let gdb_debug_scripts_section_global = let gdb_debug_scripts_section_global =
get_or_insert_gdb_debug_scripts_section_global(ccx); get_or_insert_gdb_debug_scripts_section_global(ccx);
unsafe { unsafe {

View File

@ -135,7 +135,7 @@ pub fn register_static(ccx: &CrateContext,
}; };
unsafe { unsafe {
// Declare a symbol `foo` with the desired linkage. // Declare a symbol `foo` with the desired linkage.
let buf = CString::from_slice(ident.as_bytes()); let buf = CString::new(ident.as_bytes()).unwrap();
let g1 = llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(), let g1 = llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(),
buf.as_ptr()); buf.as_ptr());
llvm::SetLinkage(g1, linkage); llvm::SetLinkage(g1, linkage);
@ -148,7 +148,7 @@ pub fn register_static(ccx: &CrateContext,
// zero. // zero.
let mut real_name = "_rust_extern_with_linkage_".to_string(); let mut real_name = "_rust_extern_with_linkage_".to_string();
real_name.push_str(&ident); real_name.push_str(&ident);
let real_name = CString::from_vec(real_name.into_bytes()); let real_name = CString::new(real_name).unwrap();
let g2 = llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), let g2 = llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(),
real_name.as_ptr()); real_name.as_ptr());
llvm::SetLinkage(g2, llvm::InternalLinkage); llvm::SetLinkage(g2, llvm::InternalLinkage);
@ -158,7 +158,7 @@ pub fn register_static(ccx: &CrateContext,
} }
None => unsafe { None => unsafe {
// Generate an external declaration. // Generate an external declaration.
let buf = CString::from_slice(ident.as_bytes()); let buf = CString::new(ident.as_bytes()).unwrap();
llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf.as_ptr()) llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf.as_ptr())
} }
} }

View File

@ -513,7 +513,7 @@ pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
let llalign = llalign_of(ccx, llty); let llalign = llalign_of(ccx, llty);
let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc"); let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc");
debug!("+++ declare_tydesc {} {}", ppaux::ty_to_string(ccx.tcx(), t), name); debug!("+++ declare_tydesc {} {}", ppaux::ty_to_string(ccx.tcx(), t), name);
let buf = CString::from_slice(name.as_bytes()); let buf = CString::new(name.clone()).unwrap();
let gvar = unsafe { let gvar = unsafe {
llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(), llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(),
buf.as_ptr()) buf.as_ptr())

View File

@ -163,7 +163,7 @@ impl Type {
} }
pub fn named_struct(ccx: &CrateContext, name: &str) -> Type { pub fn named_struct(ccx: &CrateContext, name: &str) -> Type {
let name = CString::from_slice(name.as_bytes()); let name = CString::new(name).unwrap();
ty!(llvm::LLVMStructCreateNamed(ccx.llcx(), name.as_ptr())) ty!(llvm::LLVMStructCreateNamed(ccx.llcx(), name.as_ptr()))
} }

View File

@ -112,7 +112,7 @@ mod imp {
impl Lock { impl Lock {
pub fn new(p: &Path) -> Lock { pub fn new(p: &Path) -> Lock {
let buf = CString::from_slice(p.as_vec()); let buf = CString::from_slice(p.as_vec()).unwrap();
let fd = unsafe { let fd = unsafe {
libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT, libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT,
libc::S_IRWXU) libc::S_IRWXU)

View File

@ -236,7 +236,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
s.push_str(&highlight::highlight(&text, s.push_str(&highlight::highlight(&text,
None, None,
Some("rust-example-rendered"))); Some("rust-example-rendered")));
let output = CString::from_vec(s.into_bytes()); let output = CString::from_vec(s.into_bytes()).unwrap();
hoedown_buffer_puts(ob, output.as_ptr()); hoedown_buffer_puts(ob, output.as_ptr());
}) })
} }
@ -293,7 +293,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
format!("{} ", sec) format!("{} ", sec)
}); });
let text = CString::from_vec(text.into_bytes()); let text = CString::from_vec(text.into_bytes()).unwrap();
unsafe { hoedown_buffer_puts(ob, text.as_ptr()) } unsafe { hoedown_buffer_puts(ob, text.as_ptr()) }
} }

View File

@ -112,7 +112,7 @@ impl DynamicLibrary {
// This function should have a lifetime constraint of 'a on // This function should have a lifetime constraint of 'a on
// T but that feature is still unimplemented // T but that feature is still unimplemented
let raw_string = CString::from_slice(symbol.as_bytes()); let raw_string = CString::new(symbol).unwrap();
let maybe_symbol_value = dl::check_for_errors_in(|| { let maybe_symbol_value = dl::check_for_errors_in(|| {
dl::symbol(self.handle, raw_string.as_ptr()) dl::symbol(self.handle, raw_string.as_ptr())
}); });
@ -187,7 +187,7 @@ mod test {
mod dl { mod dl {
use prelude::v1::*; use prelude::v1::*;
use ffi::{self, CString}; use ffi::{CString, CStr};
use str; use str;
use libc; use libc;
use ptr; use ptr;
@ -206,7 +206,7 @@ mod dl {
const LAZY: libc::c_int = 1; const LAZY: libc::c_int = 1;
unsafe fn open_external(filename: &[u8]) -> *mut u8 { unsafe fn open_external(filename: &[u8]) -> *mut u8 {
let s = CString::from_slice(filename); let s = CString::new(filename).unwrap();
dlopen(s.as_ptr(), LAZY) as *mut u8 dlopen(s.as_ptr(), LAZY) as *mut u8
} }
@ -231,7 +231,7 @@ mod dl {
let ret = if ptr::null() == last_error { let ret = if ptr::null() == last_error {
Ok(result) Ok(result)
} else { } else {
let s = ffi::c_str_to_bytes(&last_error); let s = CStr::from_ptr(last_error).to_bytes();
Err(str::from_utf8(s).unwrap().to_string()) Err(str::from_utf8(s).unwrap().to_string())
}; };

View File

@ -8,18 +8,25 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use error::{Error, FromError};
use fmt; use fmt;
use io;
use iter::IteratorExt; use iter::IteratorExt;
use libc; use libc;
use mem; use mem;
use old_io;
use ops::Deref; use ops::Deref;
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
use slice::{self, SliceExt}; use slice::{self, SliceExt};
use str::StrExt;
use string::String; use string::String;
use vec::Vec; use vec::Vec;
/// A type representing a C-compatible string /// A type representing an owned C-compatible string
/// ///
/// This type serves the primary purpose of being able to generate a /// This type serves the primary purpose of being able to safely generate a
/// C-compatible string from a Rust byte slice or vector. An instance of this /// C-compatible string from a Rust byte slice or vector. An instance of this
/// type is a static guarantee that the underlying bytes contain no interior 0 /// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes and the final byte is 0. /// bytes and the final byte is 0.
@ -44,8 +51,8 @@ use vec::Vec;
/// fn my_printer(s: *const libc::c_char); /// fn my_printer(s: *const libc::c_char);
/// } /// }
/// ///
/// let to_print = "Hello, world!"; /// let to_print = b"Hello, world!";
/// let c_to_print = CString::from_slice(to_print.as_bytes()); /// let c_to_print = CString::new(to_print).unwrap();
/// unsafe { /// unsafe {
/// my_printer(c_to_print.as_ptr()); /// my_printer(c_to_print.as_ptr());
/// } /// }
@ -53,19 +60,135 @@ use vec::Vec;
/// ``` /// ```
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct CString { pub struct CString {
inner: Vec<libc::c_char>, inner: Vec<u8>,
}
/// Representation of a borrowed C string.
///
/// This dynamically sized type is only safely constructed via a borrowed
/// version of an instance of `CString`. This type can be constructed from a raw
/// C string as well and represents a C string borrowed from another location.
///
/// Note that this structure is **not** `repr(C)` and is not recommended to be
/// placed in the signatures of FFI functions. Instead safe wrappers of FFI
/// functions may leverage the unsafe `from_ptr` constructor to provide a safe
/// interface to other consumers.
///
/// # Examples
///
/// Inspecting a foreign C string
///
/// ```no_run
/// extern crate libc;
/// use std::ffi::CStr;
///
/// extern { fn my_string() -> *const libc::c_char; }
///
/// fn main() {
/// unsafe {
/// let slice = CStr::from_ptr(my_string());
/// println!("string length: {}", slice.to_bytes().len());
/// }
/// }
/// ```
///
/// Passing a Rust-originating C string
///
/// ```no_run
/// extern crate libc;
/// use std::ffi::{CString, CStr};
///
/// fn work(data: &CStr) {
/// extern { fn work_with(data: *const libc::c_char); }
///
/// unsafe { work_with(data.as_ptr()) }
/// }
///
/// fn main() {
/// let s = CString::from_slice(b"data data data data").unwrap();
/// work(&s);
/// }
/// ```
#[derive(Hash)]
pub struct CStr {
inner: [libc::c_char]
}
/// An error returned from `CString::new` to indicate that a nul byte was found
/// in the vector provided.
#[derive(Clone, PartialEq, Debug)]
pub struct NulError(usize, Vec<u8>);
/// A conversion trait used by the constructor of `CString` for types that can
/// be converted to a vector of bytes.
pub trait IntoBytes {
/// Consumes this container, returning a vector of bytes.
fn into_bytes(self) -> Vec<u8>;
} }
impl CString { impl CString {
/// Create a new C-compatible string from a container of bytes.
///
/// This method will consume the provided data and use the underlying bytes
/// to construct a new string, ensuring that there is a trailing 0 byte.
///
/// # Examples
///
/// ```no_run
/// extern crate libc;
/// use std::ffi::CString;
///
/// extern { fn puts(s: *const libc::c_char); }
///
/// fn main() {
/// let to_print = CString::from_slice(b"Hello!").unwrap();
/// unsafe {
/// puts(to_print.as_ptr());
/// }
/// }
/// ```
///
/// # Errors
///
/// This function will return an error if the bytes yielded contain an
/// internal 0 byte. The error returned will contain the bytes as well as
/// the position of the nul byte.
pub fn new<T: IntoBytes>(t: T) -> Result<CString, NulError> {
let bytes = t.into_bytes();
match bytes.iter().position(|x| *x == 0) {
Some(i) => Err(NulError(i, bytes)),
None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
}
}
/// Create a new C-compatible string from a byte slice. /// Create a new C-compatible string from a byte slice.
/// ///
/// This method will copy the data of the slice provided into a new /// This method will copy the data of the slice provided into a new
/// allocation, ensuring that there is a trailing 0 byte. /// allocation, ensuring that there is a trailing 0 byte.
/// ///
/// # Examples
///
/// ```no_run
/// extern crate libc;
/// use std::ffi::CString;
///
/// extern { fn puts(s: *const libc::c_char); }
///
/// fn main() {
/// let to_print = CString::from_slice(b"Hello!").unwrap();
/// unsafe {
/// puts(to_print.as_ptr());
/// }
/// }
/// ```
///
/// # Panics /// # Panics
/// ///
/// This function will panic if there are any 0 bytes already in the slice /// This function will panic if the provided slice contains any
/// provided. /// interior nul bytes.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0", reason = "use CString::new instead")]
#[allow(deprecated)]
pub fn from_slice(v: &[u8]) -> CString { pub fn from_slice(v: &[u8]) -> CString {
CString::from_vec(v.to_vec()) CString::from_vec(v.to_vec())
} }
@ -77,11 +200,15 @@ impl CString {
/// ///
/// # Panics /// # Panics
/// ///
/// This function will panic if there are any 0 bytes already in the vector /// This function will panic if the provided slice contains any
/// provided. /// interior nul bytes.
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0", reason = "use CString::new instead")]
pub fn from_vec(v: Vec<u8>) -> CString { pub fn from_vec(v: Vec<u8>) -> CString {
assert!(!v.iter().any(|&x| x == 0)); match v.iter().position(|x| *x == 0) {
unsafe { CString::from_vec_unchecked(v) } Some(i) => panic!("null byte found in slice at: {}", i),
None => unsafe { CString::from_vec_unchecked(v) },
}
} }
/// Create a C-compatible string from a byte vector without checking for /// Create a C-compatible string from a byte vector without checking for
@ -91,31 +218,29 @@ impl CString {
/// is made that `v` contains no 0 bytes. /// is made that `v` contains no 0 bytes.
pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString { pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
v.push(0); v.push(0);
CString { inner: mem::transmute(v) } CString { inner: v }
} }
/// Create a view into this C string which includes the trailing nul /// Returns the contents of this `CString` as a slice of bytes.
/// terminator at the end of the string. ///
pub fn as_slice_with_nul(&self) -> &[libc::c_char] { &self.inner } /// The returned slice does **not** contain the trailing nul separator and
/// it is guaranteet to not have any interior nul bytes.
/// Similar to the `as_slice` method, but returns a `u8` slice instead of a
/// `libc::c_char` slice.
pub fn as_bytes(&self) -> &[u8] { pub fn as_bytes(&self) -> &[u8] {
unsafe { mem::transmute(&**self) } &self.inner[..self.inner.len() - 1]
} }
/// Equivalent to `as_slice_with_nul` except that the type returned is a /// Equivalent to the `as_bytes` function except that the returned slice
/// `u8` slice instead of a `libc::c_char` slice. /// includes the trailing nul byte.
pub fn as_bytes_with_nul(&self) -> &[u8] { pub fn as_bytes_with_nul(&self) -> &[u8] {
unsafe { mem::transmute(self.as_slice_with_nul()) } &self.inner
} }
} }
impl Deref for CString { impl Deref for CString {
type Target = [libc::c_char]; type Target = CStr;
fn deref(&self) -> &[libc::c_char] { fn deref(&self) -> &CStr {
&self.inner[..(self.inner.len() - 1)] unsafe { mem::transmute(self.as_bytes_with_nul()) }
} }
} }
@ -126,54 +251,172 @@ impl fmt::Debug for CString {
} }
} }
/// Interpret a C string as a byte slice. impl NulError {
/// /// Returns the position of the nul byte in the slice that was provided to
/// This function will calculate the length of the C string provided, and it /// `CString::from_vec`.
/// will then return a corresponding slice for the contents of the C string not pub fn nul_position(&self) -> usize { self.0 }
/// including the nul terminator.
/// /// Consumes this error, returning the underlying vector of bytes which
/// This function will tie the lifetime of the returned slice to the lifetime of /// generated the error in the first place.
/// the pointer provided. This is done to help prevent the slice from escaping pub fn into_vec(self) -> Vec<u8> { self.1 }
/// the lifetime of the pointer itself. If a longer lifetime is needed, then }
/// `mem::copy_lifetime` should be used.
/// impl Error for NulError {
/// This function is unsafe because there is no guarantee of the validity of the fn description(&self) -> &str { "nul byte found in data" }
/// pointer `raw` or a guarantee that a nul terminator will be found. }
///
/// # Example impl fmt::Display for NulError {
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// ```no_run write!(f, "nul byte found in provided data at position: {}", self.0)
/// # extern crate libc; }
/// # fn main() { }
/// use std::ffi;
/// use std::str; impl FromError<NulError> for io::Error {
/// use libc; fn from_error(_: NulError) -> io::Error {
/// io::Error::new(io::ErrorKind::InvalidInput,
/// extern { "data provided contains a nul byte", None)
/// fn my_string() -> *const libc::c_char; }
/// } }
///
/// unsafe { impl FromError<NulError> for old_io::IoError {
/// let to_print = my_string(); fn from_error(_: NulError) -> old_io::IoError {
/// let slice = ffi::c_str_to_bytes(&to_print); old_io::IoError {
/// println!("string returned: {}", str::from_utf8(slice).unwrap()); kind: old_io::IoErrorKind::InvalidInput,
/// } desc: "data provided contains a nul byte",
/// # } detail: None
/// ``` }
}
}
impl CStr {
/// Cast a raw C string to a safe C string wrapper.
///
/// This function will cast the provided `ptr` to the `CStr` wrapper which
/// allows inspection and interoperation of non-owned C strings. This method
/// is unsafe for a number of reasons:
///
/// * There is no guarantee to the validity of `ptr`
/// * The returned lifetime is not guaranteed to be the actual lifetime of
/// `ptr`
/// * There is no guarantee that the memory pointed to by `ptr` contains a
/// valid nul terminator byte at the end of the string.
///
/// > **Note**: This operation is intended to be a 0-cost cast but it is
/// > currently implemented with an up-front calculation of the length of
/// > the string. This is not guaranteed to always be the case.
///
/// # Example
///
/// ```no_run
/// # extern crate libc;
/// # fn main() {
/// use std::ffi::CStr;
/// use std::str;
/// use libc;
///
/// extern {
/// fn my_string() -> *const libc::c_char;
/// }
///
/// unsafe {
/// let slice = CStr::from_ptr(my_string());
/// println!("string returned: {}",
/// str::from_utf8(slice.to_bytes()).unwrap());
/// }
/// # }
/// ```
pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr {
let len = libc::strlen(ptr);
mem::transmute(slice::from_raw_parts(ptr, len as usize + 1))
}
/// Return the inner pointer to this C string.
///
/// The returned pointer will be valid for as long as `self` is and points
/// to a continguous region of memory terminated with a 0 byte to represent
/// the end of the string.
pub fn as_ptr(&self) -> *const libc::c_char {
self.inner.as_ptr()
}
/// Convert this C string to a byte slice.
///
/// This function will calculate the length of this string (which normally
/// requires a linear amount of work to be done) and then return the
/// resulting slice of `u8` elements.
///
/// The returned slice will **not** contain the trailing nul that this C
/// string has.
///
/// > **Note**: This method is currently implemented as a 0-cost cast, but
/// > it is planned to alter its definition in the future to perform the
/// > length calculation whenever this method is called.
pub fn to_bytes(&self) -> &[u8] {
let bytes = self.to_bytes_with_nul();
&bytes[..bytes.len() - 1]
}
/// Convert this C string to a byte slice containing the trailing 0 byte.
///
/// This function is the equivalent of `to_bytes` except that it will retain
/// the trailing nul instead of chopping it off.
///
/// > **Note**: This method is currently implemented as a 0-cost cast, but
/// > it is planned to alter its definition in the future to perform the
/// > length calculation whenever this method is called.
pub fn to_bytes_with_nul(&self) -> &[u8] {
unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) }
}
}
impl PartialEq for CStr {
fn eq(&self, other: &CStr) -> bool {
self.to_bytes().eq(&other.to_bytes())
}
}
impl Eq for CStr {}
impl PartialOrd for CStr {
fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
self.to_bytes().partial_cmp(&other.to_bytes())
}
}
impl Ord for CStr {
fn cmp(&self, other: &CStr) -> Ordering {
self.to_bytes().cmp(&other.to_bytes())
}
}
/// Deprecated in favor of `CStr`
#[unstable(feature = "std_misc")]
#[deprecated(since = "1.0.0", reason = "use CStr::from_ptr(p).to_bytes() instead")]
pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] { pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
let len = libc::strlen(*raw); let len = libc::strlen(*raw);
slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize) slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize)
} }
/// Interpret a C string as a byte slice with the nul terminator. /// Deprecated in favor of `CStr`
/// #[unstable(feature = "std_misc")]
/// This function is identical to `from_raw_buf` except that the returned slice #[deprecated(since = "1.0.0",
/// will include the nul terminator of the string. reason = "use CStr::from_ptr(p).to_bytes_with_nul() instead")]
pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char) -> &'a [u8] { pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char)
-> &'a [u8] {
let len = libc::strlen(*raw) + 1; let len = libc::strlen(*raw) + 1;
slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize) slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize)
} }
impl<'a> IntoBytes for &'a str {
fn into_bytes(self) -> Vec<u8> { self.as_bytes().to_vec() }
}
impl<'a> IntoBytes for &'a [u8] {
fn into_bytes(self) -> Vec<u8> { self.to_vec() }
}
impl IntoBytes for String {
fn into_bytes(self) -> Vec<u8> { self.into_bytes() }
}
impl IntoBytes for Vec<u8> {
fn into_bytes(self) -> Vec<u8> { self }
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use prelude::v1::*; use prelude::v1::*;
@ -193,21 +436,19 @@ mod tests {
#[test] #[test]
fn simple() { fn simple() {
let s = CString::from_slice(b"1234"); let s = CString::from_slice(b"1234").unwrap();
assert_eq!(s.as_bytes(), b"1234"); assert_eq!(s.as_bytes(), b"1234");
assert_eq!(s.as_bytes_with_nul(), b"1234\0"); assert_eq!(s.as_bytes_with_nul(), b"1234\0");
unsafe {
assert_eq!(&*s,
mem::transmute::<_, &[libc::c_char]>(b"1234"));
assert_eq!(s.as_slice_with_nul(),
mem::transmute::<_, &[libc::c_char]>(b"1234\0"));
}
} }
#[should_fail] #[test] #[test]
fn build_with_zero1() { CString::from_slice(b"\0"); } fn build_with_zero1() {
#[should_fail] #[test] assert!(CString::from_slice(b"\0").is_err());
fn build_with_zero2() { CString::from_vec(vec![0]); } }
#[test]
fn build_with_zero2() {
assert!(CString::from_vec(vec![0]).is_err());
}
#[test] #[test]
fn build_with_zero3() { fn build_with_zero3() {
@ -219,7 +460,16 @@ mod tests {
#[test] #[test]
fn formatted() { fn formatted() {
let s = CString::from_slice(b"12"); let s = CString::from_slice(b"12").unwrap();
assert_eq!(format!("{:?}", s), "\"12\""); assert_eq!(format!("{:?}", s), "\"12\"");
} }
#[test]
fn borrowed() {
unsafe {
let s = CStr::from_ptr(b"12\0".as_ptr() as *const _);
assert_eq!(s.to_bytes(), b"12");
assert_eq!(s.to_bytes_with_nul(), b"12\0");
}
}
} }

View File

@ -14,8 +14,10 @@
reason = "module just underwent fairly large reorganization and the dust \ reason = "module just underwent fairly large reorganization and the dust \
still needs to settle")] still needs to settle")]
pub use self::c_str::CString; pub use self::c_str::{CString, CStr, NulError, IntoBytes};
#[allow(deprecated)]
pub use self::c_str::c_str_to_bytes; pub use self::c_str::c_str_to_bytes;
#[allow(deprecated)]
pub use self::c_str::c_str_to_bytes_with_nul; pub use self::c_str::c_str_to_bytes_with_nul;
pub use self::os_str::OsString; pub use self::os_str::OsString;

View File

@ -55,7 +55,7 @@ impl UnixStream {
/// stream.write(&[1, 2, 3]); /// stream.write(&[1, 2, 3]);
/// ``` /// ```
pub fn connect<P: BytesContainer>(path: P) -> IoResult<UnixStream> { pub fn connect<P: BytesContainer>(path: P) -> IoResult<UnixStream> {
let path = CString::from_slice(path.container_as_bytes()); let path = try!(CString::new(path.container_as_bytes()));
UnixStreamImp::connect(&path, None) UnixStreamImp::connect(&path, None)
.map(|inner| UnixStream { inner: inner }) .map(|inner| UnixStream { inner: inner })
} }
@ -77,7 +77,7 @@ impl UnixStream {
return Err(standard_error(TimedOut)); return Err(standard_error(TimedOut));
} }
let path = CString::from_slice(path.container_as_bytes()); let path = try!(CString::new(path.container_as_bytes()));
UnixStreamImp::connect(&path, Some(timeout.num_milliseconds() as u64)) UnixStreamImp::connect(&path, Some(timeout.num_milliseconds() as u64))
.map(|inner| UnixStream { inner: inner }) .map(|inner| UnixStream { inner: inner })
} }
@ -184,7 +184,7 @@ impl UnixListener {
/// # } /// # }
/// ``` /// ```
pub fn bind<P: BytesContainer>(path: P) -> IoResult<UnixListener> { pub fn bind<P: BytesContainer>(path: P) -> IoResult<UnixListener> {
let path = CString::from_slice(path.container_as_bytes()); let path = try!(CString::new(path.container_as_bytes()));
UnixListenerImp::bind(&path) UnixListenerImp::bind(&path)
.map(|inner| UnixListener { inner: inner }) .map(|inner| UnixListener { inner: inner })
} }

View File

@ -204,7 +204,7 @@ impl Command {
/// otherwise configure the process. /// otherwise configure the process.
pub fn new<T: BytesContainer>(program: T) -> Command { pub fn new<T: BytesContainer>(program: T) -> Command {
Command { Command {
program: CString::from_slice(program.container_as_bytes()), program: CString::new(program.container_as_bytes()).unwrap(),
args: Vec::new(), args: Vec::new(),
env: None, env: None,
cwd: None, cwd: None,
@ -219,14 +219,14 @@ impl Command {
/// Add an argument to pass to the program. /// Add an argument to pass to the program.
pub fn arg<'a, T: BytesContainer>(&'a mut self, arg: T) -> &'a mut Command { pub fn arg<'a, T: BytesContainer>(&'a mut self, arg: T) -> &'a mut Command {
self.args.push(CString::from_slice(arg.container_as_bytes())); self.args.push(CString::new(arg.container_as_bytes()).unwrap());
self self
} }
/// Add multiple arguments to pass to the program. /// Add multiple arguments to pass to the program.
pub fn args<'a, T: BytesContainer>(&'a mut self, args: &[T]) -> &'a mut Command { pub fn args<'a, T: BytesContainer>(&'a mut self, args: &[T]) -> &'a mut Command {
self.args.extend(args.iter().map(|arg| { self.args.extend(args.iter().map(|arg| {
CString::from_slice(arg.container_as_bytes()) CString::new(arg.container_as_bytes()).unwrap()
})); }));
self self
} }
@ -239,8 +239,8 @@ impl Command {
// if the env is currently just inheriting from the parent's, // if the env is currently just inheriting from the parent's,
// materialize the parent's env into a hashtable. // materialize the parent's env into a hashtable.
self.env = Some(os::env_as_bytes().into_iter().map(|(k, v)| { self.env = Some(os::env_as_bytes().into_iter().map(|(k, v)| {
(EnvKey(CString::from_slice(&k)), (EnvKey(CString::new(k).unwrap()),
CString::from_slice(&v)) CString::new(v).unwrap())
}).collect()); }).collect());
self.env.as_mut().unwrap() self.env.as_mut().unwrap()
} }
@ -254,8 +254,8 @@ impl Command {
pub fn env<'a, T, U>(&'a mut self, key: T, val: U) pub fn env<'a, T, U>(&'a mut self, key: T, val: U)
-> &'a mut Command -> &'a mut Command
where T: BytesContainer, U: BytesContainer { where T: BytesContainer, U: BytesContainer {
let key = EnvKey(CString::from_slice(key.container_as_bytes())); let key = EnvKey(CString::new(key.container_as_bytes()).unwrap());
let val = CString::from_slice(val.container_as_bytes()); let val = CString::new(val.container_as_bytes()).unwrap();
self.get_env_map().insert(key, val); self.get_env_map().insert(key, val);
self self
} }
@ -263,7 +263,7 @@ impl Command {
/// Removes an environment variable mapping. /// Removes an environment variable mapping.
pub fn env_remove<'a, T>(&'a mut self, key: T) -> &'a mut Command pub fn env_remove<'a, T>(&'a mut self, key: T) -> &'a mut Command
where T: BytesContainer { where T: BytesContainer {
let key = EnvKey(CString::from_slice(key.container_as_bytes())); let key = EnvKey(CString::new(key.container_as_bytes()).unwrap());
self.get_env_map().remove(&key); self.get_env_map().remove(&key);
self self
} }
@ -276,15 +276,15 @@ impl Command {
-> &'a mut Command -> &'a mut Command
where T: BytesContainer, U: BytesContainer { where T: BytesContainer, U: BytesContainer {
self.env = Some(env.iter().map(|&(ref k, ref v)| { self.env = Some(env.iter().map(|&(ref k, ref v)| {
(EnvKey(CString::from_slice(k.container_as_bytes())), (EnvKey(CString::new(k.container_as_bytes()).unwrap()),
CString::from_slice(v.container_as_bytes())) CString::new(v.container_as_bytes()).unwrap())
}).collect()); }).collect());
self self
} }
/// Set the working directory for the child process. /// Set the working directory for the child process.
pub fn cwd<'a>(&'a mut self, dir: &Path) -> &'a mut Command { pub fn cwd<'a>(&'a mut self, dir: &Path) -> &'a mut Command {
self.cwd = Some(CString::from_slice(dir.as_vec())); self.cwd = Some(CString::new(dir.as_vec()).unwrap());
self self
} }
@ -1226,7 +1226,7 @@ mod tests {
cmd.env("path", "foo"); cmd.env("path", "foo");
cmd.env("Path", "bar"); cmd.env("Path", "bar");
let env = &cmd.env.unwrap(); let env = &cmd.env.unwrap();
let val = env.get(&EnvKey(CString::from_slice(b"PATH"))); let val = env.get(&EnvKey(CString::new(b"PATH").unwrap()));
assert!(val.unwrap() == &CString::from_slice(b"bar")); assert!(val.unwrap() == &CString::new(b"bar").unwrap());
} }
} }

View File

@ -49,7 +49,7 @@ mod imp {
use libc; use libc;
use mem; use mem;
use ffi; use ffi::CStr;
use sync::{StaticMutex, MUTEX_INIT}; use sync::{StaticMutex, MUTEX_INIT};
@ -96,10 +96,11 @@ mod imp {
unsafe { mem::transmute(&GLOBAL_ARGS_PTR) } unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
} }
unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec<Vec<u8>> { unsafe fn load_argc_and_argv(argc: isize,
argv: *const *const u8) -> Vec<Vec<u8>> {
let argv = argv as *const *const libc::c_char; let argv = argv as *const *const libc::c_char;
(0..argc as uint).map(|i| { (0..argc).map(|i| {
ffi::c_str_to_bytes(&*argv.offset(i as int)).to_vec() CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec()
}).collect() }).collect()
} }

View File

@ -12,8 +12,7 @@ use prelude::v1::*;
use self::SocketStatus::*; use self::SocketStatus::*;
use self::InAddr::*; use self::InAddr::*;
use ffi::CString; use ffi::{CString, CStr};
use ffi;
use old_io::net::addrinfo; use old_io::net::addrinfo;
use old_io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr}; use old_io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr};
use old_io::{IoResult, IoError}; use old_io::{IoResult, IoError};
@ -235,9 +234,15 @@ pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>,
assert!(host.is_some() || servname.is_some()); assert!(host.is_some() || servname.is_some());
let c_host = host.map(|x| CString::from_slice(x.as_bytes())); let c_host = match host {
Some(x) => Some(try!(CString::new(x))),
None => None,
};
let c_host = c_host.as_ref().map(|x| x.as_ptr()).unwrap_or(null()); let c_host = c_host.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
let c_serv = servname.map(|x| CString::from_slice(x.as_bytes())); let c_serv = match servname {
Some(x) => Some(try!(CString::new(x))),
None => None,
};
let c_serv = c_serv.as_ref().map(|x| x.as_ptr()).unwrap_or(null()); let c_serv = c_serv.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
let hint = hint.map(|hint| { let hint = hint.map(|hint| {
@ -325,8 +330,8 @@ pub fn get_address_name(addr: IpAddr) -> Result<String, IoError> {
} }
unsafe { unsafe {
Ok(str::from_utf8(ffi::c_str_to_bytes(&hostbuf.as_ptr())) let data = CStr::from_ptr(hostbuf.as_ptr());
.unwrap().to_string()) Ok(str::from_utf8(data.to_bytes()).unwrap().to_string())
} }
} }

View File

@ -121,7 +121,7 @@ impl Drop for LookupHost {
pub fn lookup_host(host: &str) -> io::Result<LookupHost> { pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
init(); init();
let c_host = CString::from_slice(host.as_bytes()); let c_host = try!(CString::new(host));
let mut res = 0 as *mut _; let mut res = 0 as *mut _;
unsafe { unsafe {
try!(cvt_gai(getaddrinfo(c_host.as_ptr(), 0 as *const _, 0 as *const _, try!(cvt_gai(getaddrinfo(c_host.as_ptr(), 0 as *const _, 0 as *const _,

View File

@ -85,7 +85,7 @@
use prelude::v1::*; use prelude::v1::*;
use ffi; use ffi::CStr;
use old_io::IoResult; use old_io::IoResult;
use libc; use libc;
use mem; use mem;
@ -233,7 +233,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
output(w, idx,addr, None) output(w, idx,addr, None)
} else { } else {
output(w, idx, addr, Some(unsafe { output(w, idx, addr, Some(unsafe {
ffi::c_str_to_bytes(&info.dli_sname) CStr::from_ptr(info.dli_sname).to_bytes()
})) }))
} }
} }
@ -364,7 +364,7 @@ fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
if ret == 0 || data.is_null() { if ret == 0 || data.is_null() {
output(w, idx, addr, None) output(w, idx, addr, None)
} else { } else {
output(w, idx, addr, Some(unsafe { ffi::c_str_to_bytes(&data) })) output(w, idx, addr, Some(unsafe { CStr::from_ptr(data).to_bytes() }))
} }
} }

View File

@ -33,7 +33,7 @@
use prelude::v1::*; use prelude::v1::*;
use ffi::{CString, OsStr, OsString}; use ffi::{CString, NulError, OsStr, OsString};
use fs::{self, Permissions, OpenOptions}; use fs::{self, Permissions, OpenOptions};
use net; use net;
use mem; use mem;
@ -155,7 +155,7 @@ pub trait OsStrExt {
fn as_bytes(&self) -> &[u8]; fn as_bytes(&self) -> &[u8];
/// Convert the `OsStr` slice into a `CString`. /// Convert the `OsStr` slice into a `CString`.
fn to_cstring(&self) -> CString; fn to_cstring(&self) -> Result<CString, NulError>;
} }
impl OsStrExt for OsStr { impl OsStrExt for OsStr {
@ -166,8 +166,8 @@ impl OsStrExt for OsStr {
&self.as_inner().inner &self.as_inner().inner
} }
fn to_cstring(&self) -> CString { fn to_cstring(&self) -> Result<CString, NulError> {
CString::from_slice(self.as_bytes()) CString::new(self.as_bytes())
} }
} }
@ -249,5 +249,7 @@ impl ExitStatusExt for process::ExitStatus {
/// Includes all extension traits, and some important type definitions. /// Includes all extension traits, and some important type definitions.
pub mod prelude { pub mod prelude {
#[doc(no_inline)] #[doc(no_inline)]
pub use super::{Fd, AsRawFd, OsStrExt, OsStringExt, PermissionsExt, CommandExt, ExitStatusExt}; pub use super::{Fd, AsRawFd, OsStrExt, OsStringExt, PermissionsExt};
#[doc(no_inline)]
pub use super::{CommandExt, ExitStatusExt};
} }

View File

@ -12,7 +12,7 @@
use prelude::v1::*; use prelude::v1::*;
use ffi::{self, CString}; use ffi::{CString, CStr};
use old_io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode}; use old_io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
use old_io::{IoResult, FileStat, SeekStyle}; use old_io::{IoResult, FileStat, SeekStyle};
use old_io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append}; use old_io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
@ -151,8 +151,8 @@ impl Drop for FileDesc {
} }
} }
fn cstr(path: &Path) -> CString { fn cstr(path: &Path) -> IoResult<CString> {
CString::from_slice(path.as_vec()) Ok(try!(CString::new(path.as_vec())))
} }
pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> { 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), 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) }) { match retry(|| unsafe { libc::open(path.as_ptr(), flags, mode) }) {
-1 => Err(super::last_error()), -1 => Err(super::last_error()),
fd => Ok(FileDesc::new(fd, true)), 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<()> { 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) }) 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 mut buf = Vec::<u8>::with_capacity(size as uint);
let ptr = buf.as_mut_ptr() as *mut dirent_t; 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())}; let dir_ptr = unsafe {opendir(p.as_ptr())};
if dir_ptr as uint != 0 { 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 } { while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } {
if entry_ptr.is_null() { break } if entry_ptr.is_null() { break }
paths.push(unsafe { 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); 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<()> { pub fn unlink(p: &Path) -> IoResult<()> {
let p = cstr(p); let p = try!(cstr(p));
mkerr_libc(unsafe { libc::unlink(p.as_ptr()) }) mkerr_libc(unsafe { libc::unlink(p.as_ptr()) })
} }
pub fn rename(old: &Path, new: &Path) -> IoResult<()> { pub fn rename(old: &Path, new: &Path) -> IoResult<()> {
let old = cstr(old); let old = try!(cstr(old));
let new = cstr(new); let new = try!(cstr(new));
mkerr_libc(unsafe { mkerr_libc(unsafe {
libc::rename(old.as_ptr(), new.as_ptr()) libc::rename(old.as_ptr(), new.as_ptr())
}) })
} }
pub fn chmod(p: &Path, mode: uint) -> IoResult<()> { pub fn chmod(p: &Path, mode: uint) -> IoResult<()> {
let p = cstr(p); let p = try!(cstr(p));
mkerr_libc(retry(|| unsafe { mkerr_libc(retry(|| unsafe {
libc::chmod(p.as_ptr(), mode as libc::mode_t) libc::chmod(p.as_ptr(), mode as libc::mode_t)
})) }))
} }
pub fn rmdir(p: &Path) -> IoResult<()> { pub fn rmdir(p: &Path) -> IoResult<()> {
let p = cstr(p); let p = try!(cstr(p));
mkerr_libc(unsafe { libc::rmdir(p.as_ptr()) }) mkerr_libc(unsafe { libc::rmdir(p.as_ptr()) })
} }
pub fn chown(p: &Path, uid: int, gid: int) -> IoResult<()> { pub fn chown(p: &Path, uid: int, gid: int) -> IoResult<()> {
let p = cstr(p); let p = try!(cstr(p));
mkerr_libc(retry(|| unsafe { mkerr_libc(retry(|| unsafe {
libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t)
})) }))
} }
pub fn readlink(p: &Path) -> IoResult<Path> { 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 p = c_path.as_ptr();
let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) }; let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) };
if len == -1 { if len == -1 {
@ -276,14 +276,14 @@ pub fn readlink(p: &Path) -> IoResult<Path> {
} }
pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> { pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
let src = cstr(src); let src = try!(cstr(src));
let dst = cstr(dst); let dst = try!(cstr(dst));
mkerr_libc(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) }) mkerr_libc(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) })
} }
pub fn link(src: &Path, dst: &Path) -> IoResult<()> { pub fn link(src: &Path, dst: &Path) -> IoResult<()> {
let src = cstr(src); let src = try!(cstr(src));
let dst = cstr(dst); let dst = try!(cstr(dst));
mkerr_libc(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) }) 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> { pub fn stat(p: &Path) -> IoResult<FileStat> {
let p = cstr(p); let p = try!(cstr(p));
let mut stat: libc::stat = unsafe { mem::zeroed() }; let mut stat: libc::stat = unsafe { mem::zeroed() };
match unsafe { libc::stat(p.as_ptr(), &mut stat) } { match unsafe { libc::stat(p.as_ptr(), &mut stat) } {
0 => Ok(mkstat(&stat)), 0 => Ok(mkstat(&stat)),
@ -340,7 +340,7 @@ pub fn stat(p: &Path) -> IoResult<FileStat> {
} }
pub fn lstat(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() }; let mut stat: libc::stat = unsafe { mem::zeroed() };
match unsafe { libc::lstat(p.as_ptr(), &mut stat) } { match unsafe { libc::lstat(p.as_ptr(), &mut stat) } {
0 => Ok(mkstat(&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<()> { pub fn utime(p: &Path, atime: u64, mtime: u64) -> IoResult<()> {
let p = cstr(p); let p = try!(cstr(p));
let buf = libc::utimbuf { let buf = libc::utimbuf {
actime: (atime / 1000) as libc::time_t, actime: (atime / 1000) as libc::time_t,
modtime: (mtime / 1000) as libc::time_t, modtime: (mtime / 1000) as libc::time_t,

View File

@ -12,7 +12,7 @@ use core::prelude::*;
use io::prelude::*; use io::prelude::*;
use os::unix::prelude::*; use os::unix::prelude::*;
use ffi::{self, CString, OsString, AsOsStr, OsStr}; use ffi::{CString, CStr, OsString, AsOsStr, OsStr};
use io::{self, Error, Seek, SeekFrom}; use io::{self, Error, Seek, SeekFrom};
use libc::{self, c_int, c_void, size_t, off_t, c_char, mode_t}; use libc::{self, c_int, c_void, size_t, off_t, c_char, mode_t};
use mem; use mem;
@ -147,8 +147,7 @@ impl DirEntry {
fn rust_list_dir_val(ptr: *mut libc::dirent_t) -> *const c_char; fn rust_list_dir_val(ptr: *mut libc::dirent_t) -> *const c_char;
} }
unsafe { unsafe {
let ptr = rust_list_dir_val(self.dirent); CStr::from_ptr(rust_list_dir_val(self.dirent)).to_bytes()
ffi::c_str_to_bytes(mem::copy_lifetime(self, &ptr))
} }
} }
} }
@ -204,7 +203,7 @@ impl File {
(true, false) | (true, false) |
(false, false) => libc::O_RDONLY, (false, false) => libc::O_RDONLY,
}; };
let path = cstr(path); let path = try!(cstr(path));
let fd = try!(cvt_r(|| unsafe { let fd = try!(cvt_r(|| unsafe {
libc::open(path.as_ptr(), flags, opts.mode) libc::open(path.as_ptr(), flags, opts.mode)
})); }));
@ -268,19 +267,20 @@ impl File {
pub fn fd(&self) -> &FileDesc { &self.0 } pub fn fd(&self) -> &FileDesc { &self.0 }
} }
fn cstr(path: &Path) -> CString { fn cstr(path: &Path) -> io::Result<CString> {
CString::from_slice(path.as_os_str().as_bytes()) let cstring = try!(path.as_os_str().to_cstring());
Ok(cstring)
} }
pub fn mkdir(p: &Path) -> io::Result<()> { pub fn mkdir(p: &Path) -> io::Result<()> {
let p = cstr(p); let p = try!(cstr(p));
try!(cvt(unsafe { libc::mkdir(p.as_ptr(), 0o777) })); try!(cvt(unsafe { libc::mkdir(p.as_ptr(), 0o777) }));
Ok(()) Ok(())
} }
pub fn readdir(p: &Path) -> io::Result<ReadDir> { pub fn readdir(p: &Path) -> io::Result<ReadDir> {
let root = Rc::new(p.to_path_buf()); let root = Rc::new(p.to_path_buf());
let p = cstr(p); let p = try!(cstr(p));
unsafe { unsafe {
let ptr = libc::opendir(p.as_ptr()); let ptr = libc::opendir(p.as_ptr());
if ptr.is_null() { if ptr.is_null() {
@ -292,32 +292,32 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
} }
pub fn unlink(p: &Path) -> io::Result<()> { pub fn unlink(p: &Path) -> io::Result<()> {
let p = cstr(p); let p = try!(cstr(p));
try!(cvt(unsafe { libc::unlink(p.as_ptr()) })); try!(cvt(unsafe { libc::unlink(p.as_ptr()) }));
Ok(()) Ok(())
} }
pub fn rename(old: &Path, new: &Path) -> io::Result<()> { pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
let old = cstr(old); let old = try!(cstr(old));
let new = cstr(new); let new = try!(cstr(new));
try!(cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) })); try!(cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }));
Ok(()) Ok(())
} }
pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
let p = cstr(p); let p = try!(cstr(p));
try!(cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) })); try!(cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }));
Ok(()) Ok(())
} }
pub fn rmdir(p: &Path) -> io::Result<()> { pub fn rmdir(p: &Path) -> io::Result<()> {
let p = cstr(p); let p = try!(cstr(p));
try!(cvt(unsafe { libc::rmdir(p.as_ptr()) })); try!(cvt(unsafe { libc::rmdir(p.as_ptr()) }));
Ok(()) Ok(())
} }
pub fn chown(p: &Path, uid: isize, gid: isize) -> io::Result<()> { pub fn chown(p: &Path, uid: isize, gid: isize) -> io::Result<()> {
let p = cstr(p); let p = try!(cstr(p));
try!(cvt_r(|| unsafe { try!(cvt_r(|| unsafe {
libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t) libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t)
})); }));
@ -325,7 +325,7 @@ pub fn chown(p: &Path, uid: isize, gid: isize) -> io::Result<()> {
} }
pub fn readlink(p: &Path) -> io::Result<PathBuf> { pub fn readlink(p: &Path) -> io::Result<PathBuf> {
let c_path = cstr(p); let c_path = try!(cstr(p));
let p = c_path.as_ptr(); let p = c_path.as_ptr();
let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) }; let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) };
if len < 0 { if len < 0 {
@ -343,35 +343,35 @@ pub fn readlink(p: &Path) -> io::Result<PathBuf> {
} }
pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
let src = cstr(src); let src = try!(cstr(src));
let dst = cstr(dst); let dst = try!(cstr(dst));
try!(cvt(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) })); try!(cvt(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) }));
Ok(()) Ok(())
} }
pub fn link(src: &Path, dst: &Path) -> io::Result<()> { pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
let src = cstr(src); let src = try!(cstr(src));
let dst = cstr(dst); let dst = try!(cstr(dst));
try!(cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })); try!(cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) }));
Ok(()) Ok(())
} }
pub fn stat(p: &Path) -> io::Result<FileAttr> { pub fn stat(p: &Path) -> io::Result<FileAttr> {
let p = cstr(p); let p = try!(cstr(p));
let mut stat: libc::stat = unsafe { mem::zeroed() }; let mut stat: libc::stat = unsafe { mem::zeroed() };
try!(cvt(unsafe { libc::stat(p.as_ptr(), &mut stat) })); try!(cvt(unsafe { libc::stat(p.as_ptr(), &mut stat) }));
Ok(FileAttr { stat: stat }) Ok(FileAttr { stat: stat })
} }
pub fn lstat(p: &Path) -> io::Result<FileAttr> { pub fn lstat(p: &Path) -> io::Result<FileAttr> {
let p = cstr(p); let p = try!(cstr(p));
let mut stat: libc::stat = unsafe { mem::zeroed() }; let mut stat: libc::stat = unsafe { mem::zeroed() };
try!(cvt(unsafe { libc::lstat(p.as_ptr(), &mut stat) })); try!(cvt(unsafe { libc::lstat(p.as_ptr(), &mut stat) }));
Ok(FileAttr { stat: stat }) Ok(FileAttr { stat: stat })
} }
pub fn utimes(p: &Path, atime: u64, mtime: u64) -> io::Result<()> { pub fn utimes(p: &Path, atime: u64, mtime: u64) -> io::Result<()> {
let p = cstr(p); let p = try!(cstr(p));
let buf = [super::ms_to_timeval(atime), super::ms_to_timeval(mtime)]; let buf = [super::ms_to_timeval(atime), super::ms_to_timeval(mtime)];
try!(cvt(unsafe { c::utimes(p.as_ptr(), buf.as_ptr()) })); try!(cvt(unsafe { c::utimes(p.as_ptr(), buf.as_ptr()) }));
Ok(()) Ok(())

View File

@ -17,7 +17,7 @@
use prelude::v1::*; use prelude::v1::*;
use ffi; use ffi::CStr;
use io::{self, ErrorKind}; use io::{self, ErrorKind};
use libc; use libc;
use num::{Int, SignedInt}; use num::{Int, SignedInt};
@ -91,7 +91,8 @@ pub fn last_gai_error(s: libc::c_int) -> IoError {
let mut err = decode_error(s); let mut err = decode_error(s);
err.detail = Some(unsafe { err.detail = Some(unsafe {
str::from_utf8(ffi::c_str_to_bytes(&gai_strerror(s))).unwrap().to_string() let data = CStr::from_ptr(gai_strerror(s));
str::from_utf8(data.to_bytes()).unwrap().to_string()
}); });
err err
} }

View File

@ -10,7 +10,7 @@
use prelude::v1::*; use prelude::v1::*;
use ffi; use ffi::CStr;
use io; use io;
use libc::{self, c_int, size_t}; use libc::{self, c_int, size_t};
use str; use str;
@ -31,7 +31,7 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> {
if err == 0 { return Ok(()) } if err == 0 { return Ok(()) }
let detail = unsafe { let detail = unsafe {
str::from_utf8(ffi::c_str_to_bytes(&c::gai_strerror(err))).unwrap() str::from_utf8(CStr::from_ptr(c::gai_strerror(err)).to_bytes()).unwrap()
.to_string() .to_string()
}; };
Err(io::Error::new(io::ErrorKind::Other, Err(io::Error::new(io::ErrorKind::Other,

View File

@ -14,7 +14,7 @@ use prelude::v1::*;
use os::unix::*; use os::unix::*;
use error::Error as StdError; use error::Error as StdError;
use ffi::{self, CString, OsString, OsStr, AsOsStr}; use ffi::{CString, CStr, OsString, OsStr, AsOsStr};
use fmt; use fmt;
use iter; use iter;
use libc::{self, c_int, c_char, c_void}; use libc::{self, c_int, c_char, c_void};
@ -88,7 +88,7 @@ pub fn error_string(errno: i32) -> String {
} }
let p = p as *const _; let p = p as *const _;
str::from_utf8(ffi::c_str_to_bytes(&p)).unwrap().to_string() str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_string()
} }
} }
@ -98,13 +98,13 @@ pub fn getcwd() -> IoResult<Path> {
if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() { if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
Err(IoError::last_error()) Err(IoError::last_error())
} else { } else {
Ok(Path::new(ffi::c_str_to_bytes(&buf.as_ptr()))) Ok(Path::new(CStr::from_ptr(buf.as_ptr()).to_bytes()))
} }
} }
} }
pub fn chdir(p: &Path) -> IoResult<()> { pub fn chdir(p: &Path) -> IoResult<()> {
let p = CString::from_slice(p.as_vec()); let p = CString::new(p.as_vec()).unwrap();
unsafe { unsafe {
match libc::chdir(p.as_ptr()) == (0 as c_int) { match libc::chdir(p.as_ptr()) == (0 as c_int) {
true => Ok(()), true => Ok(()),
@ -211,7 +211,7 @@ pub fn current_exe() -> IoResult<Path> {
if v.is_null() { if v.is_null() {
Err(IoError::last_error()) Err(IoError::last_error())
} else { } else {
Ok(Path::new(ffi::c_str_to_bytes(&v).to_vec())) Ok(Path::new(CStr::from_ptr(&v).to_bytes().to_vec()))
} }
} }
} }
@ -266,7 +266,7 @@ pub fn args() -> Args {
let (argc, argv) = (*_NSGetArgc() as isize, let (argc, argv) = (*_NSGetArgc() as isize,
*_NSGetArgv() as *const *const c_char); *_NSGetArgv() as *const *const c_char);
range(0, argc as isize).map(|i| { range(0, argc as isize).map(|i| {
let bytes = ffi::c_str_to_bytes(&*argv.offset(i)).to_vec(); let bytes = CStr::from_ptr(&*argv.offset(i)).to_bytes().to_vec();
OsStringExt::from_vec(bytes) OsStringExt::from_vec(bytes)
}).collect::<Vec<_>>() }).collect::<Vec<_>>()
}; };
@ -324,7 +324,7 @@ pub fn args() -> Args {
let tmp = objc_msgSend(args, object_at_sel, i); let tmp = objc_msgSend(args, object_at_sel, i);
let utf_c_str: *const libc::c_char = let utf_c_str: *const libc::c_char =
mem::transmute(objc_msgSend(tmp, utf8_sel)); mem::transmute(objc_msgSend(tmp, utf8_sel));
let bytes = ffi::c_str_to_bytes(&utf_c_str); let bytes = CStr::from_ptr(utf_c_str).to_bytes();
res.push(OsString::from_str(str::from_utf8(bytes).unwrap())) res.push(OsString::from_str(str::from_utf8(bytes).unwrap()))
} }
} }
@ -380,7 +380,7 @@ pub fn env() -> Env {
} }
let mut result = Vec::new(); let mut result = Vec::new();
while *environ != ptr::null() { while *environ != ptr::null() {
result.push(parse(ffi::c_str_to_bytes(&*environ))); result.push(parse(CStr::from_ptr(*environ).to_bytes()));
environ = environ.offset(1); environ = environ.offset(1);
} }
Env { iter: result.into_iter(), _dont_send_or_sync_me: 0 as *mut _ } Env { iter: result.into_iter(), _dont_send_or_sync_me: 0 as *mut _ }
@ -397,20 +397,20 @@ pub fn env() -> Env {
pub fn getenv(k: &OsStr) -> Option<OsString> { pub fn getenv(k: &OsStr) -> Option<OsString> {
unsafe { unsafe {
let s = CString::from_slice(k.as_bytes()); let s = k.to_cstring().unwrap();
let s = libc::getenv(s.as_ptr()) as *const _; let s = libc::getenv(s.as_ptr()) as *const _;
if s.is_null() { if s.is_null() {
None None
} else { } else {
Some(OsStringExt::from_vec(ffi::c_str_to_bytes(&s).to_vec())) Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
} }
} }
} }
pub fn setenv(k: &OsStr, v: &OsStr) { pub fn setenv(k: &OsStr, v: &OsStr) {
unsafe { unsafe {
let k = CString::from_slice(k.as_bytes()); let k = k.to_cstring().unwrap();
let v = CString::from_slice(v.as_bytes()); let v = v.to_cstring().unwrap();
if libc::funcs::posix01::unistd::setenv(k.as_ptr(), v.as_ptr(), 1) != 0 { if libc::funcs::posix01::unistd::setenv(k.as_ptr(), v.as_ptr(), 1) != 0 {
panic!("failed setenv: {}", IoError::last_error()); panic!("failed setenv: {}", IoError::last_error());
} }
@ -419,7 +419,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) {
pub fn unsetenv(n: &OsStr) { pub fn unsetenv(n: &OsStr) {
unsafe { unsafe {
let nbuf = CString::from_slice(n.as_bytes()); let nbuf = n.to_cstring().unwrap();
if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 { if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 {
panic!("failed unsetenv: {}", IoError::last_error()); panic!("failed unsetenv: {}", IoError::last_error());
} }
@ -480,7 +480,7 @@ pub fn home_dir() -> Option<Path> {
_ => return None _ => return None
} }
let ptr = passwd.pw_dir as *const _; let ptr = passwd.pw_dir as *const _;
let bytes = ffi::c_str_to_bytes(&ptr).to_vec(); let bytes = CStr::from_ptr(ptr).to_bytes().to_vec();
return Some(OsStringExt::from_vec(bytes)) return Some(OsStringExt::from_vec(bytes))
} }
} }

View File

@ -38,7 +38,7 @@ fn addr_to_sockaddr_un(addr: &CString,
mem::size_of::<libc::sockaddr_un>()); mem::size_of::<libc::sockaddr_un>());
let s = unsafe { &mut *(storage as *mut _ as *mut libc::sockaddr_un) }; let s = unsafe { &mut *(storage as *mut _ as *mut libc::sockaddr_un) };
let len = addr.len(); let len = addr.as_bytes().len();
if len > s.sun_path.len() - 1 { if len > s.sun_path.len() - 1 {
return Err(IoError { return Err(IoError {
kind: old_io::InvalidInput, kind: old_io::InvalidInput,
@ -47,8 +47,8 @@ fn addr_to_sockaddr_un(addr: &CString,
}) })
} }
s.sun_family = libc::AF_UNIX as libc::sa_family_t; s.sun_family = libc::AF_UNIX as libc::sa_family_t;
for (slot, value) in s.sun_path.iter_mut().zip(addr.iter()) { for (slot, value) in s.sun_path.iter_mut().zip(addr.as_bytes().iter()) {
*slot = *value; *slot = *value as libc::c_char;
} }
// count the null terminator // count the null terminator

View File

@ -46,7 +46,7 @@ pub struct Command {
impl Command { impl Command {
pub fn new(program: &OsStr) -> Command { pub fn new(program: &OsStr) -> Command {
Command { Command {
program: program.to_cstring(), program: program.to_cstring().unwrap(),
args: Vec::new(), args: Vec::new(),
env: None, env: None,
cwd: None, cwd: None,
@ -57,10 +57,10 @@ impl Command {
} }
pub fn arg(&mut self, arg: &OsStr) { pub fn arg(&mut self, arg: &OsStr) {
self.args.push(arg.to_cstring()) self.args.push(arg.to_cstring().unwrap())
} }
pub fn args<'a, I: Iterator<Item = &'a OsStr>>(&mut self, args: I) { pub fn args<'a, I: Iterator<Item = &'a OsStr>>(&mut self, args: I) {
self.args.extend(args.map(OsStrExt::to_cstring)) self.args.extend(args.map(|s| OsStrExt::to_cstring(s).unwrap()))
} }
fn init_env_map(&mut self) { fn init_env_map(&mut self) {
if self.env.is_none() { if self.env.is_none() {
@ -79,7 +79,7 @@ impl Command {
self.env = Some(HashMap::new()) self.env = Some(HashMap::new())
} }
pub fn cwd(&mut self, dir: &OsStr) { pub fn cwd(&mut self, dir: &OsStr) {
self.cwd = Some(dir.to_cstring()) self.cwd = Some(dir.to_cstring().unwrap())
} }
} }

View File

@ -237,7 +237,7 @@ pub unsafe fn create(stack: uint, p: Thunk) -> io::Result<rust_thread> {
pub unsafe fn set_name(name: &str) { pub unsafe fn set_name(name: &str) {
// pthread_setname_np() since glibc 2.12 // pthread_setname_np() since glibc 2.12
// availability autodetected via weak linkage // availability autodetected via weak linkage
let cname = CString::from_slice(name.as_bytes()); let cname = CString::new(name).unwrap();
type F = unsafe extern "C" fn(libc::pthread_t, *const libc::c_char) -> libc::c_int; type F = unsafe extern "C" fn(libc::pthread_t, *const libc::c_char) -> libc::c_int;
extern { extern {
#[linkage = "extern_weak"] #[linkage = "extern_weak"]
@ -255,14 +255,14 @@ pub unsafe fn set_name(name: &str) {
target_os = "openbsd"))] target_os = "openbsd"))]
pub unsafe fn set_name(name: &str) { pub unsafe fn set_name(name: &str) {
// pthread_set_name_np() since almost forever on all BSDs // pthread_set_name_np() since almost forever on all BSDs
let cname = CString::from_slice(name.as_bytes()); let cname = CString::new(name).unwrap();
pthread_set_name_np(pthread_self(), cname.as_ptr()); pthread_set_name_np(pthread_self(), cname.as_ptr());
} }
#[cfg(any(target_os = "macos", target_os = "ios"))] #[cfg(any(target_os = "macos", target_os = "ios"))]
pub unsafe fn set_name(name: &str) { pub unsafe fn set_name(name: &str) {
// pthread_setname_np() since OS X 10.6 and iOS 3.2 // pthread_setname_np() since OS X 10.6 and iOS 3.2
let cname = CString::from_slice(name.as_bytes()); let cname = CString::new(name).unwrap();
pthread_setname_np(cname.as_ptr()); pthread_setname_np(cname.as_ptr());
} }

View File

@ -618,22 +618,25 @@ fn print_macro_backtrace(w: &mut EmitterWriter,
cm: &codemap::CodeMap, cm: &codemap::CodeMap,
sp: Span) sp: Span)
-> old_io::IoResult<()> { -> old_io::IoResult<()> {
let cs = try!(cm.with_expn_info(sp.expn_id, |expn_info| match expn_info { let cs = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> old_io::IoResult<_> {
Some(ei) => { match expn_info {
let ss = ei.callee.span.map_or(String::new(), |span| cm.span_to_string(span)); Some(ei) => {
let (pre, post) = match ei.callee.format { let ss = ei.callee.span.map_or(String::new(),
codemap::MacroAttribute => ("#[", "]"), |span| cm.span_to_string(span));
codemap::MacroBang => ("", "!") let (pre, post) = match ei.callee.format {
}; codemap::MacroAttribute => ("#[", "]"),
try!(print_diagnostic(w, &ss[], Note, codemap::MacroBang => ("", "!")
&format!("in expansion of {}{}{}", pre, };
ei.callee.name, try!(print_diagnostic(w, &ss[], Note,
post)[], None)); &format!("in expansion of {}{}{}", pre,
let ss = cm.span_to_string(ei.call_site); ei.callee.name,
try!(print_diagnostic(w, &ss[], Note, "expansion site", None)); post)[], None));
Ok(Some(ei.call_site)) let ss = cm.span_to_string(ei.call_site);
} try!(print_diagnostic(w, &ss[], Note, "expansion site", None));
None => Ok(None) Ok(Some(ei.call_site))
}
None => Ok(None)
}
})); }));
cs.map_or(Ok(()), |call_site| print_macro_backtrace(w, cm, call_site)) cs.map_or(Ok(()), |call_site| print_macro_backtrace(w, cm, call_site))
} }

View File

@ -24,12 +24,12 @@ mod mlibc {
} }
fn atol(s: String) -> int { fn atol(s: String) -> int {
let c = CString::from_slice(s.as_bytes()); let c = CString::from_slice(s.as_bytes()).unwrap();
unsafe { mlibc::atol(c.as_ptr()) as int } unsafe { mlibc::atol(c.as_ptr()) as int }
} }
fn atoll(s: String) -> i64 { fn atoll(s: String) -> i64 {
let c = CString::from_slice(s.as_bytes()); let c = CString::from_slice(s.as_bytes()).unwrap();
unsafe { mlibc::atoll(c.as_ptr()) as i64 } unsafe { mlibc::atoll(c.as_ptr()) as i64 }
} }

View File

@ -24,7 +24,7 @@ mod mlibc {
fn strlen(str: String) -> uint { fn strlen(str: String) -> uint {
// C string is terminated with a zero // C string is terminated with a zero
let s = CString::from_slice(str.as_bytes()); let s = CString::from_slice(str.as_bytes()).unwrap();
unsafe { unsafe {
mlibc::my_strlen(s.as_ptr()) as uint mlibc::my_strlen(s.as_ptr()) as uint
} }

View File

@ -31,12 +31,12 @@ fn rename_directory() {
let test_file = &old_path.join("temp.txt"); let test_file = &old_path.join("temp.txt");
/* Write the temp input file */ /* Write the temp input file */
let fromp = CString::from_slice(test_file.as_vec()); let fromp = CString::from_slice(test_file.as_vec()).unwrap();
let modebuf = CString::from_slice(b"w+b"); let modebuf = CString::from_slice(b"w+b").unwrap();
let ostream = libc::fopen(fromp.as_ptr(), modebuf.as_ptr()); let ostream = libc::fopen(fromp.as_ptr(), modebuf.as_ptr());
assert!((ostream as uint != 0u)); assert!((ostream as uint != 0u));
let s = "hello".to_string(); let s = "hello".to_string();
let buf = CString::from_slice(b"hello"); let buf = CString::from_slice(b"hello").unwrap();
let write_len = libc::fwrite(buf.as_ptr() as *mut _, let write_len = libc::fwrite(buf.as_ptr() as *mut _,
1u as libc::size_t, 1u as libc::size_t,
(s.len() + 1u) as libc::size_t, (s.len() + 1u) as libc::size_t,

View File

@ -29,11 +29,11 @@ pub fn main() {
unsafe { unsafe {
// Call with just the named parameter // Call with just the named parameter
let c = CString::from_slice(b"Hello World\n"); let c = CString::from_slice(b"Hello World\n").unwrap();
check("Hello World\n", |s| sprintf(s, c.as_ptr())); check("Hello World\n", |s| sprintf(s, c.as_ptr()));
// Call with variable number of arguments // Call with variable number of arguments
let c = CString::from_slice(b"%d %f %c %s\n"); let c = CString::from_slice(b"%d %f %c %s\n").unwrap();
check("42 42.500000 a %d %f %c %s\n\n", |s| { check("42 42.500000 a %d %f %c %s\n\n", |s| {
sprintf(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr()); sprintf(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr());
}); });
@ -44,11 +44,11 @@ pub fn main() {
// A function that takes a function pointer // A function that takes a function pointer
unsafe fn call(p: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int) { unsafe fn call(p: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int) {
// Call with just the named parameter // Call with just the named parameter
let c = CString::from_slice(b"Hello World\n"); let c = CString::from_slice(b"Hello World\n").unwrap();
check("Hello World\n", |s| sprintf(s, c.as_ptr())); check("Hello World\n", |s| sprintf(s, c.as_ptr()));
// Call with variable number of arguments // Call with variable number of arguments
let c = CString::from_slice(b"%d %f %c %s\n"); let c = CString::from_slice(b"%d %f %c %s\n").unwrap();
check("42 42.500000 a %d %f %c %s\n\n", |s| { check("42 42.500000 a %d %f %c %s\n\n", |s| {
sprintf(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr()); sprintf(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr());
}); });