initial commit
This commit is contained in:
174
main.cc
Normal file
174
main.cc
Normal file
@@ -0,0 +1,174 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* (c) 2025, Konstantin Demin
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
extern "C" {
|
||||
#include <unistd.h>
|
||||
}
|
||||
|
||||
#include "overlay.hh"
|
||||
|
||||
static
|
||||
void usage(int retcode = 0)
|
||||
{
|
||||
static const char usage_msg[] =
|
||||
"overlaydirs 0.0.1\n"
|
||||
"Usage:\n"
|
||||
" overlaydirs --help\n"
|
||||
" show this message\n"
|
||||
" overlaydirs --list [--no-sort|--zero] <source directory> [..<source directory>]\n"
|
||||
// TODO: shell-escape mode
|
||||
/* " overlaydirs --list [--no-sort|--zero|--escape] <source directory> [..<source directory>]\n" */
|
||||
" list entries\n"
|
||||
" overlaydirs --merge <target directory> <source directory> [..<source directory>]\n"
|
||||
" symlinks entries into <target directory>\n"
|
||||
"\n"
|
||||
" --no-sort - don't sort entries\n"
|
||||
" --zero - separate entries with NUL instead of LF\n"
|
||||
// TODO: shell-escape mode
|
||||
/*
|
||||
" --escape - shell-escape strings\n"
|
||||
"\n"
|
||||
"Notes:\n"
|
||||
" - flags \"--zero\" and \"--escape\" are mutually exclusive.\n"
|
||||
*/
|
||||
;
|
||||
|
||||
(void) write(STDERR_FILENO, usage_msg, sizeof(usage_msg));
|
||||
|
||||
exit(retcode);
|
||||
}
|
||||
|
||||
static int main_list(int argc, char * argv[]);
|
||||
static int main_merge(int argc, char * argv[]);
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
if (argc < 2) usage(0);
|
||||
|
||||
if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0))
|
||||
usage(0);
|
||||
else if (strcmp(argv[1], "--list") == 0)
|
||||
return main_list(argc, argv);
|
||||
else if (strcmp(argv[1], "--merge") == 0)
|
||||
return main_merge(argc, argv);
|
||||
else
|
||||
usage(EINVAL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int main_list(int argc, char * argv[])
|
||||
{
|
||||
if (argc < 3) usage(EINVAL);
|
||||
|
||||
print_mode print_m = print_mode::_default;
|
||||
sort_mode sort_m = sort_mode::_default;
|
||||
|
||||
int arg_start = 2;
|
||||
while (arg_start < argc) {
|
||||
char * _arg = argv[arg_start];
|
||||
|
||||
if (strncmp(_arg, "--", 2) != 0) break;
|
||||
|
||||
if (strcmp(_arg, "--") == 0) {
|
||||
arg_start++;
|
||||
break;
|
||||
}
|
||||
else if (strcmp(_arg, "--no-sort") == 0) {
|
||||
arg_start++;
|
||||
if (sort_m != sort_mode::_default) {
|
||||
(void) fprintf(stderr, "overlaydirs: no-sort mode already set\n");
|
||||
}
|
||||
sort_m = sort_mode::none;
|
||||
}
|
||||
else if (strcmp(_arg, "--zero") == 0) {
|
||||
arg_start++;
|
||||
if (print_m != print_mode::_default) {
|
||||
(void) fprintf(stderr, "overlaydirs: output mode already set\n");
|
||||
}
|
||||
print_m = print_mode::zero;
|
||||
}
|
||||
// TODO
|
||||
/*
|
||||
else if (strcmp(_arg, "--escape") == 0) {
|
||||
arg_start++;
|
||||
if (print_m != print_mode::_default) {
|
||||
(void) fprintf(stderr, "overlaydirs: output mode already set\n");
|
||||
}
|
||||
print_m = print_mode::shell_escape;
|
||||
}
|
||||
*/
|
||||
else {
|
||||
(void) fprintf(stderr, "overlaydirs: unknown option \"%s\"\n", _arg);
|
||||
// nevertheless, continue and try argument as a directory
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto roots = std::vector<ovl_dirspec_t>();
|
||||
for (int i = arg_start; i < argc; i++) {
|
||||
ovl_dirspec_t t;
|
||||
if (!arg_to_rootspec(argv[i], &t, ovl_rootspec_flags::relative)) continue;
|
||||
roots.push_back(t);
|
||||
}
|
||||
if (roots.empty()) {
|
||||
(void) fprintf(stderr, "overlaydirs: no usable sources found\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
auto ovl = process_overlay(roots, sort_m);
|
||||
// not needed anymore
|
||||
roots.clear();
|
||||
roots.shrink_to_fit();
|
||||
|
||||
list_overlay(ovl, print_m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int main_merge(int argc, char * argv[])
|
||||
{
|
||||
if (argc < 4) usage(EINVAL);
|
||||
|
||||
ovl_dirspec_t target;
|
||||
if (!arg_to_rootspec(argv[2], &target, ovl_rootspec_flags::relative)) {
|
||||
(void) fprintf(stderr, "overlaydirs: not a directory: \"%s\"\n", argv[2]);
|
||||
return EINVAL;
|
||||
}
|
||||
if (!is_empty_dir(target.fd)) {
|
||||
(void) fprintf(stderr, "overlaydirs: target directory is not empty\n");
|
||||
return EEXIST;
|
||||
}
|
||||
|
||||
auto roots = std::vector<ovl_dirspec_t>();
|
||||
for (int i = 3; i < argc; i++) {
|
||||
ovl_dirspec_t t;
|
||||
if (!arg_to_rootspec(argv[i], &t)) continue;
|
||||
roots.push_back(t);
|
||||
}
|
||||
if (roots.empty()) {
|
||||
(void) fprintf(stderr, "overlaydirs: no usable sources found\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
auto ovl = process_overlay(roots);
|
||||
// not needed anymore
|
||||
roots.clear();
|
||||
roots.shrink_to_fit();
|
||||
|
||||
int rv = merge_overlay(ovl, target);
|
||||
if (rv == -1) {
|
||||
(void) fprintf(stderr, "overlaydirs: target directory is not empty\n");
|
||||
return EEXIST;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
Reference in New Issue
Block a user