Fix truncate and related tests.

This commit is contained in:
Joseph Crail 2015-04-29 19:20:51 -04:00
parent 3eb1d124ec
commit 5ec7f28625
2 changed files with 75 additions and 79 deletions

View file

@ -1,5 +1,5 @@
#![crate_name = "truncate"]
#![feature(collections, core, old_io, old_path, rustc_private)]
#![feature(rustc_private)]
/*
* This file is part of the uutils coreutils package.
@ -14,8 +14,9 @@ extern crate getopts;
extern crate libc;
use std::ascii::AsciiExt;
use std::old_io::{File, Open, ReadWrite, fs};
use std::old_io::fs::PathExtensions;
use std::fs::{File, metadata, OpenOptions};
use std::io::{Result, Write};
use std::path::Path;
#[path = "../common/util.rs"]
#[macro_use]
@ -45,7 +46,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
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, "{}", f)
@ -92,7 +93,7 @@ file based on its current size:
} else {
match truncate(no_create, io_blocks, reference, size, matches.free) {
Ok(()) => ( /* pass */ ),
Err(e) => return e
Err(_) => return 1
}
}
}
@ -100,59 +101,54 @@ file based on its current size:
0
}
fn truncate(no_create: bool, _: bool, reference: Option<String>, size: Option<String>, filenames: Vec<String>) -> Result<(), i32> {
fn truncate(no_create: bool, _: bool, reference: Option<String>, size: Option<String>, filenames: Vec<String>) -> Result<()> {
let (refsize, mode) = match reference {
Some(rfilename) => {
let rfile = match File::open(&Path::new(rfilename.clone())) {
let _ = match File::open(Path::new(&rfilename)) {
Ok(m) => m,
Err(f) => {
crash!(1, "{}", f.to_string())
}
};
match fs::stat(rfile.path()) {
Ok(stat) => (stat.size, TruncateMode::Reference),
match metadata(rfilename) {
Ok(meta) => (meta.len(), TruncateMode::Reference),
Err(f) => {
show_error!("{}", f.to_string());
return Err(1);
crash!(1, "{}", f.to_string())
}
}
}
None => parse_size(size.unwrap().as_slice())
None => parse_size(size.unwrap().as_ref())
};
for filename in filenames.iter() {
let filename = filename.as_slice();
let path = Path::new(filename);
if path.exists() || !no_create {
match File::open_mode(&path, Open, ReadWrite) {
Ok(mut file) => {
let fsize = match fs::stat(file.path()) {
Ok(stat) => stat.size,
Err(f) => {
show_warning!("{}", f.to_string());
continue;
}
};
let tsize = match mode {
TruncateMode::Reference => refsize,
TruncateMode::Extend => fsize + refsize,
TruncateMode::Reduce => fsize - refsize,
TruncateMode::AtMost => if fsize > refsize { refsize } else { fsize },
TruncateMode::AtLeast => if fsize < refsize { refsize } else { fsize },
TruncateMode::RoundDown => fsize - fsize % refsize,
TruncateMode::RoundUp => fsize + fsize % refsize
};
match file.truncate(tsize as i64) {
Ok(_) => {}
Err(f) => {
show_error!("{}", f.to_string());
return Err(1);
}
match OpenOptions::new().read(true).write(true).create(!no_create).open(path) {
Ok(file) => {
let fsize = match metadata(filename) {
Ok(meta) => meta.len(),
Err(f) => {
show_warning!("{}", f.to_string());
continue;
}
}
Err(f) => {
show_error!("{}", f.to_string());
return Err(1);
}
};
let tsize: u64 = match mode {
TruncateMode::Reference => refsize,
TruncateMode::Extend => fsize + refsize,
TruncateMode::Reduce => fsize - refsize,
TruncateMode::AtMost => if fsize > refsize { refsize } else { fsize },
TruncateMode::AtLeast => if fsize < refsize { refsize } else { fsize },
TruncateMode::RoundDown => fsize - fsize % refsize,
TruncateMode::RoundUp => fsize + fsize % refsize
};
let _ = match file.set_len(tsize) {
Ok(_) => {},
Err(f) => {
crash!(1, "{}", f.to_string())
}
};
}
Err(f) => {
crash!(1, "{}", f.to_string())
}
}
}
@ -160,7 +156,7 @@ fn truncate(no_create: bool, _: bool, reference: Option<String>, size: Option<St
}
fn parse_size(size: &str) -> (u64, TruncateMode) {
let mode = match size.char_at(0) {
let mode = match size.chars().next().unwrap() {
'+' => TruncateMode::Extend,
'-' => TruncateMode::Reduce,
'<' => TruncateMode::AtMost,
@ -177,43 +173,43 @@ fn parse_size(size: &str) -> (u64, TruncateMode) {
} else {
&size[1..]
};
if slice.char_at(slice.len() - 1).is_alphabetic() {
if slice.chars().last().unwrap().is_alphabetic() {
slice = &slice[..slice.len() - 1];
if slice.len() > 0 && slice.char_at(slice.len() - 1).is_alphabetic() {
if slice.len() > 0 && slice.chars().last().unwrap().is_alphabetic() {
slice = &slice[..slice.len() - 1];
}
}
slice
}.to_string();
let mut number: u64 = match bytes.as_slice().parse() {
let mut number: u64 = match bytes.parse() {
Ok(num) => num,
Err(e) => {
crash!(1, "'{}' is not a valid number: {}", size, e)
}
};
if size.char_at(size.len() - 1).is_alphabetic() {
number *= match size.char_at(size.len() - 1).to_ascii_uppercase() {
'B' => match size.char_at(size.len() - 2).to_ascii_uppercase() {
'K' => 1000,
'M' => 1000 * 1000,
'G' => 1000 * 1000 * 1000,
'T' => 1000 * 1000 * 1000 * 1000,
'P' => 1000 * 1000 * 1000 * 1000 * 1000,
'E' => 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
'Z' => 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
'Y' => 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
if size.chars().last().unwrap().is_alphabetic() {
number *= match size.chars().last().unwrap().to_ascii_uppercase() {
'B' => match size.chars().nth(size.len() - 2).unwrap().to_ascii_uppercase() {
'K' => 1000u64,
'M' => 1000u64.pow(2),
'G' => 1000u64.pow(3),
'T' => 1000u64.pow(4),
'P' => 1000u64.pow(5),
'E' => 1000u64.pow(6),
'Z' => 1000u64.pow(7),
'Y' => 1000u64.pow(8),
letter => {
crash!(1, "'{}B' is not a valid suffix.", letter)
}
},
'K' => 1024,
'M' => 1024 * 1024,
'G' => 1024 * 1024 * 1024,
'T' => 1024 * 1024 * 1024 * 1024,
'P' => 1024 * 1024 * 1024 * 1024 * 1024,
'E' => 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
'Z' => 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
'Y' => 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
'K' => 1024u64,
'M' => 1024u64.pow(2),
'G' => 1024u64.pow(3),
'T' => 1024u64.pow(4),
'P' => 1024u64.pow(5),
'E' => 1024u64.pow(6),
'Z' => 1024u64.pow(7),
'Y' => 1024u64.pow(8),
letter => {
crash!(1, "'{}' is not a valid suffix.", letter)
}

View file

@ -1,14 +1,14 @@
#![allow(unstable)]
use std::old_io as io;
use std::old_io::process::Command;
use std::fs::{File, remove_file};
use std::io::{Seek, SeekFrom, Write};
use std::path::Path;
use std::process::Command;
static PROGNAME: &'static str = "./truncate";
static TFILE1: &'static str = "truncate_test_1";
static TFILE2: &'static str = "truncate_test_2";
fn make_file(name: &str) -> io::File {
match io::File::create(&Path::new(name)) {
fn make_file(name: &str) -> File {
match File::create(Path::new(name)) {
Ok(f) => f,
Err(_) => panic!()
}
@ -20,11 +20,11 @@ fn test_increase_file_size() {
if !Command::new(PROGNAME).args(&["-s", "+5K", TFILE1]).status().unwrap().success() {
panic!();
}
file.seek(0, io::SeekEnd).unwrap();
if file.tell().unwrap() != 5 * 1024 {
file.seek(SeekFrom::End(0)).unwrap();
if file.seek(SeekFrom::Current(0)).unwrap() != 5 * 1024 {
panic!();
}
io::fs::unlink(&Path::new(TFILE1)).unwrap();
remove_file(Path::new(TFILE1)).unwrap();
}
#[test]
@ -34,10 +34,10 @@ fn test_decrease_file_size() {
if !Command::new(PROGNAME).args(&["--size=-4", TFILE2]).status().unwrap().success() {
panic!();
}
file.seek(0, io::SeekEnd).unwrap();
if file.tell().unwrap() != 6 {
println!("{:?}", file.tell());
file.seek(SeekFrom::End(0)).unwrap();
if file.seek(SeekFrom::Current(0)).unwrap() != 6 {
println!("{:?}", file.seek(SeekFrom::Current(0)));
panic!();
}
io::fs::unlink(&Path::new(TFILE2)).unwrap();
remove_file(Path::new(TFILE2)).unwrap();
}