From ec4e3a60e43a36edc70efe4c68fc9a75e7760ff7 Mon Sep 17 00:00:00 2001 From: kwantam Date: Tue, 28 Apr 2015 13:57:17 -0400 Subject: [PATCH] fix `unlink` --- src/unlink/unlink.rs | 59 ++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/src/unlink/unlink.rs b/src/unlink/unlink.rs index 0151110cf..3aeb8b473 100644 --- a/src/unlink/unlink.rs +++ b/src/unlink/unlink.rs @@ -1,5 +1,5 @@ #![crate_name = "unlink"] -#![feature(collections, core, old_io, old_path, rustc_private)] +#![feature(rustc_private)] /* * This file is part of the uutils coreutils package. @@ -15,9 +15,14 @@ extern crate getopts; extern crate libc; -use std::old_io as io; -use std::old_io::fs::{self, PathExtensions}; -use std::old_io::print; +use libc::consts::os::posix88::{S_IFMT, S_IFLNK, S_IFREG}; +use libc::types::os::arch::c95::c_char; +use libc::types::os::arch::posix01::stat; +use libc::funcs::posix01::stat_::lstat; +use libc::funcs::posix88::unistd::unlink; + +use std::mem::uninitialized; +use std::io::{Error, ErrorKind, Write}; #[path = "../common/util.rs"] #[macro_use] @@ -26,13 +31,12 @@ mod util; static NAME: &'static str = "unlink"; pub fn uumain(args: Vec) -> i32 { - let program = args[0].clone(); let opts = [ getopts::optflag("h", "help", "display this help and exit"), getopts::optflag("V", "version", "output version information and exit"), ]; - let matches = match getopts::getopts(args.tail(), &opts) { + let matches = match getopts::getopts(&args[1..], &opts) { Ok(m) => m, Err(f) => { crash!(1, "invalid options\n{}", f) @@ -43,9 +47,9 @@ pub fn uumain(args: Vec) -> i32 { println!("unlink 1.0.0"); println!(""); println!("Usage:"); - println!(" {0} [FILE]... [OPTION]...", program); + println!(" {0} [FILE]... [OPTION]...", args[0]); println!(""); - print(getopts::usage("Unlink the file at [FILE].", &opts).as_slice()); + println!("{}", getopts::usage("Unlink the file at [FILE].", &opts)); return 0; } @@ -55,31 +59,38 @@ pub fn uumain(args: Vec) -> i32 { } if matches.free.len() == 0 { - crash!(1, "missing operand\nTry '{0} --help' for more information.", program); + crash!(1, "missing operand\nTry '{0} --help' for more information.", args[0]); } else if matches.free.len() > 1 { - crash!(1, "extra operand: '{1}'\nTry '{0} --help' for more information.", program, matches.free[1]); + crash!(1, "extra operand: '{1}'\nTry '{0} --help' for more information.", args[0], matches.free[1]); } - let path = Path::new(matches.free[0].clone()); + let st_mode = { + let mut buf: stat = unsafe { uninitialized() }; + let result = unsafe { lstat(matches.free[0].as_ptr() as *const c_char, &mut buf as *mut stat) }; - let result = path.lstat().and_then(|info| { - match info.kind { - io::FileType::RegularFile => Ok(()), - io::FileType::Symlink => Ok(()), - _ => Err(io::IoError { - kind: io::OtherIoError, - desc: "is not a file or symlink", - detail: None - }) + if result < 0 { + crash!(1, "Cannot stat '{}': {}", matches.free[0], Error::last_os_error()); } - }).and_then(|_| { - fs::unlink(&path) - }); + + buf.st_mode & S_IFMT + }; + + let result = if st_mode != S_IFREG && st_mode != S_IFLNK { + Err(Error::new(ErrorKind::Other, "Not a regular file or symlink")) + } else { + let result = unsafe { unlink(matches.free[0].as_ptr() as *const c_char) }; + + if result < 0 { + Err(Error::last_os_error()) + } else { + Ok(()) + } + }; match result { Ok(_) => (), Err(e) => { - crash!(1, "cannot unlink '{0}': {1}", path.display(), e.desc); + crash!(1, "cannot unlink '{0}': {1}", matches.free[0], e); } }