use nix to remove many uses of unsafe

This commit is contained in:
Scott Lamb
2019-07-11 21:59:01 -07:00
parent d75157af56
commit bb227491b6
11 changed files with 142 additions and 139 deletions

View File

@@ -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.

View File

@@ -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
}

View File

@@ -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(())