Remove fscposix and begin adding native impls

This commit removes the fscposix.c file and begins implementing native
file locking mechanisms for each platform (supported platforms)

BSD-style `flock`s were added
next
Sayan Nandan 3 years ago
parent bfb74200ec
commit aca9888109

1
Cargo.lock generated

@ -686,7 +686,6 @@ version = "0.5.1"
dependencies = [
"bincode",
"bytes",
"cc",
"chrono",
"clap",
"env_logger",

@ -3,7 +3,6 @@ name = "skyd"
version = "0.5.1"
authors = ["Sayan Nandan <ohsayan@outlook.com>"]
edition = "2018"
build = "build.rs"
[dependencies]
tokio = { version = "1.5.0", features = ["full"] }
bytes = "1.0.1"
@ -26,11 +25,11 @@ openssl = { version = "0.10.33", features = ["vendored"] }
[target.'cfg(not(target_env = "msvc"))'.dependencies]
jemallocator = "0.3.2"
[target.'cfg(target_os = "windows")'.dependencies]
winapi = {version="0.3.9", features=["fileapi"]}
[dev-dependencies]
tokio = { version = "1.5.0", features = ["test-util"] }
[target.'cfg(unix)'.build-dependencies]
cc = "1.0.67"
[target.'cfg(unix)'.dependencies]
libc = "0.2.93"

@ -1,11 +0,0 @@
#[cfg(unix)]
use cc;
fn main() {
#[cfg(unix)]
{
println!("cargo:rerun-if-changed=native/fscposix.c");
cc::Build::new()
.file("native/fscposix.c")
.compile("libflock-posix.a")
}
}

@ -63,8 +63,6 @@ use tokio::net::TcpStream;
use tokio::sync::Semaphore;
use tokio::sync::{broadcast, mpsc};
use tokio::time::{self, Duration};
#[cfg(unix)]
use crate::diskstore::recordlock;
/// Responsible for gracefully shutting down the server instead of dying randomly
// Sounds very sci-fi ;)
@ -472,15 +470,6 @@ pub async fn run(
process::exit(0x100);
}
};
#[cfg(unix)]
let lock = match recordlock::FileLock::lock("data.bin") {
Ok(lock) => lock,
Err(e) => {
log::error!("Failed to acquire lock on data file with error: '{}'", e);
process::exit(0x100);
}
};
match fs::create_dir_all(&*DIR_REMOTE_SNAPSHOT) {
Ok(_) => (),
Err(e) => match e.kind() {
@ -561,11 +550,6 @@ pub async fn run(
}
}
}
#[cfg(unix)]
if let Err(e) = lock.unlock() {
log::error!("Failed to release lock on data file with error: '{}'", e);
process::exit(0x100);
}
terminal::write_info("Goodbye :)\n").unwrap();
}

@ -39,7 +39,6 @@ use std::path::PathBuf;
use std::time::Duration;
use tokio::time;
pub mod snapshot;
#[cfg(unix)]
pub mod recordlock;
mod snapstore;

@ -29,16 +29,7 @@
//! This module provides the `FileLock` struct that can be used for locking and/or unlocking files on
//! POSIX-compliant systems
use libc::c_int;
use std::fs::File;
use std::fs::OpenOptions;
use std::io::Error;
use std::os::unix::io::AsRawFd;
extern "C" {
fn lock_file(fd: i32) -> c_int;
fn unlock_file(fd: i32) -> c_int;
}
#[derive(Debug)]
/// # File Lock
@ -48,65 +39,39 @@ extern "C" {
/// the C function `lock_file` or `unlock_file` provided by the `native/fscposix.c` file (or `libflock-posix.a`)
///
/// **Note:** You need to lock a file first using this object before unlocking it!
///
///
/// ## Suggestions
///
///
/// It is always a good idea to attempt a lock release (unlock) explicitly than letting the `Drop` implementation
/// run it for you as that may cause some Wild West panic if the lock release fails (haha!)
///
///
pub struct FileLock {
file: File,
}
impl FileLock {
/// Lock a file with `filename`
///
/// If C's `fcntl` returns any error, then it is converted into the _Rust equivalent_ and returned
/// by this function
pub fn lock(filename: &str) -> Result<Self, Error> {
let file = OpenOptions::new()
.read(false)
.write(true)
.create(true)
.open(&filename)?;
let raw_err = unsafe { lock_file(file.as_raw_fd()) };
match raw_err {
0 => Ok(FileLock { file }),
x @ _ => Err(Error::from_raw_os_error(x)),
#[cfg(unix)]
mod __sys {
use libc;
use std::fs::File;
use std::io::Error;
use std::io::Result;
use std::os::unix::io::AsRawFd;
// TODO(@ohsayan): Support SOLARIS
#[cfg(not(target_os = "solaris"))]
fn flock(file: &File, flag: libc::c_int) -> Result<()> {
let ret = unsafe { libc::flock(file.as_raw_fd(), flag) };
if ret < 0 {
Err(Error::last_os_error())
} else {
Ok(())
}
}
/// Unlock a file with `filename`
///
/// If C's `fctnl` returns any error, then it is converted into the _Rust equivalent_ and returned
/// by this function
pub fn unlock(&self) -> Result<(), Error> {
let raw_err = unsafe { unlock_file(self.file.as_raw_fd()) };
match raw_err {
0 => Ok(()),
x @ _ => Err(Error::from_raw_os_error(x)),
}
}
}
impl Drop for FileLock {
fn drop(&mut self) {
if self.unlock().is_err() {
// This is wild; uh oh
panic!("Failed to release file lock!");
}
fn lock_exclusive(file: &File) -> Result<()> {
flock(file, libc::LOCK_EX)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
#[test]
fn test_basic_file_locking() {
let _ = fs::File::create("blahblah.bin").unwrap();
let lock = FileLock::lock("blahblah.bin").unwrap();
lock.unlock().unwrap();
// delete the file
fs::remove_file("blahblah.bin").unwrap();
fn try_lock_exclusive(file: &File) -> Result<()> {
flock(file, libc::LOCK_EX | libc::LOCK_NB)
}
}
}

Loading…
Cancel
Save