2015-12-08 02:42:08 +00:00
|
|
|
#![crate_name = "uu_sync"]
|
2015-01-10 19:31:55 +00:00
|
|
|
|
2014-06-15 14:25:00 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the uutils coreutils package.
|
|
|
|
*
|
|
|
|
* (c) Alexander Fomin <xander.fomin@ya.ru>
|
|
|
|
*
|
|
|
|
* For the full copyright and license information, please view the LICENSE
|
|
|
|
* file that was distributed with this source code.
|
|
|
|
*/
|
|
|
|
|
2018-03-12 08:20:58 +00:00
|
|
|
/* Last synced with: sync (GNU coreutils) 8.13 */
|
2014-06-15 14:25:00 +00:00
|
|
|
|
|
|
|
extern crate getopts;
|
|
|
|
extern crate libc;
|
|
|
|
|
2017-07-15 19:03:43 +00:00
|
|
|
#[cfg(windows)]
|
2015-11-24 01:00:51 +00:00
|
|
|
#[macro_use]
|
|
|
|
extern crate uucore;
|
2014-06-20 12:44:35 +00:00
|
|
|
|
2017-07-15 19:03:43 +00:00
|
|
|
#[cfg(not(windows))]
|
|
|
|
extern crate uucore;
|
|
|
|
|
2014-08-15 22:53:23 +00:00
|
|
|
static NAME: &'static str = "sync";
|
2015-11-25 09:52:10 +00:00
|
|
|
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
2014-08-15 22:53:23 +00:00
|
|
|
|
2014-06-20 12:44:35 +00:00
|
|
|
#[cfg(unix)]
|
|
|
|
mod platform {
|
|
|
|
use super::libc;
|
|
|
|
|
2018-03-12 08:20:58 +00:00
|
|
|
extern "C" {
|
2014-06-20 12:44:35 +00:00
|
|
|
fn sync() -> libc::c_void;
|
|
|
|
}
|
|
|
|
|
2015-01-10 18:07:08 +00:00
|
|
|
pub unsafe fn do_sync() -> isize {
|
2014-06-20 12:44:35 +00:00
|
|
|
sync();
|
|
|
|
0
|
|
|
|
}
|
2014-06-15 14:25:00 +00:00
|
|
|
}
|
|
|
|
|
2014-06-20 12:44:35 +00:00
|
|
|
#[cfg(windows)]
|
|
|
|
mod platform {
|
2015-07-20 00:25:48 +00:00
|
|
|
extern crate kernel32;
|
2018-03-12 08:20:58 +00:00
|
|
|
extern crate winapi;
|
|
|
|
use std::mem;
|
2015-07-20 00:25:48 +00:00
|
|
|
use std::fs::OpenOptions;
|
|
|
|
use std::os::windows::prelude::*;
|
2015-11-24 01:00:51 +00:00
|
|
|
use uucore::wide::{FromWide, ToWide};
|
2018-03-05 02:07:38 +00:00
|
|
|
use self::winapi::um::winbase;
|
|
|
|
use self::winapi::um::winnt;
|
|
|
|
use self::winapi::shared::minwindef;
|
|
|
|
use self::winapi::um::handleapi;
|
|
|
|
use self::winapi::shared::winerror;
|
2014-06-20 12:44:35 +00:00
|
|
|
|
|
|
|
unsafe fn flush_volume(name: &str) {
|
2015-07-20 00:25:48 +00:00
|
|
|
let name_wide = name.to_wide_null();
|
2018-03-05 02:07:38 +00:00
|
|
|
if kernel32::GetDriveTypeW(name_wide.as_ptr()) == winbase::DRIVE_FIXED {
|
2015-01-25 06:46:55 +00:00
|
|
|
let sliced_name = &name[..name.len() - 1]; // eliminate trailing backslash
|
2015-07-20 00:25:48 +00:00
|
|
|
match OpenOptions::new().write(true).open(sliced_name) {
|
|
|
|
Ok(file) => if kernel32::FlushFileBuffers(file.as_raw_handle()) == 0 {
|
2018-03-12 08:20:58 +00:00
|
|
|
crash!(
|
|
|
|
kernel32::GetLastError() as i32,
|
|
|
|
"failed to flush file buffer"
|
|
|
|
);
|
2015-07-20 00:25:48 +00:00
|
|
|
},
|
2018-03-12 08:20:58 +00:00
|
|
|
Err(e) => crash!(
|
|
|
|
e.raw_os_error().unwrap_or(1),
|
|
|
|
"failed to create volume handle"
|
|
|
|
),
|
2014-06-20 12:44:35 +00:00
|
|
|
}
|
2014-09-24 05:28:07 +00:00
|
|
|
}
|
2014-06-20 12:44:35 +00:00
|
|
|
}
|
|
|
|
|
2018-03-05 02:07:38 +00:00
|
|
|
unsafe fn find_first_volume() -> (String, winnt::HANDLE) {
|
|
|
|
let mut name: [winnt::WCHAR; minwindef::MAX_PATH] = mem::uninitialized();
|
|
|
|
let handle = kernel32::FindFirstVolumeW(name.as_mut_ptr(), name.len() as minwindef::DWORD);
|
|
|
|
if handle == handleapi::INVALID_HANDLE_VALUE {
|
2018-03-12 08:20:58 +00:00
|
|
|
crash!(
|
|
|
|
kernel32::GetLastError() as i32,
|
|
|
|
"failed to find first volume"
|
|
|
|
);
|
2014-06-20 12:44:35 +00:00
|
|
|
}
|
2015-07-20 00:25:48 +00:00
|
|
|
(String::from_wide_null(&name), handle)
|
2014-06-20 12:44:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsafe fn find_all_volumes() -> Vec<String> {
|
2015-07-20 00:25:48 +00:00
|
|
|
let (first_volume, next_volume_handle) = find_first_volume();
|
|
|
|
let mut volumes = vec![first_volume];
|
|
|
|
loop {
|
2018-03-05 02:07:38 +00:00
|
|
|
let mut name: [winnt::WCHAR; minwindef::MAX_PATH] = mem::uninitialized();
|
2015-07-20 00:25:48 +00:00
|
|
|
if kernel32::FindNextVolumeW(
|
2018-03-12 08:20:58 +00:00
|
|
|
next_volume_handle,
|
|
|
|
name.as_mut_ptr(),
|
|
|
|
name.len() as minwindef::DWORD,
|
|
|
|
) == 0
|
|
|
|
{
|
2015-07-20 00:25:48 +00:00
|
|
|
match kernel32::GetLastError() {
|
2018-03-05 02:07:38 +00:00
|
|
|
winerror::ERROR_NO_MORE_FILES => {
|
2015-07-20 00:25:48 +00:00
|
|
|
kernel32::FindVolumeClose(next_volume_handle);
|
2018-03-12 08:20:58 +00:00
|
|
|
return volumes;
|
|
|
|
}
|
2015-07-20 00:25:48 +00:00
|
|
|
err => crash!(err as i32, "failed to find next volume"),
|
2014-06-20 12:44:35 +00:00
|
|
|
}
|
2015-07-20 00:25:48 +00:00
|
|
|
} else {
|
|
|
|
volumes.push(String::from_wide_null(&name));
|
2014-06-20 12:44:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-20 00:25:48 +00:00
|
|
|
pub unsafe fn do_sync() -> isize {
|
2014-06-20 12:44:35 +00:00
|
|
|
let volumes = find_all_volumes();
|
2015-07-20 00:25:48 +00:00
|
|
|
for vol in &volumes {
|
|
|
|
flush_volume(vol);
|
2014-06-20 12:44:35 +00:00
|
|
|
}
|
|
|
|
0
|
|
|
|
}
|
2014-06-15 14:25:00 +00:00
|
|
|
}
|
|
|
|
|
2015-02-06 13:48:07 +00:00
|
|
|
pub fn uumain(args: Vec<String>) -> i32 {
|
2015-05-21 18:42:42 +00:00
|
|
|
let mut opts = getopts::Options::new();
|
2014-06-15 14:25:00 +00:00
|
|
|
|
2015-05-21 18:42:42 +00:00
|
|
|
opts.optflag("h", "help", "display this help and exit");
|
|
|
|
opts.optflag("V", "version", "output version information and exit");
|
2014-06-15 14:25:00 +00:00
|
|
|
|
2015-05-21 18:42:42 +00:00
|
|
|
let matches = match opts.parse(&args[1..]) {
|
2018-03-12 08:20:58 +00:00
|
|
|
Ok(m) => m,
|
|
|
|
_ => {
|
|
|
|
help(&opts);
|
|
|
|
return 1;
|
|
|
|
}
|
2014-06-15 14:25:00 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if matches.opt_present("h") {
|
2015-05-21 18:42:42 +00:00
|
|
|
help(&opts);
|
2018-03-12 08:20:58 +00:00
|
|
|
return 0;
|
2014-06-15 14:25:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if matches.opt_present("V") {
|
|
|
|
version();
|
2018-03-12 08:20:58 +00:00
|
|
|
return 0;
|
2014-06-15 14:25:00 +00:00
|
|
|
}
|
|
|
|
|
2015-01-10 21:00:15 +00:00
|
|
|
sync();
|
2014-06-15 14:25:00 +00:00
|
|
|
0
|
|
|
|
}
|
|
|
|
|
|
|
|
fn version() {
|
2014-09-17 03:08:40 +00:00
|
|
|
println!("{} (uutils) {}", NAME, VERSION);
|
2014-06-15 14:25:00 +00:00
|
|
|
println!("The MIT License");
|
|
|
|
println!("");
|
|
|
|
println!("Author -- Alexander Fomin.");
|
|
|
|
}
|
|
|
|
|
2015-05-21 18:42:42 +00:00
|
|
|
fn help(opts: &getopts::Options) {
|
2018-03-12 08:20:58 +00:00
|
|
|
let msg = format!(
|
|
|
|
"{0} {1}
|
2015-05-21 18:42:42 +00:00
|
|
|
|
|
|
|
Usage:
|
|
|
|
{0} [OPTION]
|
|
|
|
|
2018-03-12 08:20:58 +00:00
|
|
|
Force changed blocks to disk, update the super block.",
|
|
|
|
NAME, VERSION
|
|
|
|
);
|
2015-05-21 18:42:42 +00:00
|
|
|
|
|
|
|
print!("{}", opts.usage(&msg));
|
2014-06-15 14:25:00 +00:00
|
|
|
}
|
2014-06-20 12:44:35 +00:00
|
|
|
|
2015-01-10 21:00:15 +00:00
|
|
|
fn sync() -> isize {
|
2018-03-12 08:20:58 +00:00
|
|
|
unsafe { platform::do_sync() }
|
2014-06-26 05:56:03 +00:00
|
|
|
}
|