aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config.h11
-rw-r--r--src/main.c135
-rw-r--r--src/utils.c7
3 files changed, 90 insertions, 63 deletions
diff --git a/src/config.h b/src/config.h
index 50cba3a..4814f7f 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,17 +1,6 @@
#ifndef CONFIG_H
#define CONFIG_H
-#ifndef FTAG_REMOTE_HOST
-#define FTAG_REMOTE_HOST "localhost"
-#endif
-
-#ifndef FTAG_REMOTE_ROOT
-/* HOME on remote host */
-#define FTAG_REMOTE_ROOT "ftag"
-#endif
-
-#define DATABASE_PATH FTAG_CACHE_DIR "/ftag.sqlite3"
-
/* Note "FC" stands for "Ftag Config". */
enum ftag_config_e {
FC_DATABASE_PATH,
diff --git a/src/main.c b/src/main.c
index 58d30ca..243b385 100644
--- a/src/main.c
+++ b/src/main.c
@@ -40,7 +40,8 @@ static void parse_args(int argc,
const struct ftag_command *commands,
int command_count);
-static void __sqlite3_check(int rc, sqlite3 *db, const char *file, int line, const char *func)
+static void __sqlite3_check(int rc, sqlite3 *db,
+ const char *file, int line, const char *func)
{
/* Note: "rc" stands for "return code" */
if (rc == SQLITE_OK)
@@ -54,6 +55,15 @@ static void __sqlite3_check(int rc, sqlite3 *db, const char *file, int line, con
#define sqlite3_check(RC, DB) \
__sqlite3_check(RC, DB, __FILE__, __LINE__, __func__)
+static sqlite3 *ftag_db_open(void)
+{
+ const char *db_path = ftag_config_get(FC_DATABASE_PATH);
+ sqlite3 *db;
+ int rc = sqlite3_open(db_path, &db);
+ sqlite3_check(rc, db);
+ return db;
+}
+
/* Convert heap-allocated *STR from C string to SQL string, essentially by
* adding single quotes to escape single quotes. */
static void sanitize_sql_str(char **str)
@@ -159,8 +169,7 @@ static void ftag_file_get_extension(char *out, int size, const char *file)
strbuild(sql,
"SELECT extension FROM files WHERE canonical_name = '%s';",
file);
- rc = sqlite3_open(DATABASE_PATH, &db);
- sqlite3_check(rc, db);
+ db = ftag_db_open();
rc = sqlite3_exec(db, sql, ftag_file_get_extension_callback, &ext, NULL);
sqlite3_check(rc, db);
sqlite3_close(db);
@@ -170,7 +179,8 @@ static void ftag_file_get_extension(char *out, int size, const char *file)
static void ftag_file_get_path(char *out, int size, const char *file)
{
/* look for the encrypted version first */
- strbuild_with_size(out, size, "%s/files/%s.gpg", FTAG_CACHE_DIR, file);
+ strbuild_with_size(out, size, "%s/files/%s.gpg",
+ ftag_config_get(FC_CACHE_DIR), file);
if (file_exists(out))
return;
/* look for the clear version after */
@@ -267,21 +277,24 @@ static void ftag_export(int argc, char **argv)
/* Create ftag's database and directories. */
static void ftag_init(int, char **)
{
- int rc = mkdir(FTAG_CACHE_DIR, 0755);
+ const char *cache_dir = ftag_config_get(FC_CACHE_DIR);
+ int rc = mkdir(cache_dir, 0755);
if (rc == -1 && errno != EEXIST) {
- fprintf(stderr, "mkdir: %s: ", FTAG_CACHE_DIR);
+ fprintf(stderr, "mkdir: %s: ", cache_dir);
perror("");
exit(EXIT_FAILURE);
}
- rc = mkdir(FTAG_CACHE_DIR "/files", 0755);
+ char files_dir[512];
+ strbuild(files_dir, "%s/files", cache_dir);
+ rc = mkdir(files_dir, 0755);
if (rc == -1 && errno != EEXIST) {
- fprintf(stderr, "mkdir: %s/files: ", FTAG_CACHE_DIR);
+ fprintf(stderr, "mkdir: %s: ", files_dir);
perror("");
exit(EXIT_FAILURE);
}
char cmd_sqlite[1024];
strbuild(cmd_sqlite, "sqlite3 %s < %s",
- DATABASE_PATH, FTAG_PREFIX "/share/ftag/sql/init.sql");
+ ftag_config_get(FC_DATABASE_PATH), FTAG_PREFIX "/share/ftag/sql/init.sql");
char *cmd[] = {
"sh",
"-c",
@@ -307,8 +320,7 @@ static void ftag_list_table(const char *table, const char *col)
char sql[64];
sqlite3 *db = NULL;
int rc;
- rc = sqlite3_open(DATABASE_PATH, &db);
- sqlite3_check(rc, db);
+ db = ftag_db_open();
strbuild(sql, "SELECT %s FROM %s;", col, table);
rc = sqlite3_exec(db, sql, ftag_print, NULL, NULL);
sqlite3_check(rc, db);
@@ -343,6 +355,7 @@ ftag_add_one_file(sqlite3 *db, int *next_id, const char *file, uint32_t file_sum
time_t date = time(NULL);
size_t line_len = 0;
ssize_t read_len;
+ const char *cache_dir = ftag_config_get(FC_CACHE_DIR);
/* TODO: possibly be non-interactive
Maybe take canonical_name, full_name, and description as
@@ -436,11 +449,11 @@ ftag_add_one_file(sqlite3 *db, int *next_id, const char *file, uint32_t file_sum
char new_path[512];
if (encrypt) {
- strbuild(new_path, "%s/files/%s.gpg", FTAG_CACHE_DIR, canonical_name);
+ strbuild(new_path, "%s/files/%s.gpg", cache_dir, canonical_name);
copy_file_with_encryption(file, new_path, ENCRYPT);
}
else {
- strbuild(new_path, "%s/files/%s", FTAG_CACHE_DIR, canonical_name);
+ strbuild(new_path, "%s/files/%s", cache_dir, canonical_name);
copy_file(file, new_path);
}
@@ -549,8 +562,7 @@ static void ftag_file_add(int argc, char **argv)
/* step 2: retrieve sums of files already in the database */
sqlite3 *db;
- rc = sqlite3_open(DATABASE_PATH, &db);
- sqlite3_check(rc, db);
+ db = ftag_db_open();
int next_id = table_next_id(db, "files");
int file_count = next_id; /* number of files already in the database */
uint32_t known_sums_array[file_count];
@@ -658,8 +670,8 @@ static void ftag_file_tag(int argc, char **argv)
const char *file = argv[0];
char sql[64];
sqlite3 *db;
- int rc = sqlite3_open(DATABASE_PATH, &db);
- sqlite3_check(rc, db);
+ int rc;
+ db = ftag_db_open();
int file_id = get_id_by_col(db, "files", "canonical_name", file);
printf("%s: debug: file id is %d\n", __func__, file_id);
for (int i = 1; i < argc; i++) {
@@ -688,7 +700,10 @@ static void ftag_file(int argc, char **argv)
static void ftag_help(int, char **)
{
- puts("Usage: ftag COMMAND [ARG]...");
+ puts("Usage: ftag [OPTION]... COMMAND [ARG]...");
+ puts("Available values for OPTION:");
+ puts(" -c FILE use FILE as configuration file");
+ puts(" -h display this help");
puts("Available values for COMMAND:");
puts(" init initialize the database");
puts(" file manage files");
@@ -698,11 +713,6 @@ static void ftag_help(int, char **)
puts(" tag manage tags");
puts("Some commands also have their own help,");
puts("try \"ftag COMMAND help\" or \"ftag COMMAND -h\".");
- puts("Configuration:");
- printf(" cache %s\n", FTAG_CACHE_DIR);
- printf(" config %s\n", FTAG_CONFIG_DIR);
- printf(" prefix %s\n", FTAG_PREFIX);
- printf(" version %s\n", FTAG_VERSION);
}
static void ftag_query_usage(void)
@@ -815,8 +825,7 @@ static void ftag_query(int argc, char **argv)
char sql[4096];
sqlite3 *db;
int rc;
- rc = sqlite3_open(DATABASE_PATH, &db);
- sqlite3_check(rc, db);
+ db = ftag_db_open();
char sql_join[2048];
memset(sql_join, 0, sizeof(sql_join));
ftag_query_join(db, sql_join, sizeof(sql_join)-1,
@@ -833,13 +842,16 @@ static void ftag_query(int argc, char **argv)
static time_t get_remote_mtime(void)
{
- char *remote_path = FTAG_REMOTE_ROOT "/ftag.sqlite3";
+ const char *remote_host = ftag_config_get(FC_REMOTE_HOST);
+ char remote_path[512];
+ strbuild(remote_path, "%s/ftag.sqlite3",
+ ftag_config_get(FC_REMOTE_ROOT));
char cmd[1024];
strbuild(cmd, "ssh %s 'test -f %s && stat --format=%%Y %s || echo 0'",
- FTAG_REMOTE_HOST, remote_path, remote_path);
+ remote_host, remote_path, remote_path);
FILE *pipe = popen(cmd, "r");
if (!pipe) {
- fprintf(stderr, "popen: ssh %s: ", FTAG_REMOTE_HOST);
+ fprintf(stderr, "popen: ssh %s: ", remote_host);
perror("");
exit(EXIT_FAILURE);
}
@@ -852,7 +864,7 @@ static time_t get_remote_mtime(void)
}
int rc = pclose(pipe);
if (rc == 1) {
- fprintf(stderr, "pclose: ssh %s: ", FTAG_REMOTE_HOST);
+ fprintf(stderr, "pclose: ssh %s: ", remote_host);
perror("");
exit(EXIT_FAILURE);
}
@@ -863,10 +875,11 @@ static time_t get_remote_mtime(void)
static time_t get_local_mtime(void)
{
+ const char *db_path = ftag_config_get(FC_DATABASE_PATH);
struct stat st;
- int rc = stat(DATABASE_PATH, &st);
+ int rc = stat(db_path, &st);
if (rc == -1) {
- fprintf(stderr, "stat: %s: ", DATABASE_PATH);
+ fprintf(stderr, "stat: %s: ", db_path);
perror("");
exit(EXIT_FAILURE);
}
@@ -901,21 +914,27 @@ static void ftag_sync_help(int, char **)
* non-zero, perform a push, else perform a pull. */
static void ftag_sync_run_rsync(int push)
{
- char remote_root[128];
- strbuild(remote_root, "%s:%s/",
- FTAG_REMOTE_HOST, FTAG_REMOTE_ROOT);
- char *first = remote_root;
- char *second = FTAG_CACHE_DIR "/";
+ const char *cache_dir = ftag_config_get(FC_CACHE_DIR);
+ const char *remote_host = ftag_config_get(FC_REMOTE_HOST);
+ const char *remote_root = ftag_config_get(FC_REMOTE_ROOT);
+
+ char remote_path[128];
+ strbuild(remote_path, "%s:%s/", remote_host, remote_root);
+ char local_path[128];
+ strbuild(local_path, "%s/", cache_dir);
+
+ char *src = remote_path;
+ char *dst = local_path;
if (push) {
- first = FTAG_CACHE_DIR "/";
- second = remote_root;
+ src = dst;
+ dst = src;
}
char *cmd[] = {
"rsync",
"--verbose", /* temporary */
"--archive",
- first,
- second,
+ src,
+ dst,
NULL
};
ftag_execvp(cmd, 1);
@@ -977,8 +996,7 @@ static void ftag_tag_add(int argc, char **argv)
sqlite3 *db;
int rc;
- rc = sqlite3_open(DATABASE_PATH, &db);
- sqlite3_check(rc, db);
+ db = ftag_db_open();
strbuild(sql, "SELECT name, description FROM tags WHERE name = '%s';",
new_tag_name);
@@ -1050,17 +1068,10 @@ static void parse_args(int argc,
int main(int argc, char *argv[])
{
- if (argc == 1) {
- ftag_help(0, NULL);
- exit(EXIT_FAILURE);
- }
-
const struct ftag_command toplevel_commands[] = {
{.name = "export", .func = ftag_export},
{.name = "init", .func = ftag_init},
{.name = "file", .func = ftag_file},
- {.name = "-h", .func = ftag_help},
- {.name = "--help", .func = ftag_help},
{.name = "help", .func = ftag_help},
{.name = "query", .func = ftag_query},
{.name = "sync", .func = ftag_sync},
@@ -1074,6 +1085,32 @@ int main(int argc, char *argv[])
able to only transfer the new files, maybe using rsync. */
};
const int toplevel_command_count = sizeof(toplevel_commands) / sizeof(struct ftag_command);
+ const char* config_file = NULL;
+ const char *optstring = "c:h";
+ int opt;
+
+ while ((opt = getopt(argc, argv, optstring)) != -1) {
+ switch (opt) {
+ case 'h':
+ ftag_help(0, NULL);
+ exit(EXIT_SUCCESS);
+ case 'c':
+ config_file = optarg;
+ break;
+ case'?':
+ default:
+ ftag_help(0, NULL);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (optind == argc) {
+ ftag_help(0, NULL);
+ exit(EXIT_FAILURE);
+ }
+
+#error "Resume here, read the config file before doing anything"
+
parse_args(argc-1, argv+1, toplevel_commands, toplevel_command_count);
return EXIT_SUCCESS;
}
diff --git a/src/utils.c b/src/utils.c
index a1fc5b9..9ad9190 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -50,17 +50,18 @@ int str_has_suffix(const char *str, const char *suffix)
void assert_db_exists(void)
{
- if (file_exists(DATABASE_PATH))
+ const char *db_path = ftag_config_get(FC_DATABASE_PATH);
+ if (file_exists(db_path))
return;
if (errno == ENOENT) {
fprintf(stderr,
"ftag: database not found at \"%s\", "
"have you run \"ftag init\"?\n",
- DATABASE_PATH);
+ db_path);
}
else {
- perror(DATABASE_PATH);
+ perror(db_path);
}
exit(EXIT_FAILURE);
}