coreutils/src/sync/sync.rs

155 lines
4.1 KiB
Rust
Raw Normal View History

#![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.
*/
/* Last synced with: sync (GNU coreutils) 8.13 */
extern crate getopts;
extern crate libc;
2017-07-15 19:03:43 +00:00
#[cfg(windows)]
#[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;
extern {
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 {
extern crate winapi;
extern crate kernel32;
use std::{mem};
use std::fs::OpenOptions;
use std::os::windows::prelude::*;
use uucore::wide::{FromWide, ToWide};
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) {
let name_wide = name.to_wide_null();
if kernel32::GetDriveTypeW(name_wide.as_ptr()) == winbase::DRIVE_FIXED {
let sliced_name = &name[..name.len() - 1]; // eliminate trailing backslash
match OpenOptions::new().write(true).open(sliced_name) {
Ok(file) => if kernel32::FlushFileBuffers(file.as_raw_handle()) == 0 {
crash!(kernel32::GetLastError() as i32, "failed to flush file buffer");
},
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
}
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 {
crash!(kernel32::GetLastError() as i32, "failed to find first volume");
2014-06-20 12:44:35 +00:00
}
(String::from_wide_null(&name), handle)
2014-06-20 12:44:35 +00:00
}
unsafe fn find_all_volumes() -> Vec<String> {
let (first_volume, next_volume_handle) = find_first_volume();
let mut volumes = vec![first_volume];
loop {
let mut name: [winnt::WCHAR; minwindef::MAX_PATH] = mem::uninitialized();
if kernel32::FindNextVolumeW(
next_volume_handle, name.as_mut_ptr(), name.len() as minwindef::DWORD
) == 0 {
match kernel32::GetLastError() {
winerror::ERROR_NO_MORE_FILES => {
kernel32::FindVolumeClose(next_volume_handle);
return volumes
},
err => crash!(err as i32, "failed to find next volume"),
2014-06-20 12:44:35 +00:00
}
} else {
volumes.push(String::from_wide_null(&name));
2014-06-20 12:44:35 +00:00
}
}
}
pub unsafe fn do_sync() -> isize {
2014-06-20 12:44:35 +00:00
let volumes = find_all_volumes();
for vol in &volumes {
flush_volume(vol);
2014-06-20 12:44:35 +00:00
}
0
}
2014-06-15 14:25:00 +00:00
}
pub fn uumain(args: Vec<String>) -> i32 {
let mut opts = getopts::Options::new();
2014-06-15 14:25:00 +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
let matches = match opts.parse(&args[1..]) {
2014-06-15 14:25:00 +00:00
Ok(m) => { m }
_ => { help(&opts); return 1 }
2014-06-15 14:25:00 +00:00
};
if matches.opt_present("h") {
help(&opts);
2014-06-15 14:25:00 +00:00
return 0
}
if matches.opt_present("V") {
version();
return 0
}
sync();
2014-06-15 14:25:00 +00:00
0
}
fn version() {
println!("{} (uutils) {}", NAME, VERSION);
2014-06-15 14:25:00 +00:00
println!("The MIT License");
println!("");
println!("Author -- Alexander Fomin.");
}
fn help(opts: &getopts::Options) {
let msg = format!("{0} {1}
Usage:
{0} [OPTION]
Force changed blocks to disk, update the super block.", NAME, VERSION);
print!("{}", opts.usage(&msg));
2014-06-15 14:25:00 +00:00
}
2014-06-20 12:44:35 +00:00
fn sync() -> isize {
2014-06-20 12:44:35 +00:00
unsafe {
platform::do_sync()
}
}