diff options
Diffstat (limited to 'src/system.c')
| -rw-r--r-- | src/system.c | 114 |
1 files changed, 114 insertions, 0 deletions
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; +} |
