coreutils/src/sync/sync.rs

147 lines
3.9 KiB
Rust
Raw Normal View History

#![crate_name = "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;
2015-01-08 12:54:22 +00:00
#[path = "../common/util.rs"] #[macro_use] mod util;
2014-06-20 12:44:35 +00:00
2014-08-15 22:53:23 +00:00
static NAME: &'static str = "sync";
static VERSION: &'static str = "1.0.0";
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;
#[path = "../../common/wide.rs"] mod wide;
use std::{mem};
use std::fs::OpenOptions;
use std::io::{Write};
use std::os::windows::prelude::*;
use self::wide::{FromWide, ToWide};
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()) == winapi::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, winapi::HANDLE) {
let mut name: [winapi::WCHAR; winapi::MAX_PATH] = mem::uninitialized();
let handle = kernel32::FindFirstVolumeW(name.as_mut_ptr(), name.len() as winapi::DWORD);
if handle == winapi::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: [winapi::WCHAR; winapi::MAX_PATH] = mem::uninitialized();
if kernel32::FindNextVolumeW(
next_volume_handle, name.as_mut_ptr(), name.len() as winapi::DWORD
) == 0 {
match kernel32::GetLastError() {
winapi::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()
}
}