aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTristan Riehs <tristan.riehs@inria.fr>2026-04-26 11:51:56 +0200
committerTristan Riehs <tristan.riehs@inria.fr>2026-04-26 11:53:41 +0200
commitd2fb6a8aac6abe5bfe4b4ea7f2528d119afbc8c6 (patch)
tree611f03f03044f8f1210984d03b1cd28cd52016f2
parent34d935265e65b6b2a5c5dbdaf0c2cbcb97c205e1 (diff)
Create a "system" module
Also unify makefiles, otherwise dependencies are not properly resolved.
-rw-r--r--Makefile21
-rw-r--r--src/Makefile11
-rw-r--r--src/main.c122
-rw-r--r--src/system.c114
-rw-r--r--src/system.h30
5 files changed, 159 insertions, 139 deletions
diff --git a/Makefile b/Makefile
index 0233c47..c20fb08 100644
--- a/Makefile
+++ b/Makefile
@@ -27,16 +27,19 @@ export __LIBS := $(shell pkg-config --libs sqlite3)
all: $(PROG)
-$(PROG):
- make -C src
- mv src/$(PROG) ./
-
+$(PROG): src/main.o src/system.o
+ $(CC) -o $@ $^ $(__LIBS) $(LDFLAGS) $(LIBS)
# Create cache and config directories at compile time since they will be used by
# the user who compiled ftag
# TODO: create this directories from "ftag init"
mkdir -p $(FTAG_CACHE_DIR)
mkdir -p $(FTAG_CONFIG_DIR)
+src/main.o: src/main.c src/system.h
+src/system.o: src/system.c src/system.h
+.c.o:
+ $(CC) $(__CFLAGS) $(CFLAGS) -o $@ -c $<
+
install: $(PROG)
mkdir -p $(PREFIX)/bin
install --mode=0755 $(PROG) $(PREFIX)/bin/
@@ -46,11 +49,13 @@ install: $(PROG)
uninstall:
rm -f $(PREFIX)/bin/$(PROG)
- rm -rf $(PREFIX)/share/ftag
+ rm -rf $(PREFIX)/share/ftag $(FTAG_CACHE_DIR) $(FTAG_CONFIG_DIR)
clean:
- make -C src clean
- rm -rf $(PROG) ftag-$(FTAG_VERSION) ftag-$(FTAG_VERSION)
+ rm -rf $(PROG) $(FTAG_ARCHIVE_DIR) $(FTAG_ARCHIVE) src/*.o
+
+fullclean: clean
+ rm -rf $(FTAG_CACHE_DIR) $(FTAG_CONFIG_DIR)
dist:
mkdir -p $(FTAG_ARCHIVE_DIR) \
@@ -61,4 +66,4 @@ dist:
cp sql/init.sql $(FTAG_ARCHIVE_DIR)/sql/
tar -czf $(FTAG_ARCHIVE) $(FTAG_ARCHIVE_DIR)
-.PHONY: all clean dist install uninstall
+.PHONY: all clean dist fullclean install uninstall
diff --git a/src/Makefile b/src/Makefile
deleted file mode 100644
index 0c8782d..0000000
--- a/src/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-$(PROG): main.o
- $(CC) -o $@ $^ $(__LIBS) $(LDFLAGS) $(LIBS)
-
-main.o: main.c
-.c.o:
- $(CC) $(__CFLAGS) $(CFLAGS) -c $<
-
-clean:
- rm -f main.o $(PROG)
-
-.PHONY: clean
diff --git a/src/main.c b/src/main.c
index 547e96e..2976931 100644
--- a/src/main.c
+++ b/src/main.c
@@ -6,12 +6,12 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/sendfile.h>
#include <sys/stat.h>
-#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
+#include "system.h"
+
#ifndef FTAG_REMOTE_HOST
#define FTAG_REMOTE_HOST "localhost"
#endif
@@ -23,13 +23,6 @@
#define DATABASE_PATH FTAG_CACHE_DIR "/ftag.sqlite3"
-/* Used when encrypting or decrpyting a file, see the copy_encrypted_file
- * function. */
-enum encrypt {
- ENCRYPT,
- DECRYPT,
-};
-
/* TODO: read the configuration from a file
This would allow working with different databases with the same ftag
@@ -69,21 +62,6 @@ 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__)
-/* Return whether PATH exists in the file system. Exit if any non-"file not
- * fount" error occurs. */
-static int file_exists(const char *path)
-{
- struct stat statbuf __attribute__((unused));
- int rc = stat(path, &statbuf);
- if (rc == 0)
- return 1;
- else if ((rc == -1) && (errno == ENOENT))
- return 0;
- fprintf(stderr, "stat: \"%s\": ", path);
- perror("");
- exit(EXIT_FAILURE);
-}
-
static void assert_db_exists(void)
{
if (file_exists(DATABASE_PATH))
@@ -101,102 +79,6 @@ static void assert_db_exists(void)
exit(EXIT_FAILURE);
}
-/* Execute command in a child process, then wait for the child to exit before
- * returning. If any error occurs, including in the child process, then if EXIT
- * is non-zero, exit, else return -1. Return 0 on success. */
-static int ftag_execvp(char *const *cmd, int can_exit)
-{
- int status = 0;
- int rc = fork();
- if (rc == 0) {
- execvp(cmd[0], cmd);
- fprintf(stderr, "exec: %s: ", cmd[0]);
- perror("");
- }
- else if (rc > 0) {
- int status;
- wait(&status);
- if (!(WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
- fprintf(stderr,
- "ftag: child process exited abnormally\n");
- if (can_exit)
- exit(EXIT_FAILURE);
- else
- status = -1;
- }
- }
- else {
- perror("fork");
- if (can_exit)
- exit(EXIT_FAILURE);
- else
- status = -1;
- }
- return status;
-}
-
-/* Copy the file whose path is IN at path OUT. OUT is created or overwritten if
- * needed. */
-static void copy_file(const char *in, const char *out)
-{
- int in_fd;
- int out_fd;
- int rc;
- ssize_t written_bytes;
- in_fd = open(in, O_RDONLY);
- if (in_fd == -1) {
- fprintf(stderr, "open: %s:", in);
- perror("");
- exit(EXIT_FAILURE);
- }
- out_fd = open(out, O_WRONLY | O_CREAT | O_TRUNC, 0600);
- if (out_fd == -1) {
- fprintf(stderr, "open: %s:", out);
- perror("");
- exit(EXIT_FAILURE);
- }
- while ((written_bytes = sendfile(out_fd, in_fd, NULL, 4096)) == 4096)
- ;
- if (written_bytes == -1) {
- perror("sendfile");
- exit(EXIT_FAILURE);
- }
- rc = fchmod(out_fd, 0400);
- if (rc == -1) {
- fprintf(stderr, "chmod: %s: ", out);
- perror("");
- exit(EXIT_FAILURE);
- }
- close(in_fd);
- close(out_fd);
-}
-
-/* Like copy_file, but OUT is an encrypted version of IN. Encryption is done
- * using GPG. */
-static void
-copy_file_with_encryption(const char *in, const char *out, enum encrypt encrypt)
-{
- char *crypt_param;
- assert(encrypt == ENCRYPT || encrypt == DECRYPT);
- if (encrypt == ENCRYPT)
- crypt_param = "--encrypt";
- else
- crypt_param = "--decrypt";
- /* use dups to suppress "discards const qualifier" warnings */
- char *in_dup = strdup(in);
- char *out_dup = strdup(out);
- char *cmd[] = {
- "gpg",
- "--output", out_dup,
- "--yes",
- crypt_param, in_dup,
- NULL
- };
- ftag_execvp(cmd, 1);
- free(in_dup);
- free(out_dup);
-}
-
/* Prompt the user for yes or no (default is yes). Before calling, a prompt
* should be printed to stdout, eventually not with an ending newline. */
static int prompt_yes_no(void)
diff --git a/src/system.c b/src/system.c
new file mode 100644
index 0000000..df53e99
--- /dev/null
+++ b/src/system.c
@@ -0,0 +1,114 @@
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/sendfile.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "system.h"
+
+int file_exists(const char *path)
+{
+ struct stat statbuf __attribute__((unused));
+ int rc = stat(path, &statbuf);
+ if (rc == 0)
+ return 1;
+ else if ((rc == -1) && (errno == ENOENT))
+ return 0;
+ fprintf(stderr, "stat: \"%s\": ", path);
+ perror("");
+ exit(EXIT_FAILURE);
+}
+
+void copy_file(const char *in, const char *out)
+{
+ int in_fd;
+ int out_fd;
+ int rc;
+ ssize_t written_bytes;
+ in_fd = open(in, O_RDONLY);
+ if (in_fd == -1) {
+ fprintf(stderr, "open: %s:", in);
+ perror("");
+ exit(EXIT_FAILURE);
+ }
+ out_fd = open(out, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ if (out_fd == -1) {
+ fprintf(stderr, "open: %s:", out);
+ perror("");
+ exit(EXIT_FAILURE);
+ }
+ while ((written_bytes = sendfile(out_fd, in_fd, NULL, 4096)) == 4096)
+ ;
+ if (written_bytes == -1) {
+ perror("sendfile");
+ exit(EXIT_FAILURE);
+ }
+ rc = fchmod(out_fd, 0400);
+ if (rc == -1) {
+ fprintf(stderr, "chmod: %s: ", out);
+ perror("");
+ exit(EXIT_FAILURE);
+ }
+ close(in_fd);
+ close(out_fd);
+}
+
+void
+copy_file_with_encryption(const char *in, const char *out, enum encrypt encrypt)
+{
+ char *crypt_param;
+ assert(encrypt == ENCRYPT || encrypt == DECRYPT);
+ if (encrypt == ENCRYPT)
+ crypt_param = "--encrypt";
+ else
+ crypt_param = "--decrypt";
+ /* use dups to suppress "discards const qualifier" warnings */
+ char *in_dup = strdup(in);
+ char *out_dup = strdup(out);
+ char *cmd[] = {
+ "gpg",
+ "--output", out_dup,
+ "--yes",
+ crypt_param, in_dup,
+ NULL
+ };
+ ftag_execvp(cmd, 1);
+ free(in_dup);
+ free(out_dup);
+}
+
+int ftag_execvp(char *const *cmd, int can_exit)
+{
+ int status = 0;
+ int rc = fork();
+ if (rc == 0) {
+ execvp(cmd[0], cmd);
+ fprintf(stderr, "exec: %s: ", cmd[0]);
+ perror("");
+ }
+ else if (rc > 0) {
+ int status;
+ wait(&status);
+ if (!(WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
+ fprintf(stderr,
+ "ftag: child process exited abnormally\n");
+ if (can_exit)
+ exit(EXIT_FAILURE);
+ else
+ status = -1;
+ }
+ }
+ else {
+ perror("fork");
+ if (can_exit)
+ exit(EXIT_FAILURE);
+ else
+ status = -1;
+ }
+ return status;
+}
diff --git a/src/system.h b/src/system.h
new file mode 100644
index 0000000..950a82a
--- /dev/null
+++ b/src/system.h
@@ -0,0 +1,30 @@
+#ifndef SYSTEM_H
+#define SYSTEM_H
+
+/* Routines for interacting with the system, mainly executing processes and
+ * dealing with the file system. */
+
+/* Used when encrypting or decrypting a file, see the copy_file_with_encryption
+ * function. */
+enum encrypt {
+ ENCRYPT,
+ DECRYPT
+};
+
+/* Return whether PATH exists in the file system. Exit if any non-"file not
+ * fount" error occurs. */
+int file_exists(const char *path);
+
+/* Copy the file whose path is IN at path OUT. OUT is created or overwritten if
+ * needed. */
+void copy_file(const char *in, const char *out);
+
+/* Like copy_file but with encryption, which is managed using GPG. */
+void copy_file_with_encryption(const char *in, const char *out, enum encrypt encrypt);
+
+/* Execute command in a child process, then wait for the child to exit before
+ * returning. If any error occurs, including in the child process, then if EXIT
+ * is non-zero, exit, else return -1. Return 0 on success. */
+int ftag_execvp(char *const *cmd, int can_exit);
+
+#endif