mirror of
https://github.com/mgree/ffs.git
synced 2024-08-17 07:10:35 +03:00
Mountpoints are typically inferred/generated from filenames with a -m/--mount flag for when reading from STDIN or to manually specify a mountpoint.
This commit is contained in:
parent
4639d31cc6
commit
4aff907523
@ -16,7 +16,25 @@ pub struct Config {
|
|||||||
pub base64: base64::Config,
|
pub base64: base64::Config,
|
||||||
pub try_decode_base64: bool,
|
pub try_decode_base64: bool,
|
||||||
pub read_only: bool,
|
pub read_only: bool,
|
||||||
|
pub input: Input,
|
||||||
pub output: Output,
|
pub output: Output,
|
||||||
|
pub mount: Option<PathBuf>,
|
||||||
|
pub cleanup_mount: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Input {
|
||||||
|
Stdin,
|
||||||
|
File(PathBuf),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Input {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||||
|
match self {
|
||||||
|
Input::Stdin => write!(f, "<stdin>"),
|
||||||
|
Input::File(file) => write!(f, "{}", file.display()),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -68,7 +86,10 @@ impl Default for Config {
|
|||||||
base64: base64::STANDARD,
|
base64: base64::STANDARD,
|
||||||
try_decode_base64: false,
|
try_decode_base64: false,
|
||||||
read_only: false,
|
read_only: false,
|
||||||
|
input: Input::Stdin,
|
||||||
output: Output::Stdout,
|
output: Output::Stdout,
|
||||||
|
mount: None,
|
||||||
|
cleanup_mount: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
169
src/main.rs
169
src/main.rs
@ -1,5 +1,4 @@
|
|||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
|
|
||||||
@ -11,7 +10,7 @@ mod config;
|
|||||||
mod format;
|
mod format;
|
||||||
mod fs;
|
mod fs;
|
||||||
|
|
||||||
use config::{Config, Output};
|
use config::{Config, Input, Output};
|
||||||
use format::Format;
|
use format::Format;
|
||||||
|
|
||||||
use fuser::MountOption;
|
use fuser::MountOption;
|
||||||
@ -121,15 +120,16 @@ fn main() {
|
|||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("MOUNT")
|
Arg::with_name("MOUNT")
|
||||||
.help("Sets the mountpoint")
|
.help("Sets the mountpoint; will be inferred when using a file, but must be specified when running on stdin")
|
||||||
.required(true)
|
.long("mount")
|
||||||
.index(1),
|
.short("m")
|
||||||
|
.takes_value(true)
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("INPUT")
|
Arg::with_name("INPUT")
|
||||||
.help("Sets the input file (defaults to '-', meaning STDIN)")
|
.help("Sets the input file (defaults to '-', meaning STDIN)")
|
||||||
.default_value("-")
|
.default_value("-")
|
||||||
.index(2),
|
.index(1),
|
||||||
)
|
)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
|
||||||
@ -193,13 +193,6 @@ fn main() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 2021-06-08 infer and create mountpoint from filename as possible
|
|
||||||
let mount_point = Path::new(args.value_of("MOUNT").expect("mount point"));
|
|
||||||
if !mount_point.exists() {
|
|
||||||
error!("Mount point {} does not exist.", mount_point.display());
|
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
match args.value_of("UID") {
|
match args.value_of("UID") {
|
||||||
Some(uid_string) => match uid_string.parse() {
|
Some(uid_string) => match uid_string.parse() {
|
||||||
Ok(uid) => config.uid = uid,
|
Ok(uid) => config.uid = uid,
|
||||||
@ -229,15 +222,32 @@ fn main() {
|
|||||||
None => config.gid = unsafe { libc::getegid() },
|
None => config.gid = unsafe { libc::getegid() },
|
||||||
}
|
}
|
||||||
|
|
||||||
let input_source = args.value_of("INPUT").expect("input source");
|
config.input = match args.value_of("INPUT") {
|
||||||
|
Some(input_source) => {
|
||||||
|
if input_source == "-" {
|
||||||
|
Input::Stdin
|
||||||
|
} else {
|
||||||
|
let input_source = PathBuf::from(input_source);
|
||||||
|
if !input_source.exists() {
|
||||||
|
error!("Input file {} does not exist.", input_source.display());
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
Input::File(input_source)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => Input::Stdin,
|
||||||
|
};
|
||||||
config.output = if let Some(output) = args.value_of("OUTPUT") {
|
config.output = if let Some(output) = args.value_of("OUTPUT") {
|
||||||
Output::File(PathBuf::from(output))
|
Output::File(PathBuf::from(output))
|
||||||
} else if args.is_present("INPLACE") {
|
} else if args.is_present("INPLACE") {
|
||||||
if input_source == "-" {
|
match &config.input {
|
||||||
warn!("In-place output `-i` with STDIN input makes no sense; outputting on STDOUT.");
|
Input::Stdin => {
|
||||||
Output::Stdout
|
warn!(
|
||||||
} else {
|
"In-place output `-i` with STDIN input makes no sense; outputting on STDOUT."
|
||||||
Output::File(PathBuf::from(input_source))
|
);
|
||||||
|
Output::Stdout
|
||||||
|
}
|
||||||
|
Input::File(input_source) => Output::File(input_source.clone()),
|
||||||
}
|
}
|
||||||
} else if args.is_present("NOOUTPUT") || args.is_present("QUIET") {
|
} else if args.is_present("NOOUTPUT") || args.is_present("QUIET") {
|
||||||
Output::Quiet
|
Output::Quiet
|
||||||
@ -245,6 +255,54 @@ fn main() {
|
|||||||
Output::Stdout
|
Output::Stdout
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// infer and create mountpoint from filename as possible
|
||||||
|
config.mount = match args.value_of("MOUNT") {
|
||||||
|
Some(mount_point) => {
|
||||||
|
let mount_point = PathBuf::from(mount_point);
|
||||||
|
if !mount_point.exists() {
|
||||||
|
error!("Mount point {} does not exist.", mount_point.display());
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
config.cleanup_mount = false;
|
||||||
|
Some(mount_point)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
match &config.input {
|
||||||
|
Input::Stdin => {
|
||||||
|
error!("You must specify a mount point when reading from stdin.");
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
Input::File(file) => {
|
||||||
|
// If the input is from a file foo.EXT, then try to make a directory foo.
|
||||||
|
let mount_dir = file.with_extension("");
|
||||||
|
|
||||||
|
// If that file already exists, give up and tell the user about --mount.
|
||||||
|
if mount_dir.exists() {
|
||||||
|
error!("Inferred mountpoint '{mount}' for input file '{file}', but '{mount}' already exists. Use `--mount MOUNT` to specify a mountpoint.",
|
||||||
|
mount = mount_dir.display(), file = file.display());
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the mountpoint can't be created, give up and tell the user about --mount.
|
||||||
|
if let Err(e) = std::fs::create_dir(&mount_dir) {
|
||||||
|
error!(
|
||||||
|
"Couldn't create mountpoint '{}': {}. Use `--mount MOUNT` to specify a mountpoint.",
|
||||||
|
mount_dir.display(),
|
||||||
|
e
|
||||||
|
);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We did it!
|
||||||
|
config.cleanup_mount = true;
|
||||||
|
Some(mount_dir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
assert!(config.mount.is_some());
|
||||||
|
|
||||||
// try to autodetect the input format.
|
// try to autodetect the input format.
|
||||||
//
|
//
|
||||||
// first see if it's specified and parses okay.
|
// first see if it's specified and parses okay.
|
||||||
@ -268,18 +326,23 @@ fn main() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match Path::new(input_source)
|
match &config.input {
|
||||||
.extension() // will fail for STDIN, no worries
|
Input::Stdin => Format::Json,
|
||||||
.map(|s| s.to_str().expect("utf8 filename").to_lowercase())
|
Input::File(input_source) => match input_source
|
||||||
{
|
.extension()
|
||||||
Some(s) => match s.parse::<Format>() {
|
.and_then(|s| s.to_str())
|
||||||
|
.ok_or(format::ParseFormatError::NoFormatProvided)
|
||||||
|
.and_then(|s| s.parse::<Format>())
|
||||||
|
{
|
||||||
Ok(format) => format,
|
Ok(format) => format,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
warn!("Unrecognized format {}, defaulting to JSON.", s);
|
warn!(
|
||||||
|
"Unrecognized format {}, defaulting to JSON.",
|
||||||
|
input_source.display()
|
||||||
|
);
|
||||||
Format::Json
|
Format::Json
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => Format::Json,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -330,7 +393,11 @@ fn main() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut options = vec![MountOption::FSName(input_source.into())];
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
// DONE PARSING
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
let mut options = vec![MountOption::FSName(format!("{}", config.input))];
|
||||||
if args.is_present("AUTOUNMOUNT") {
|
if args.is_present("AUTOUNMOUNT") {
|
||||||
options.push(MountOption::AutoUnmount);
|
options.push(MountOption::AutoUnmount);
|
||||||
}
|
}
|
||||||
@ -338,19 +405,45 @@ fn main() {
|
|||||||
options.push(MountOption::RO);
|
options.push(MountOption::RO);
|
||||||
}
|
}
|
||||||
|
|
||||||
let input_format = config.input_format;
|
assert!(config.mount.is_some());
|
||||||
let reader: Box<dyn std::io::Read> = if input_source == "-" {
|
let mount = match &config.mount {
|
||||||
Box::new(std::io::stdin())
|
Some(mount) => mount.clone(),
|
||||||
} else {
|
None => {
|
||||||
let file = std::fs::File::open(input_source).unwrap_or_else(|e| {
|
error!(
|
||||||
error!("Unable to open {} for JSON input: {}", input_source, e);
|
"No mount point specified; aborting. Use `--mount MOUNT` to specify a mountpoint."
|
||||||
|
);
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
});
|
}
|
||||||
Box::new(file)
|
};
|
||||||
|
let cleanup_mount = config.cleanup_mount;
|
||||||
|
let input_format = config.input_format;
|
||||||
|
let reader: Box<dyn std::io::Read> = match &config.input {
|
||||||
|
Input::Stdin => Box::new(std::io::stdin()),
|
||||||
|
Input::File(file) => {
|
||||||
|
let fmt = config.input_format;
|
||||||
|
let file = std::fs::File::open(&file).unwrap_or_else(|e| {
|
||||||
|
error!("Unable to open {} for {} input: {}", file.display(), fmt, e);
|
||||||
|
std::process::exit(1);
|
||||||
|
});
|
||||||
|
Box::new(file)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let fs = input_format.load(reader, config);
|
let fs = input_format.load(reader, config);
|
||||||
|
|
||||||
info!("mounting on {:?} with options {:?}", mount_point, options);
|
info!("mounting on {:?} with options {:?}", mount, options);
|
||||||
fuser::mount2(fs, mount_point, &options).unwrap();
|
fuser::mount2(fs, &mount, &options).unwrap();
|
||||||
info!("unmounted");
|
info!("unmounted");
|
||||||
|
|
||||||
|
if cleanup_mount {
|
||||||
|
if mount.exists() {
|
||||||
|
if let Err(e) = std::fs::remove_dir(&mount) {
|
||||||
|
warn!("Unable to clean up mountpoint '{}': {}", mount.display(), e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!(
|
||||||
|
"Mountpoint '{}' disappeared before ffs could cleanup.",
|
||||||
|
mount.display()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ MNT=$(mktemp -d)
|
|||||||
OUT=$(mktemp)
|
OUT=$(mktemp)
|
||||||
MSG=$(mktemp)
|
MSG=$(mktemp)
|
||||||
|
|
||||||
ffs "$MNT" ../json/null.json >"$OUT" 2>"$MSG" &
|
ffs -m "$MNT" ../json/null.json >"$OUT" 2>"$MSG" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 1
|
sleep 1
|
||||||
kill -0 $PID >/dev/null 2>&1 && fail process
|
kill -0 $PID >/dev/null 2>&1 && fail process
|
||||||
|
@ -15,7 +15,7 @@ MNT=$(mktemp -d)
|
|||||||
OUT=$(mktemp)
|
OUT=$(mktemp)
|
||||||
MSG=$(mktemp)
|
MSG=$(mktemp)
|
||||||
|
|
||||||
echo \"just a string\" | ffs "$MNT" >"$OUT" 2>"$MSG" &
|
echo \"just a string\" | ffs -m "$MNT" >"$OUT" 2>"$MSG" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 1
|
sleep 1
|
||||||
kill -0 $PID >/dev/null 2>&1 && fail process
|
kill -0 $PID >/dev/null 2>&1 && fail process
|
||||||
|
@ -13,7 +13,7 @@ fail() {
|
|||||||
|
|
||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
|
|
||||||
ffs "$MNT" ../json/list.json &
|
ffs -m "$MNT" ../json/list.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -13,7 +13,7 @@ fail() {
|
|||||||
|
|
||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
|
|
||||||
ffs "$MNT" ../json/object.json &
|
ffs -m "$MNT" ../json/object.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -22,7 +22,7 @@ printf "10" >"${EXP}/fingernails"
|
|||||||
printf "true" >"${EXP}/human"
|
printf "true" >"${EXP}/human"
|
||||||
printf "" >"${EXP}/problems"
|
printf "" >"${EXP}/problems"
|
||||||
|
|
||||||
ffs "$MNT" ../json/object_null.json &
|
ffs -m "$MNT" ../json/object_null.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -22,7 +22,7 @@ printf "10\n" >"${EXP}/fingernails"
|
|||||||
printf "true\n" >"${EXP}/human"
|
printf "true\n" >"${EXP}/human"
|
||||||
printf "" >"${EXP}/problems"
|
printf "" >"${EXP}/problems"
|
||||||
|
|
||||||
ffs --newline "$MNT" ../json/object_null.json &
|
ffs --newline -m "$MNT" ../json/object_null.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -13,7 +13,7 @@ fail() {
|
|||||||
|
|
||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
|
|
||||||
cat ../json/object.json | ffs "$MNT" &
|
cat ../json/object.json | ffs -m "$MNT" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -13,7 +13,7 @@ fail() {
|
|||||||
|
|
||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
|
|
||||||
ffs "$MNT" ../toml/eg.toml &
|
ffs -m "$MNT" ../toml/eg.toml &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
case $(ls "$MNT") in
|
case $(ls "$MNT") in
|
||||||
|
@ -30,7 +30,7 @@ MNT=$(mktemp -d)
|
|||||||
TGT=$(mktemp)
|
TGT=$(mktemp)
|
||||||
TGT2=$(mktemp)
|
TGT2=$(mktemp)
|
||||||
|
|
||||||
ffs "$MNT" ../json/object.json >"$TGT" &
|
ffs -m "$MNT" ../json/object.json >"$TGT" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cp ../binary/twitter.ico "$MNT"/favicon
|
cp ../binary/twitter.ico "$MNT"/favicon
|
||||||
@ -42,7 +42,7 @@ kill -0 $PID >/dev/null 2>&1 && fail process1
|
|||||||
[ -f "$TGT" ] || fail output1
|
[ -f "$TGT" ] || fail output1
|
||||||
[ -s "$TGT" ] || fail output2
|
[ -s "$TGT" ] || fail output2
|
||||||
grep favicon "$TGT" >/dev/null 2>&1 || fail text
|
grep favicon "$TGT" >/dev/null 2>&1 || fail text
|
||||||
ffs --no-output "$MNT" "$TGT" >"$TGT2" &
|
ffs --no-output -m "$MNT" "$TGT" >"$TGT2" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ MNT=$(mktemp -d)
|
|||||||
TGT=$(mktemp)
|
TGT=$(mktemp)
|
||||||
TGT2=$(mktemp)
|
TGT2=$(mktemp)
|
||||||
|
|
||||||
ffs "$MNT" ../json/object.json >"$TGT" &
|
ffs -m "$MNT" ../json/object.json >"$TGT" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
echo 'echo hi' >"$MNT"/script
|
echo 'echo hi' >"$MNT"/script
|
||||||
@ -31,7 +31,7 @@ kill -0 $PID >/dev/null 2>&1 && fail process1
|
|||||||
[ -f "$TGT" ] || fail output1
|
[ -f "$TGT" ] || fail output1
|
||||||
[ -s "$TGT" ] || fail output2
|
[ -s "$TGT" ] || fail output2
|
||||||
grep -e echo "$TGT" >/dev/null 2>&1 || fail grep
|
grep -e echo "$TGT" >/dev/null 2>&1 || fail grep
|
||||||
ffs --no-output --source json "$MNT" "$TGT" >"$TGT2" &
|
ffs --no-output --source json -m "$MNT" "$TGT" >"$TGT2" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
|
@ -15,14 +15,11 @@ fail() {
|
|||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
ERR=$(mktemp)
|
ERR=$(mktemp)
|
||||||
|
|
||||||
RUST_LOG="ffs=debug" ffs -d --no-output "$MNT" ../json/object.json &
|
ffs -d --no-output -m "$MNT" ../json/object.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
chown :nobody "$MNT"/name 2>$ERR >&2 && fail "chgrp1: $(cat $ERR)"
|
chown :nobody "$MNT"/name 2>$ERR >&2 && fail "chgrp1: $(cat $ERR)"
|
||||||
[ -s "$ERR" ] || fail "chgrp1 error: $(cat $ERR)"
|
[ -s "$ERR" ] || fail "chgrp1 error: $(cat $ERR)"
|
||||||
groups
|
|
||||||
ls -l "$MNT"/name
|
|
||||||
echo $(groups | cut -d' ' -f 1)
|
|
||||||
chown :$(groups | cut -d' ' -f 1) "$MNT"/name 2>$ERR >&2 || fail "chgrp2: $(cat $ERR)"
|
chown :$(groups | cut -d' ' -f 1) "$MNT"/name 2>$ERR >&2 || fail "chgrp2: $(cat $ERR)"
|
||||||
[ -s "$ERR" ] && fail "chgrp2 error: $(cat $ERR)"
|
[ -s "$ERR" ] && fail "chgrp2 error: $(cat $ERR)"
|
||||||
chown $(whoami) "$MNT"/name 2>$ERR >&2 || fail chown
|
chown $(whoami) "$MNT"/name 2>$ERR >&2 || fail chown
|
||||||
|
@ -25,7 +25,7 @@ printf "true" >"${EXP}/human"
|
|||||||
printf "hi\n" >"${EXP}/greeting"
|
printf "hi\n" >"${EXP}/greeting"
|
||||||
printf "bye" >"${EXP}/farewell"
|
printf "bye" >"${EXP}/farewell"
|
||||||
|
|
||||||
ffs -o "$JSON" "$MNT" ../json/object.json &
|
ffs -o "$JSON" -m "$MNT" ../json/object.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
echo hi >"$MNT"/greeting
|
echo hi >"$MNT"/greeting
|
||||||
@ -35,7 +35,7 @@ sleep 1
|
|||||||
kill -0 $PID >/dev/null 2>&1 && fail process
|
kill -0 $PID >/dev/null 2>&1 && fail process
|
||||||
|
|
||||||
# remount w/o --newline, confirm that they're not there (except for greeting)
|
# remount w/o --newline, confirm that they're not there (except for greeting)
|
||||||
ffs "$MNT" "$JSON" &
|
ffs -m "$MNT" "$JSON" &
|
||||||
sleep 2
|
sleep 2
|
||||||
case $(ls "$MNT") in
|
case $(ls "$MNT") in
|
||||||
(eyes*farewell*fingernails*greeting*human*name) ;;
|
(eyes*farewell*fingernails*greeting*human*name) ;;
|
||||||
|
@ -13,7 +13,7 @@ fail() {
|
|||||||
|
|
||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
|
|
||||||
ffs "$MNT" ../json/object.json &
|
ffs -m "$MNT" ../json/object.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -13,7 +13,7 @@ fail() {
|
|||||||
|
|
||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
|
|
||||||
ffs --uid $(id -u root) --gid $(id -g root) "$MNT" ../json/object.json &
|
ffs --uid $(id -u root) --gid $(id -g root) -m "$MNT" ../json/object.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
ls -l "$MNT" | grep root >/dev/null 2>&1 || fail user
|
ls -l "$MNT" | grep root >/dev/null 2>&1 || fail user
|
||||||
|
37
tests/infer_mount.sh
Executable file
37
tests/infer_mount.sh
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
echo FAILED: $1
|
||||||
|
if [ "$MNT" ]
|
||||||
|
then
|
||||||
|
cd
|
||||||
|
umount "$TMP"/object
|
||||||
|
rm -r "$TMP"
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
TMP=$(mktemp -d)
|
||||||
|
|
||||||
|
cp ../json/object.json "$TMP"
|
||||||
|
cd "$TMP"
|
||||||
|
ffs object.json &
|
||||||
|
PID=$!
|
||||||
|
sleep 2
|
||||||
|
[ -d "object" ] || fail mountdir
|
||||||
|
case $(ls object) in
|
||||||
|
(eyes*fingernails*human*name) ;;
|
||||||
|
(*) fail ls;;
|
||||||
|
esac
|
||||||
|
[ "$(cat object/name)" = "Michael Greenberg" ] || fail name
|
||||||
|
[ "$(cat object/eyes)" -eq 2 ] || fail eyes
|
||||||
|
[ "$(cat object/fingernails)" -eq 10 ] || fail fingernails
|
||||||
|
[ "$(cat object/human)" = "true" ] || fail human
|
||||||
|
umount object || fail unmount
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
kill -0 $PID >/dev/null 2>&1 && fail process
|
||||||
|
|
||||||
|
[ -d "object" ] && fail cleanup
|
||||||
|
cd -
|
||||||
|
rm -r "$TMP"
|
@ -15,7 +15,7 @@ fail() {
|
|||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
TGT=$(mktemp)
|
TGT=$(mktemp)
|
||||||
|
|
||||||
ffs --source json --target toml -o "$TGT" "$MNT" ../json/single.json &
|
ffs --source json --target toml -o "$TGT" -m "$MNT" ../json/single.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
umount "$MNT" || fail unmount1
|
umount "$MNT" || fail unmount1
|
||||||
|
@ -15,7 +15,7 @@ MNT=$(mktemp -d)
|
|||||||
|
|
||||||
umask 022
|
umask 022
|
||||||
|
|
||||||
ffs --mode 666 "$MNT" ../json/object.json &
|
ffs --mode 666 -m "$MNT" ../json/object.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
@ -28,7 +28,7 @@ sleep 1
|
|||||||
kill -0 $PID >/dev/null 2>&1 && fail process1
|
kill -0 $PID >/dev/null 2>&1 && fail process1
|
||||||
|
|
||||||
umask 077
|
umask 077
|
||||||
ffs --mode 666 --dirmode 700 "$MNT" ../json/object.json &
|
ffs --mode 666 --dirmode 700 -m "$MNT" ../json/object.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -25,7 +25,7 @@ printf "true" >"${EXP}/human"
|
|||||||
printf "hi" >"${EXP}/greeting"
|
printf "hi" >"${EXP}/greeting"
|
||||||
printf "bye" >"${EXP}/farewell"
|
printf "bye" >"${EXP}/farewell"
|
||||||
|
|
||||||
ffs --newline -o "$JSON" "$MNT" ../json/object.json &
|
ffs --newline -o "$JSON" -m "$MNT" ../json/object.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
echo hi >"$MNT"/greeting
|
echo hi >"$MNT"/greeting
|
||||||
@ -35,7 +35,7 @@ sleep 1
|
|||||||
kill -0 $PID >/dev/null 2>&1 && fail process
|
kill -0 $PID >/dev/null 2>&1 && fail process
|
||||||
|
|
||||||
# remount w/o --newline, confirm that they're not there
|
# remount w/o --newline, confirm that they're not there
|
||||||
ffs "$MNT" "$JSON" &
|
ffs -m "$MNT" "$JSON" &
|
||||||
sleep 2
|
sleep 2
|
||||||
case $(ls "$MNT") in
|
case $(ls "$MNT") in
|
||||||
(eyes*farewell*fingernails*greeting*human*name) ;;
|
(eyes*farewell*fingernails*greeting*human*name) ;;
|
||||||
|
@ -25,7 +25,7 @@ fi
|
|||||||
|
|
||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
|
|
||||||
ffs "$MNT" ../json/nlink.json &
|
ffs -m "$MNT" ../json/nlink.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -17,7 +17,7 @@ MNT=$(mktemp -d)
|
|||||||
TGT=$(mktemp)
|
TGT=$(mktemp)
|
||||||
TGT2=$(mktemp)
|
TGT2=$(mktemp)
|
||||||
|
|
||||||
ffs "$MNT" ../json/object.json >"$TGT" &
|
ffs -m "$MNT" ../json/object.json >"$TGT" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
mkdir "$MNT"/pockets
|
mkdir "$MNT"/pockets
|
||||||
@ -38,7 +38,7 @@ kill -0 $PID >/dev/null 2>&1 && fail process1
|
|||||||
[ -s "$TGT" ] || fail output2
|
[ -s "$TGT" ] || fail output2
|
||||||
cat "$TGT"
|
cat "$TGT"
|
||||||
stat "$TGT"
|
stat "$TGT"
|
||||||
ffs --no-output "$MNT" "$TGT" >"$TGT2" &
|
ffs --no-output -m "$MNT" "$TGT" >"$TGT2" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ TGT=$(mktemp)
|
|||||||
|
|
||||||
cp ../toml/single.toml "$SRC"
|
cp ../toml/single.toml "$SRC"
|
||||||
|
|
||||||
ffs --source toml --target json -o "$TGT" "$MNT" "$SRC" &
|
ffs --source toml --target json -o "$TGT" -m "$MNT" "$SRC" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
umount "$MNT" || fail unmount1
|
umount "$MNT" || fail unmount1
|
||||||
|
@ -13,7 +13,7 @@ fail() {
|
|||||||
|
|
||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
|
|
||||||
ffs "$MNT" ../json/list2.json &
|
ffs -m "$MNT" ../json/list2.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -16,7 +16,7 @@ JSON=$(mktemp)
|
|||||||
|
|
||||||
cp ../json/object.json "$JSON"
|
cp ../json/object.json "$JSON"
|
||||||
|
|
||||||
ffs -qi "$MNT" "$JSON" &
|
ffs -qi -m "$MNT" "$JSON" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
echo hi >"$MNT"/greeting
|
echo hi >"$MNT"/greeting
|
||||||
@ -27,7 +27,7 @@ kill -0 $PID >/dev/null 2>&1 && fail process1
|
|||||||
|
|
||||||
diff ../json/object.json "$JSON" >/dev/null && fail same
|
diff ../json/object.json "$JSON" >/dev/null && fail same
|
||||||
|
|
||||||
ffs --readonly "$MNT" "$JSON" &
|
ffs --readonly -m "$MNT" "$JSON" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
[ "$(cat $MNT/greeting)" = "hi" ] || fail updated
|
[ "$(cat $MNT/greeting)" = "hi" ] || fail updated
|
||||||
|
@ -13,7 +13,7 @@ fail() {
|
|||||||
|
|
||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
|
|
||||||
ffs --readonly "$MNT" ../json/object.json &
|
ffs --readonly -m "$MNT" ../json/object.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -13,7 +13,7 @@ fail() {
|
|||||||
|
|
||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
|
|
||||||
ffs "$MNT" ../json/object.json &
|
ffs -m "$MNT" ../json/object.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -13,7 +13,7 @@ fail() {
|
|||||||
|
|
||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
|
|
||||||
ffs "$MNT" ../json/obj_rename.json &
|
ffs -m "$MNT" ../json/obj_rename.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -13,7 +13,7 @@ fail() {
|
|||||||
|
|
||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
|
|
||||||
ffs "$MNT" ../json/object.json &
|
ffs -m "$MNT" ../json/object.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -20,7 +20,7 @@ TOML="$TOML".toml
|
|||||||
|
|
||||||
cp ../toml/eg.toml "$TOML"
|
cp ../toml/eg.toml "$TOML"
|
||||||
|
|
||||||
ffs -i "$MNT" "$TOML" &
|
ffs -i -m "$MNT" "$TOML" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
case $(ls "$MNT") in
|
case $(ls "$MNT") in
|
||||||
@ -35,7 +35,7 @@ umount "$MNT" || fail unmount1
|
|||||||
sleep 1
|
sleep 1
|
||||||
kill -0 $PID >/dev/null 2>&1 && fail process1
|
kill -0 $PID >/dev/null 2>&1 && fail process1
|
||||||
|
|
||||||
ffs --readonly --no-output "$MNT" "$TOML" &
|
ffs --readonly --no-output -m "$MNT" "$TOML" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
[ "$(cat $MNT/clients/hosts/0)" = "alpha" ] || fail hosts0
|
[ "$(cat $MNT/clients/hosts/0)" = "alpha" ] || fail hosts0
|
||||||
|
@ -15,7 +15,7 @@ fail() {
|
|||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
TGT=$(mktemp)
|
TGT=$(mktemp)
|
||||||
|
|
||||||
ffs --source toml --target json -o "$TGT" "$MNT" ../toml/single.toml &
|
ffs --source toml --target json -o "$TGT" -m "$MNT" ../toml/single.toml &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
umount "$MNT" || fail unmount1
|
umount "$MNT" || fail unmount1
|
||||||
|
@ -15,7 +15,7 @@ fail() {
|
|||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
ERR=$(mktemp)
|
ERR=$(mktemp)
|
||||||
|
|
||||||
ffs --no-output "$MNT" ../json/object.json &
|
ffs --no-output -m "$MNT" ../json/object.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
touch "$MNT"/name 2>$ERR >&2 || { cat "$ERR"; fail touch; }
|
touch "$MNT"/name 2>$ERR >&2 || { cat "$ERR"; fail touch; }
|
||||||
|
@ -19,7 +19,7 @@ TGT=$(mktemp)
|
|||||||
TGT2=$(mktemp)
|
TGT2=$(mktemp)
|
||||||
ERR=$(mktemp)
|
ERR=$(mktemp)
|
||||||
|
|
||||||
ffs "$MNT" ../json/object.json >"$TGT" &
|
ffs -m "$MNT" ../json/object.json >"$TGT" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
echo 'Mikey Indiana' >"$MNT"/name 2>"$ERR"
|
echo 'Mikey Indiana' >"$MNT"/name 2>"$ERR"
|
||||||
@ -32,7 +32,7 @@ kill -0 $PID >/dev/null 2>&1 && fail process1
|
|||||||
[ -f "$TGT" ] || fail output1
|
[ -f "$TGT" ] || fail output1
|
||||||
[ -s "$TGT" ] || fail output2
|
[ -s "$TGT" ] || fail output2
|
||||||
grep -e Indiana "$TGT" >/dev/null 2>&1 || fail grep
|
grep -e Indiana "$TGT" >/dev/null 2>&1 || fail grep
|
||||||
ffs --no-output --source json "$MNT" "$TGT" >"$TGT2" &
|
ffs --no-output --source json -m "$MNT" "$TGT" >"$TGT2" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ fail() {
|
|||||||
|
|
||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
|
|
||||||
ffs "$MNT" ../json/object.json &
|
ffs -m "$MNT" ../json/object.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -13,7 +13,7 @@ fail() {
|
|||||||
|
|
||||||
MNT=$(mktemp -d)
|
MNT=$(mktemp -d)
|
||||||
|
|
||||||
ffs --unpadded "$MNT" ../json/list2.json &
|
ffs --unpadded -m "$MNT" ../json/list2.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -20,7 +20,7 @@ hi
|
|||||||
hello
|
hello
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
ffs "$MNT" ../json/list.json &
|
ffs -m "$MNT" ../json/list.json &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
cd "$MNT"
|
cd "$MNT"
|
||||||
|
@ -20,7 +20,7 @@ YAML="$YAML".yaml
|
|||||||
|
|
||||||
cp ../yaml/invoice.yaml "$YAML"
|
cp ../yaml/invoice.yaml "$YAML"
|
||||||
|
|
||||||
ffs -i "$MNT" "$YAML" &
|
ffs -i -m "$MNT" "$YAML" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
case $(ls "$MNT") in
|
case $(ls "$MNT") in
|
||||||
@ -35,7 +35,7 @@ umount "$MNT" || fail unmount1
|
|||||||
sleep 1
|
sleep 1
|
||||||
kill -0 $PID >/dev/null 2>&1 && fail process1
|
kill -0 $PID >/dev/null 2>&1 && fail process1
|
||||||
|
|
||||||
ffs --readonly --no-output "$MNT" "$YAML" &
|
ffs --readonly --no-output -m "$MNT" "$YAML" &
|
||||||
PID=$!
|
PID=$!
|
||||||
sleep 2
|
sleep 2
|
||||||
[ "$(cat $MNT/product/0/description)" = "Basketball" ] || fail desc1
|
[ "$(cat $MNT/product/0/description)" = "Basketball" ] || fail desc1
|
||||||
|
Loading…
Reference in New Issue
Block a user