mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
Merge pull request #678 from jbcrail/stabilize-4
Remove unstable features from mv/touch.
This commit is contained in:
commit
809affff6c
9 changed files with 325 additions and 57 deletions
1
Makefile
1
Makefile
|
@ -191,6 +191,7 @@ TEST_PROGS := \
|
||||||
stdbuf \
|
stdbuf \
|
||||||
tac \
|
tac \
|
||||||
test \
|
test \
|
||||||
|
touch \
|
||||||
tr \
|
tr \
|
||||||
true \
|
true \
|
||||||
truncate \
|
truncate \
|
||||||
|
|
1
deps/Cargo.toml
vendored
1
deps/Cargo.toml
vendored
|
@ -22,3 +22,4 @@ winapi = "0.2"
|
||||||
advapi32-sys = "0.1"
|
advapi32-sys = "0.1"
|
||||||
kernel32-sys = "0.1"
|
kernel32-sys = "0.1"
|
||||||
walker = "^1.0.0"
|
walker = "^1.0.0"
|
||||||
|
filetime = "0.1"
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
DEPLIBS += time
|
DEPLIBS += kernel32 winapi filetime time
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#![crate_name = "test"]
|
#![crate_name = "test"]
|
||||||
#![feature(convert)]
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file is part of the uutils coreutils package.
|
* This file is part of the uutils coreutils package.
|
||||||
|
@ -24,7 +23,7 @@ static NAME: &'static str = "test";
|
||||||
pub fn uumain(_: Vec<String>) -> i32 {
|
pub fn uumain(_: Vec<String>) -> i32 {
|
||||||
let args = args_os().collect::<Vec<OsString>>();
|
let args = args_os().collect::<Vec<OsString>>();
|
||||||
// This is completely disregarding valid windows paths that aren't valid unicode
|
// This is completely disregarding valid windows paths that aren't valid unicode
|
||||||
let args = args.iter().map(|a| a.to_bytes().unwrap()).collect::<Vec<&[u8]>>();
|
let args = args.iter().map(|a| a.to_str().unwrap().as_bytes()).collect::<Vec<&[u8]>>();
|
||||||
if args.len() == 0 {
|
if args.len() == 0 {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
DEPLIBS += time
|
DEPLIBS += kernel32 winapi filetime time
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#![crate_name = "touch"]
|
#![crate_name = "touch"]
|
||||||
#![feature(fs_time)]
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file is part of the uutils coreutils package.
|
* This file is part of the uutils coreutils package.
|
||||||
|
@ -13,14 +12,11 @@
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
|
extern crate filetime;
|
||||||
|
|
||||||
use libc::types::os::arch::c95::c_char;
|
use filetime::*;
|
||||||
use libc::types::os::arch::posix01::stat as stat_t;
|
use std::fs::{self, File};
|
||||||
use libc::funcs::posix88::stat_::stat as c_stat;
|
|
||||||
use libc::funcs::posix01::stat_::lstat as c_lstat;
|
|
||||||
use std::fs::{set_file_times, File};
|
|
||||||
use std::io::{Error, Write};
|
use std::io::{Error, Write};
|
||||||
use std::mem::uninitialized;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
#[path = "../common/util.rs"]
|
#[path = "../common/util.rs"]
|
||||||
|
@ -35,6 +31,24 @@ use filesystem::UUPathExt;
|
||||||
static NAME: &'static str = "touch";
|
static NAME: &'static str = "touch";
|
||||||
static VERSION: &'static str = "1.0.0";
|
static VERSION: &'static str = "1.0.0";
|
||||||
|
|
||||||
|
// Since touch's date/timestamp parsing doesn't account for timezone, the
|
||||||
|
// returned value from time::strptime() is UTC. We get system's timezone to
|
||||||
|
// localize the time.
|
||||||
|
macro_rules! to_local(
|
||||||
|
($exp:expr) => ({
|
||||||
|
let mut tm = $exp;
|
||||||
|
tm.tm_utcoff = time::now().tm_utcoff;
|
||||||
|
tm
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
macro_rules! local_tm_to_filetime(
|
||||||
|
($exp:expr) => ({
|
||||||
|
let ts = $exp.to_timespec();
|
||||||
|
FileTime::from_seconds_since_1970(ts.sec as u64, ts.nsec as u32)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
pub fn uumain(args: Vec<String>) -> i32 {
|
pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
let mut opts = getopts::Options::new();
|
let mut opts = getopts::Options::new();
|
||||||
|
|
||||||
|
@ -92,8 +106,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
};
|
};
|
||||||
(timestamp, timestamp)
|
(timestamp, timestamp)
|
||||||
} else {
|
} else {
|
||||||
// FIXME: Should use Timespec. https://github.com/mozilla/rust/issues/10301
|
let now = local_tm_to_filetime!(time::now());
|
||||||
let now = (time::get_time().sec * 1000) as u64;
|
|
||||||
(now, now)
|
(now, now)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -142,7 +155,7 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
|
|
||||||
// this follows symlinks and thus does not work correctly for the -h flag
|
// this follows symlinks and thus does not work correctly for the -h flag
|
||||||
// need to use lutimes() c function on supported platforms
|
// need to use lutimes() c function on supported platforms
|
||||||
match set_file_times(path, atime, mtime) {
|
match filetime::set_file_times(path, atime, mtime) {
|
||||||
Err(e) => show_warning!("cannot touch '{}': {}", path, e),
|
Err(e) => show_warning!("cannot touch '{}': {}", path, e),
|
||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
|
@ -151,60 +164,47 @@ pub fn uumain(args: Vec<String>) -> i32 {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stat(path: &str, follow: bool) -> (u64, u64) {
|
fn stat(path: &str, follow: bool) -> (FileTime, FileTime) {
|
||||||
let stat_fn = if follow {
|
let metadata = if follow {
|
||||||
c_stat
|
fs::symlink_metadata(path)
|
||||||
} else {
|
} else {
|
||||||
c_lstat
|
fs::metadata(path)
|
||||||
};
|
};
|
||||||
let mut st: stat_t = unsafe { uninitialized() };
|
|
||||||
let result = unsafe { stat_fn(path.as_ptr() as *const c_char, &mut st as *mut stat_t) };
|
|
||||||
|
|
||||||
if result < 0 {
|
match metadata {
|
||||||
crash!(1, "failed to get attributes of '{}': {}", path, Error::last_os_error());
|
Ok(m) => (
|
||||||
|
FileTime::from_last_access_time(&m),
|
||||||
|
FileTime::from_last_modification_time(&m)
|
||||||
|
),
|
||||||
|
Err(_) => crash!(1, "failed to get attributes of '{}': {}", path, Error::last_os_error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// set_file_times expects milliseconds
|
|
||||||
let atime = if st.st_atime_nsec == 0 {
|
|
||||||
st.st_atime * 1000
|
|
||||||
} else {
|
|
||||||
st.st_atime_nsec / 1000
|
|
||||||
} as u64;
|
|
||||||
|
|
||||||
// set_file_times expects milliseconds
|
|
||||||
let mtime = if st.st_mtime_nsec == 0 {
|
|
||||||
st.st_mtime * 1000
|
|
||||||
} else {
|
|
||||||
st.st_mtime_nsec / 1000
|
|
||||||
} as u64;
|
|
||||||
|
|
||||||
(atime, mtime)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_date(str: &str) -> u64 {
|
fn parse_date(str: &str) -> FileTime {
|
||||||
// This isn't actually compatible with GNU touch, but there doesn't seem to
|
// This isn't actually compatible with GNU touch, but there doesn't seem to
|
||||||
// be any simple specification for what format this parameter allows and I'm
|
// be any simple specification for what format this parameter allows and I'm
|
||||||
// not about to implement GNU parse_datetime.
|
// not about to implement GNU parse_datetime.
|
||||||
// http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob_plain;f=lib/parse-datetime.y
|
// http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob_plain;f=lib/parse-datetime.y
|
||||||
match time::strptime(str, "%c") {
|
match time::strptime(str, "%c") {
|
||||||
Ok(tm) => (tm.to_timespec().sec * 1000) as u64,
|
Ok(tm) => local_tm_to_filetime!(to_local!(tm)),
|
||||||
Err(e) => panic!("Unable to parse date\n{}", e)
|
Err(e) => panic!("Unable to parse date\n{}", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_timestamp(str: &str) -> u64 {
|
fn parse_timestamp(s: &str) -> FileTime {
|
||||||
let format = match str.chars().count() {
|
let now = time::now();
|
||||||
15 => "%Y%m%d%H%M.%S",
|
let (format, ts) = match s.chars().count() {
|
||||||
12 => "%Y%m%d%H%M",
|
15 => ("%Y%m%d%H%M.%S", s.to_string()),
|
||||||
13 => "%y%m%d%H%M.%S",
|
12 => ("%Y%m%d%H%M", s.to_string()),
|
||||||
10 => "%y%m%d%H%M",
|
13 => ("%y%m%d%H%M.%S", s.to_string()),
|
||||||
11 => "%m%d%H%M.%S",
|
10 => ("%y%m%d%H%M", s.to_string()),
|
||||||
8 => "%m%d%H%M",
|
11 => ("%Y%m%d%H%M.%S", format!("{}{}", now.tm_year + 1900, s)),
|
||||||
|
8 => ("%Y%m%d%H%M", format!("{}{}", now.tm_year + 1900, s)),
|
||||||
_ => panic!("Unknown timestamp format")
|
_ => panic!("Unknown timestamp format")
|
||||||
};
|
};
|
||||||
|
|
||||||
match time::strptime(str, format) {
|
match time::strptime(&ts, format) {
|
||||||
Ok(tm) => (tm.to_timespec().sec * 1000) as u64,
|
Ok(tm) => local_tm_to_filetime!(to_local!(tm)),
|
||||||
Err(e) => panic!("Unable to parse timestamp\n{}", e)
|
Err(e) => panic!("Unable to parse timestamp\n{}", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,6 +97,13 @@ pub fn resolve_link(path: &str) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn metadata(path: &str) -> fs::Metadata {
|
||||||
|
match fs::metadata(path) {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(e) => panic!("{}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn file_exists(path: &str) -> bool {
|
pub fn file_exists(path: &str) -> bool {
|
||||||
match fs::metadata(path) {
|
match fs::metadata(path) {
|
||||||
Ok(m) => m.is_file(),
|
Ok(m) => m.is_file(),
|
||||||
|
|
16
test/mv.rs
16
test/mv.rs
|
@ -1,10 +1,10 @@
|
||||||
#![feature(fs_time)]
|
|
||||||
|
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
|
extern crate kernel32;
|
||||||
|
extern crate winapi;
|
||||||
|
extern crate filetime;
|
||||||
|
|
||||||
use std::fs;
|
use filetime::*;
|
||||||
use std::path::Path;
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use util::*;
|
use util::*;
|
||||||
|
|
||||||
|
@ -272,9 +272,11 @@ fn test_mv_update_option() {
|
||||||
|
|
||||||
touch(file_a);
|
touch(file_a);
|
||||||
touch(file_b);
|
touch(file_b);
|
||||||
let now = (time::get_time().sec * 1000) as u64;
|
let ts = time::now().to_timespec();
|
||||||
fs::set_file_times(Path::new(file_a), now, now).unwrap();
|
let now = FileTime::from_seconds_since_1970(ts.sec as u64, ts.nsec as u32);
|
||||||
fs::set_file_times(Path::new(file_b), now, now+3600).unwrap();
|
let later = FileTime::from_seconds_since_1970(ts.sec as u64 + 3600, ts.nsec as u32);
|
||||||
|
filetime::set_file_times(file_a, now, now).unwrap();
|
||||||
|
filetime::set_file_times(file_b, now, later).unwrap();
|
||||||
|
|
||||||
let result1 = run(Command::new(PROGNAME).arg("--update").arg(file_a).arg(file_b));
|
let result1 = run(Command::new(PROGNAME).arg("--update").arg(file_a).arg(file_b));
|
||||||
|
|
||||||
|
|
258
test/touch.rs
Normal file
258
test/touch.rs
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
extern crate libc;
|
||||||
|
extern crate time;
|
||||||
|
extern crate kernel32;
|
||||||
|
extern crate winapi;
|
||||||
|
extern crate filetime;
|
||||||
|
|
||||||
|
use filetime::FileTime;
|
||||||
|
use std::process::Command;
|
||||||
|
use util::*;
|
||||||
|
|
||||||
|
static PROGNAME: &'static str = "./touch";
|
||||||
|
|
||||||
|
#[path = "common/util.rs"]
|
||||||
|
#[macro_use]
|
||||||
|
mod util;
|
||||||
|
|
||||||
|
fn get_file_times(path: &str) -> (FileTime, FileTime) {
|
||||||
|
let m = metadata(path);
|
||||||
|
(FileTime::from_last_access_time(&m), FileTime::from_last_modification_time(&m))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_file_times(path: &str, atime: FileTime, mtime: FileTime) {
|
||||||
|
filetime::set_file_times(path, atime, mtime).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjusts for local timezone
|
||||||
|
fn str_to_filetime(format: &str, s: &str) -> FileTime {
|
||||||
|
let mut tm = time::strptime(s, format).unwrap();
|
||||||
|
tm.tm_utcoff = time::now().tm_utcoff;
|
||||||
|
let ts = tm.to_timespec();
|
||||||
|
FileTime::from_seconds_since_1970(ts.sec as u64, ts.nsec as u32)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_touch_default() {
|
||||||
|
let file = "test_touch_default_file";
|
||||||
|
|
||||||
|
let result = run(Command::new(PROGNAME).arg(file));
|
||||||
|
assert_empty_stderr!(result);
|
||||||
|
assert!(result.success);
|
||||||
|
|
||||||
|
assert!(file_exists(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_touch_no_create_file_absent() {
|
||||||
|
let file = "test_touch_no_create_file_absent";
|
||||||
|
|
||||||
|
let result = run(Command::new(PROGNAME).arg("-c").arg(file));
|
||||||
|
assert_empty_stderr!(result);
|
||||||
|
assert!(result.success);
|
||||||
|
|
||||||
|
assert!(!file_exists(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_touch_no_create_file_exists() {
|
||||||
|
let file = "test_touch_no_create_file_exists";
|
||||||
|
|
||||||
|
touch(file);
|
||||||
|
assert!(file_exists(file));
|
||||||
|
|
||||||
|
let result = run(Command::new(PROGNAME).arg("-c").arg(file));
|
||||||
|
assert_empty_stderr!(result);
|
||||||
|
assert!(result.success);
|
||||||
|
|
||||||
|
assert!(file_exists(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_touch_set_mdhm_time() {
|
||||||
|
let file = "test_touch_set_mdhm_time";
|
||||||
|
|
||||||
|
let result = run(Command::new(PROGNAME).args(&["-t", "01011234", file]));
|
||||||
|
assert_empty_stderr!(result);
|
||||||
|
assert!(result.success);
|
||||||
|
|
||||||
|
assert!(file_exists(file));
|
||||||
|
|
||||||
|
let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
|
||||||
|
let (atime, mtime) = get_file_times(file);
|
||||||
|
assert_eq!(atime, mtime);
|
||||||
|
assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240);
|
||||||
|
assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_touch_set_mdhms_time() {
|
||||||
|
let file = "test_touch_set_mdhms_time";
|
||||||
|
|
||||||
|
let result = run(Command::new(PROGNAME).args(&["-t", "01011234.56", file]));
|
||||||
|
assert_empty_stderr!(result);
|
||||||
|
assert!(result.success);
|
||||||
|
|
||||||
|
assert!(file_exists(file));
|
||||||
|
|
||||||
|
let start_of_year = str_to_filetime("%Y%m%d%H%M.%S", "201501010000.00");
|
||||||
|
let (atime, mtime) = get_file_times(file);
|
||||||
|
assert_eq!(atime, mtime);
|
||||||
|
assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45296);
|
||||||
|
assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45296);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_touch_set_ymdhm_time() {
|
||||||
|
let file = "test_touch_set_ymdhm_time";
|
||||||
|
|
||||||
|
let result = run(Command::new(PROGNAME).args(&["-t", "1501011234", file]));
|
||||||
|
assert_empty_stderr!(result);
|
||||||
|
assert!(result.success);
|
||||||
|
|
||||||
|
assert!(file_exists(file));
|
||||||
|
|
||||||
|
let start_of_year = str_to_filetime("%y%m%d%H%M", "1501010000");
|
||||||
|
let (atime, mtime) = get_file_times(file);
|
||||||
|
assert_eq!(atime, mtime);
|
||||||
|
assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240);
|
||||||
|
assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_touch_set_ymdhms_time() {
|
||||||
|
let file = "test_touch_set_ymdhms_time";
|
||||||
|
|
||||||
|
let result = run(Command::new(PROGNAME).args(&["-t", "1501011234.56", file]));
|
||||||
|
assert_empty_stderr!(result);
|
||||||
|
assert!(result.success);
|
||||||
|
|
||||||
|
assert!(file_exists(file));
|
||||||
|
|
||||||
|
let start_of_year = str_to_filetime("%y%m%d%H%M.%S", "1501010000.00");
|
||||||
|
let (atime, mtime) = get_file_times(file);
|
||||||
|
assert_eq!(atime, mtime);
|
||||||
|
assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45296);
|
||||||
|
assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45296);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_touch_set_cymdhm_time() {
|
||||||
|
let file = "test_touch_set_cymdhm_time";
|
||||||
|
|
||||||
|
let result = run(Command::new(PROGNAME).args(&["-t", "201501011234", file]));
|
||||||
|
assert_empty_stderr!(result);
|
||||||
|
assert!(result.success);
|
||||||
|
|
||||||
|
assert!(file_exists(file));
|
||||||
|
|
||||||
|
let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
|
||||||
|
let (atime, mtime) = get_file_times(file);
|
||||||
|
assert_eq!(atime, mtime);
|
||||||
|
assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240);
|
||||||
|
assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_touch_set_cymdhms_time() {
|
||||||
|
let file = "test_touch_set_cymdhms_time";
|
||||||
|
|
||||||
|
let result = run(Command::new(PROGNAME).args(&["-t", "201501011234.56", file]));
|
||||||
|
assert_empty_stderr!(result);
|
||||||
|
assert!(result.success);
|
||||||
|
|
||||||
|
assert!(file_exists(file));
|
||||||
|
|
||||||
|
let start_of_year = str_to_filetime("%Y%m%d%H%M.%S", "201501010000.00");
|
||||||
|
let (atime, mtime) = get_file_times(file);
|
||||||
|
assert_eq!(atime, mtime);
|
||||||
|
assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45296);
|
||||||
|
assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45296);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_touch_set_only_atime() {
|
||||||
|
let file = "test_touch_set_only_atime";
|
||||||
|
|
||||||
|
let result = run(Command::new(PROGNAME).args(&["-t", "201501011234", "-a", file]));
|
||||||
|
assert_empty_stderr!(result);
|
||||||
|
assert!(result.success);
|
||||||
|
|
||||||
|
assert!(file_exists(file));
|
||||||
|
|
||||||
|
let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
|
||||||
|
let (atime, mtime) = get_file_times(file);
|
||||||
|
assert!(atime != mtime);
|
||||||
|
assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_touch_set_only_mtime() {
|
||||||
|
let file = "test_touch_set_only_mtime";
|
||||||
|
|
||||||
|
let result = run(Command::new(PROGNAME).args(&["-t", "201501011234", "-m", file]));
|
||||||
|
assert_empty_stderr!(result);
|
||||||
|
assert!(result.success);
|
||||||
|
|
||||||
|
assert!(file_exists(file));
|
||||||
|
|
||||||
|
let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
|
||||||
|
let (atime, mtime) = get_file_times(file);
|
||||||
|
assert!(atime != mtime);
|
||||||
|
assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_touch_set_both() {
|
||||||
|
let file = "test_touch_set_both";
|
||||||
|
|
||||||
|
let result = run(Command::new(PROGNAME).args(&["-t", "201501011234", "-a", "-m", file]));
|
||||||
|
assert_empty_stderr!(result);
|
||||||
|
assert!(result.success);
|
||||||
|
|
||||||
|
assert!(file_exists(file));
|
||||||
|
|
||||||
|
let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
|
||||||
|
let (atime, mtime) = get_file_times(file);
|
||||||
|
assert_eq!(atime, mtime);
|
||||||
|
assert_eq!(atime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240);
|
||||||
|
assert_eq!(mtime.seconds_relative_to_1970() - start_of_year.seconds_relative_to_1970(), 45240);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_touch_reference() {
|
||||||
|
let file_a = "test_touch_reference_a";
|
||||||
|
let file_b = "test_touch_reference_b";
|
||||||
|
let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
|
||||||
|
|
||||||
|
touch(file_a);
|
||||||
|
set_file_times(file_a, start_of_year, start_of_year);
|
||||||
|
assert!(file_exists(file_a));
|
||||||
|
|
||||||
|
let result = run(Command::new(PROGNAME).args(&["-r", file_a, file_b]));
|
||||||
|
assert_empty_stderr!(result);
|
||||||
|
assert!(result.success);
|
||||||
|
|
||||||
|
assert!(file_exists(file_b));
|
||||||
|
|
||||||
|
let (atime, mtime) = get_file_times(file_b);
|
||||||
|
assert_eq!(atime, mtime);
|
||||||
|
assert_eq!(atime, start_of_year);
|
||||||
|
assert_eq!(mtime, start_of_year);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_touch_set_date() {
|
||||||
|
let file = "test_touch_set_date";
|
||||||
|
|
||||||
|
let result = run(Command::new(PROGNAME).args(&["-d", "Thu Jan 01 12:34:00 2015", file]));
|
||||||
|
assert_empty_stderr!(result);
|
||||||
|
assert!(result.success);
|
||||||
|
|
||||||
|
assert!(file_exists(file));
|
||||||
|
|
||||||
|
let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501011234");
|
||||||
|
let (atime, mtime) = get_file_times(file);
|
||||||
|
assert_eq!(atime, mtime);
|
||||||
|
assert_eq!(atime, start_of_year);
|
||||||
|
assert_eq!(mtime, start_of_year);
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue