aboutsummaryrefslogtreecommitdiffstats
path: root/src/blogc-make/exec-native.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/blogc-make/exec-native.c')
-rw-r--r--src/blogc-make/exec-native.c161
1 files changed, 161 insertions, 0 deletions
diff --git a/src/blogc-make/exec-native.c b/src/blogc-make/exec-native.c
new file mode 100644
index 0000000..32874b4
--- /dev/null
+++ b/src/blogc-make/exec-native.c
@@ -0,0 +1,161 @@
+/*
+ * blogc: A blog compiler.
+ * Copyright (C) 2016 Rafael G. Martins <rafael@rafaelmartins.eng.br>
+ *
+ * This program can be distributed under the terms of the BSD License.
+ * See the file LICENSE.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <libgen.h>
+#include <errno.h>
+#include "../common/file.h"
+#include "../common/utils.h"
+#include "exec-native.h"
+#include "ctx.h"
+
+
+int
+bm_exec_native_cp(bm_filectx_t *source, bm_filectx_t *dest, bool verbose)
+{
+ if (verbose)
+ printf("Copying '%s' to '%s'\n", source->path, dest->path);
+ else
+ printf(" COPY %s\n", dest->short_path);
+ fflush(stdout);
+
+ char *fname = bc_strdup(dest->path);
+ for (char *tmp = fname; *tmp != '\0'; tmp++) {
+ if (*tmp != '/' && *tmp != '\\')
+ continue;
+ char bkp = *tmp;
+ *tmp = '\0';
+ if ((strlen(fname) > 0) &&
+ (-1 == mkdir(fname, 0777)) &&
+ (errno != EEXIST))
+ {
+ fprintf(stderr, "blogc-make: error: failed to create output "
+ "directory (%s): %s\n", fname, strerror(errno));
+ free(fname);
+ exit(2);
+ }
+ *tmp = bkp;
+ }
+ free(fname);
+
+ int fd_from = open(source->path, O_RDONLY);
+ if (fd_from < 0) {
+ fprintf(stderr, "blogc-make: error: failed to open source file to copy "
+ " (%s): %s\n", source->path, strerror(errno));
+ return 3;
+ }
+
+ int fd_to = open(dest->path, O_WRONLY | O_CREAT, 0666);
+ if (fd_to < 0) {
+ fprintf(stderr, "blogc-make: error: failed to open destination file to "
+ "copy (%s): %s\n", dest->path, strerror(errno));
+ close(fd_from);
+ return 3;
+ }
+
+ ssize_t nread;
+ char buffer[BC_FILE_CHUNK_SIZE];
+ while (0 < (nread = read(fd_from, buffer, BC_FILE_CHUNK_SIZE))) {
+ char *out_ptr = buffer;
+ do {
+ ssize_t nwritten = write(fd_to, out_ptr, nread);
+ if (nwritten == -1) {
+ fprintf(stderr, "blogc-make: error: failed to write to "
+ "destination file (%s): %s\n", dest->path, strerror(errno));
+ close(fd_from);
+ close(fd_to);
+ return 3;
+ }
+ nread -= nwritten;
+ out_ptr += nwritten;
+ } while (nread > 0);
+ }
+
+ return 0;
+}
+
+
+int
+bm_exec_native_rm(bm_filectx_t *dest, bool verbose)
+{
+ if (verbose)
+ printf("Removing file '%s'\n", dest->path);
+ else
+ printf(" CLEAN %s\n", dest->short_path);
+ fflush(stdout);
+
+ if (0 != unlink(dest->path)) {
+ fprintf(stderr, "blogc-make: error: failed to remove file (%s): %s\n",
+ dest->path, strerror(errno));
+ return 3;
+ }
+
+ int rv = 0;
+
+ char *short_path = bc_strdup(dest->short_path);
+ char *path = bc_strdup(dest->path);
+
+ char *dir_short = dirname(short_path);
+ char *dir = dirname(path);
+
+ while (0 != strcmp(dir_short, ".")) {
+
+ DIR *d = opendir(dir);
+ if (d == NULL) {
+ fprintf(stderr, "error: failed to open directory (%s): %s\n",
+ dir, strerror(errno));
+ rv = 3;
+ break;
+ }
+
+ struct dirent *e;
+ size_t count = 0;
+ while (NULL != (e = readdir(d))) {
+ if ((0 == strcmp(e->d_name, ".")) || (0 == strcmp(e->d_name, "..")))
+ continue;
+ count++;
+ break;
+ }
+
+ if (0 != closedir(d)) {
+ fprintf(stderr, "error: failed to close directory (%s): %s\n",
+ dir, strerror(errno));
+ rv = 3;
+ break;
+ }
+
+ if (count == 0) {
+ if (verbose) {
+ printf("Removing directory '%s'\n", dir);
+ fflush(stdout);
+ }
+ if (0 != rmdir(dir)) {
+ fprintf(stderr, "error: failed to remove directory(%s): %s\n",
+ dir, strerror(errno));
+ rv = 3;
+ break;
+ }
+ }
+
+ dir_short = dirname(dir_short);
+ dir = dirname(dir);
+ }
+
+ free(short_path);
+ free(path);
+
+ return rv;
+}