diff --git a/README.md b/README.md index 2f1b80e5..9643d5e8 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ compare against the true GNU coreutils version on the Linux-based tests first. | ✓ | ls | List directory contents | | ✓ | md5sum | Print or check MD5 digests | | ✓ | mkdir | Make directories | -| | mkfifo | Make FIFOs (named pipes) | +| ✓ | mkfifo | Make FIFOs (named pipes) | | | mknod | Make block or character special files | | ✓ | mktemp | Create temporary file or directory | | ✓ | mv | Move (rename) files | diff --git a/src/mkfifo/delete.me b/src/mkfifo/delete.me deleted file mode 100644 index e69de29b..00000000 diff --git a/src/mkfifo/mkfifo.v b/src/mkfifo/mkfifo.v new file mode 100644 index 00000000..9b305311 --- /dev/null +++ b/src/mkfifo/mkfifo.v @@ -0,0 +1,53 @@ +import os +import common + +const name = 'mkfifo' +const default_mode = u32(0o600) + +struct Options { + mode u32 +} + +fn mkfifo_cmd(list []string, opts &Options) { + for path in list { + ret := mkfifo(path, opts.mode) + if ret != 0 { + common.exit_with_error_message(name, os.posix_get_error_msg(ret)) + } + } +} + +fn run_mkfifo(args []string) { + mut fp := common.flag_parser(args) + fp.application(name) + fp.usage_example('[OPTION]... NAME...') + fp.description('Create named pipes (FIFOs) with the given NAMEs.') + fp.description('Mandatory arguments to long options are mandatory for short options too.') + + mut opts := Options{ + mode: u32(fp.int('mode', `m`, int(default_mode), 'set file permission bits to MODE, not a=rw - umask')) + } + + help := fp.bool('help', 0, false, 'display this help and exit') + version := fp.bool('version', 0, false, 'output version information and exit') + if help { + println(fp.usage()) + exit(0) + } + if version { + println('${name} ${common.coreutils_version()}') + exit(0) + } + + file_args := fp.finalize() or { common.exit_with_error_message(name, err.msg()) } + if file_args.len == 0 { + common.exit_with_error_message(name, 'missing operand') + } + + mkfifo_cmd(file_args, &opts) +} + +fn main() { + run_mkfifo(os.args) + exit(0) +} diff --git a/src/mkfifo/mkfifo_default.c.v b/src/mkfifo/mkfifo_default.c.v new file mode 100644 index 00000000..18d114c4 --- /dev/null +++ b/src/mkfifo/mkfifo_default.c.v @@ -0,0 +1,4 @@ +// mkfifo on unsupported platforms +fn mkfifo(pathname string, mode int) int { + return -1 +} diff --git a/src/mkfifo/mkfifo_nix.c.v b/src/mkfifo/mkfifo_nix.c.v new file mode 100644 index 00000000..ca95b5d7 --- /dev/null +++ b/src/mkfifo/mkfifo_nix.c.v @@ -0,0 +1,5 @@ +fn C.mkfifo(&char, int) int + +fn mkfifo(pathname string, mode u32) int { + return C.mkfifo(pathname.str, mode) +} diff --git a/src/mkfifo/mkfifo_nix_test.v b/src/mkfifo/mkfifo_nix_test.v new file mode 100644 index 00000000..c0b3be97 --- /dev/null +++ b/src/mkfifo/mkfifo_nix_test.v @@ -0,0 +1,55 @@ +import os +import common.testing + +const rig = testing.prepare_rig(util: util) +const tfolder = os.join_path(os.temp_dir(), 'coreutils', 'mkfifo_test') + +const util = 'mkfifo' +const platform_util = util + +const executable_under_test = testing.prepare_executable(util) +const cmd = testing.new_paired_command(platform_util, executable_under_test) + +fn test_help_and_version() { + rig.assert_help_and_version_options_work() +} + +fn testsuite_begin() { + rig.assert_platform_util() + os.chdir(testing.temp_folder)! + eprintln('testsuite_begin, tfolder = ${tfolder}') + os.rmdir_all(tfolder) or {} + assert !os.is_dir(tfolder) + os.mkdir_all(tfolder) or { panic(err) } + os.chdir(tfolder) or {} + assert os.is_dir(tfolder) +} + +fn testsuite_end() { + os.chdir(os.wd_at_startup) or {} + os.rmdir_all(tfolder) or {} + assert !os.is_dir(tfolder) + eprintln('testsuite_end , tfolder = ${tfolder} removed.') +} + +fn test_default_create_single_pipe() { + target := 'test_piped' + res := os.execute('${executable_under_test} ${target}') + assert res.exit_code == 0 + assert res.output.trim_space() == '' + assert os.is_file(target) + st := os.stat(target)! + assert st.get_filetype() == os.FileType.fifo +} + +fn test_default_create_multiple_pipes() { + target := 'tp1 tp2 tp3' + res := os.execute('${executable_under_test} ${target}') + assert res.exit_code == 0 + assert res.output.trim_space() == '' + for p in target.split(' ') { + assert os.is_file(p) + st := os.stat(p)! + assert st.get_filetype() == os.FileType.fifo + } +}