mirror of
https://github.com/uutils/coreutils
synced 2024-11-16 01:38:04 +00:00
Fix truncate and related tests.
This commit is contained in:
parent
3eb1d124ec
commit
5ec7f28625
2 changed files with 75 additions and 79 deletions
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue