#include #include #include #include #include #include #include #include #include #include #include "system.h" #include "utils.h" void __sys_check(int cond, const char *prefix, const char *file, int line) { if (!cond) { fprintf(stderr, "%s:%d: %s: ", file, line, prefix); perror(""); exit(EXIT_FAILURE); } } 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; } char *edit(const char *initial_content) { char tmp_file[32]; int tmp_fd; int rc; char *env_editor; char editor_cmd[512]; char *cmd[] = { "sh", "-c", editor_cmd, NULL }; char *new_content; strcpy(tmp_file, "/tmp/ftag-XXXXXX"); tmp_fd = mkstemp(tmp_file); sys_check(tmp_fd != -1, "mkstemp"); rc = write(tmp_fd, initial_content, strlen(initial_content)); sys_check(rc != -1, "write"); env_editor = getenv("EDITOR"); if (env_editor) strbuild(editor_cmd, "%s %s", env_editor, tmp_file); else strbuild(editor_cmd, "%s %s", "nano", tmp_file); ftag_execvp(cmd, 1); new_content = file_to_string(tmp_fd); close(tmp_fd); return new_content; } char *file_to_string(int fd) { struct stat st; char *content; int rc; rc = lseek(fd, 0L, SEEK_SET); sys_check(rc != -1, "lseek"); rc = fstat(fd, &st); sys_check(rc != -1, "stat"); content = malloc(st.st_size + 1); rc = read(fd, content, st.st_size); sys_check(rc != -1, "read"); content[st.st_size] = '\0'; return content; }