mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-12-03 06:22:32 -05:00
use nix to remove many uses of unsafe
This commit is contained in:
@@ -32,7 +32,7 @@
|
||||
|
||||
use crate::dir;
|
||||
use failure::{Error, bail, format_err};
|
||||
use libc;
|
||||
use nix::fcntl::FlockArg;
|
||||
use protobuf::prelude::MessageField;
|
||||
use rusqlite::types::ToSql;
|
||||
use crate::schema::DirMeta;
|
||||
@@ -47,7 +47,7 @@ pub fn run(args: &super::Args, tx: &rusqlite::Transaction) -> Result<(), Error>
|
||||
schema version 1 to 2."))?;
|
||||
|
||||
let d = dir::Fd::open(sample_file_path, false)?;
|
||||
d.lock(libc::LOCK_EX | libc::LOCK_NB)?;
|
||||
d.lock(FlockArg::LockExclusiveNonblock)?;
|
||||
verify_dir_contents(sample_file_path, tx)?;
|
||||
|
||||
// These create statements match the schema.sql when version 2 was the latest.
|
||||
|
||||
@@ -35,12 +35,11 @@
|
||||
use crate::db::{self, FromSqlUuid};
|
||||
use crate::dir;
|
||||
use failure::Error;
|
||||
use libc;
|
||||
use crate::schema;
|
||||
use protobuf::prelude::MessageField;
|
||||
use rusqlite::types::ToSql;
|
||||
use std::io::{self, Write};
|
||||
use std::mem;
|
||||
use std::io::Write;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::sync::Arc;
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -90,10 +89,10 @@ pub fn run(_args: &super::Args, tx: &rusqlite::Transaction) -> Result<(), Error>
|
||||
let id = db::CompositeId(row.get(0)?);
|
||||
let sample_file_uuid: FromSqlUuid = row.get(1)?;
|
||||
let from_path = get_uuid_pathname(sample_file_uuid.0);
|
||||
let to_path = get_id_pathname(id);
|
||||
let r = unsafe { dir::renameat(&d.fd, from_path.as_ptr(), &d.fd, to_path.as_ptr()) };
|
||||
if let Err(e) = r {
|
||||
if e.kind() == io::ErrorKind::NotFound {
|
||||
let to_path = crate::dir::CompositeIdPath::from(id);
|
||||
if let Err(e) = nix::fcntl::renameat(d.fd.as_raw_fd(), &from_path[..],
|
||||
d.fd.as_raw_fd(), &to_path) {
|
||||
if e == nix::Error::Sys(nix::errno::Errno::ENOENT) {
|
||||
continue; // assume it was already moved.
|
||||
}
|
||||
Err(e)?;
|
||||
@@ -122,17 +121,9 @@ pub fn run(_args: &super::Args, tx: &rusqlite::Transaction) -> Result<(), Error>
|
||||
}
|
||||
|
||||
/// Gets a pathname for a sample file suitable for passing to open or unlink.
|
||||
fn get_uuid_pathname(uuid: Uuid) -> [libc::c_char; 37] {
|
||||
fn get_uuid_pathname(uuid: Uuid) -> [u8; 37] {
|
||||
let mut buf = [0u8; 37];
|
||||
write!(&mut buf[..36], "{}", uuid.to_hyphenated_ref())
|
||||
.expect("can't format uuid to pathname buf");
|
||||
|
||||
// libc::c_char seems to be i8 on some platforms (Linux/arm) and u8 on others (Linux/amd64).
|
||||
unsafe { mem::transmute::<[u8; 37], [libc::c_char; 37]>(buf) }
|
||||
}
|
||||
|
||||
fn get_id_pathname(id: db::CompositeId) -> [libc::c_char; 17] {
|
||||
let mut buf = [0u8; 17];
|
||||
write!(&mut buf[..16], "{:016x}", id.0).expect("can't format id to pathname buf");
|
||||
unsafe { mem::transmute::<[u8; 17], [libc::c_char; 17]>(buf) }
|
||||
buf
|
||||
}
|
||||
|
||||
@@ -37,9 +37,12 @@ use crate::db::FromSqlUuid;
|
||||
use crate::{dir, schema};
|
||||
use cstr::*;
|
||||
use failure::{Error, Fail, bail};
|
||||
use nix::fcntl::{FlockArg, OFlag};
|
||||
use nix::sys::stat::Mode;
|
||||
use protobuf::{Message, prelude::MessageField};
|
||||
use rusqlite::params;
|
||||
use std::io::{Read, Write};
|
||||
use std::os::unix::io::AsRawFd;
|
||||
|
||||
const FIXED_DIR_META_LEN: usize = 512;
|
||||
|
||||
@@ -76,10 +79,10 @@ pub fn run(_args: &super::Args, tx: &rusqlite::Transaction) -> Result<(), Error>
|
||||
}
|
||||
|
||||
let dir = dir::Fd::open(path, false)?;
|
||||
dir.lock(libc::LOCK_EX)?;
|
||||
dir.lock(FlockArg::LockExclusiveNonblock)?;
|
||||
let tmp_path = cstr!("meta.tmp");
|
||||
let path = cstr!("meta");
|
||||
let mut f = unsafe { dir.openat(path.as_ptr(), libc::O_RDONLY, 0) }?;
|
||||
let mut f = dir.openat(path, OFlag::O_RDONLY, Mode::empty())?;
|
||||
let mut data = Vec::new();
|
||||
f.read_to_end(&mut data)?;
|
||||
if data.len() == FIXED_DIR_META_LEN {
|
||||
@@ -92,8 +95,8 @@ pub fn run(_args: &super::Args, tx: &rusqlite::Transaction) -> Result<(), Error>
|
||||
if !dir::SampleFileDir::consistent(&db_meta, &dir_meta) {
|
||||
bail!("Inconsistent db_meta={:?} dir_meta={:?}", &db_meta, &dir_meta);
|
||||
}
|
||||
let mut f = unsafe { dir.openat(tmp_path.as_ptr(),
|
||||
libc::O_CREAT | libc::O_TRUNC | libc::O_WRONLY, 0o600)? };
|
||||
let mut f = dir.openat(tmp_path, OFlag::O_CREAT | OFlag::O_TRUNC | OFlag::O_WRONLY,
|
||||
Mode::S_IRUSR | Mode::S_IWUSR)?;
|
||||
let mut data =
|
||||
dir_meta.write_length_delimited_to_bytes().expect("proto3->vec is infallible");
|
||||
if data.len() > FIXED_DIR_META_LEN {
|
||||
@@ -103,7 +106,7 @@ pub fn run(_args: &super::Args, tx: &rusqlite::Transaction) -> Result<(), Error>
|
||||
data.resize(FIXED_DIR_META_LEN, 0); // pad to required length.
|
||||
f.write_all(&data)?;
|
||||
f.sync_all()?;
|
||||
unsafe { dir::renameat(&dir, tmp_path.as_ptr(), &dir, path.as_ptr())? };
|
||||
nix::fcntl::renameat(dir.as_raw_fd(), tmp_path, dir.as_raw_fd(), path)?;
|
||||
dir.sync()?;
|
||||
}
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user