aboutsummaryrefslogtreecommitdiffstats
path: root/src/filepath.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/filepath.c')
-rw-r--r--src/filepath.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/filepath.c b/src/filepath.c
new file mode 100644
index 0000000..b8b217a
--- /dev/null
+++ b/src/filepath.c
@@ -0,0 +1,121 @@
+#include <stdbool.h>
+#include <assert.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "util.h"
+#define _FILENAME "build.c"
+#include "dbg.h"
+
+
+/* Check if the given path is absolute */
+bool is_absolute(const char* path) {
+ return path[0] == '/';
+}
+
+/* Returns a new copy of str with the extension removed, where the extension is
+ everything behind the last dot, including the dot. */
+char *remove_ext(const char *str) {
+ assert(str);
+ size_t len;
+ char *ret, *dot = NULL;
+
+ for (len = 0; str[len]; ++len)
+ if (str[len] == '.')
+ dot = (char*) &str[len];
+
+ if (dot) /* recalculate length to only reach just before the last dot */
+ len = dot - str;
+
+ ret = safe_malloc(len+1);
+ memcpy(ret, str, len);
+ ret[len] = '\0';
+
+ return ret;
+}
+
+/* Returns the extension of the target or the empty string if none was found */
+char *take_extension(const char *target) {
+ assert(target);
+ char *temp = strrchr(target, '.');
+ if (temp)
+ return temp;
+ else
+ return "";
+}
+
+/* Make one path relative to another i.e. some/path to some/path/a/b/c would
+ yield a/b/c as result. Prints '.' if the 2 paths match */
+// TODO: nameing, requires absolute paths, doesn't MALLOC
+const char *make_relative(const char *target, const char *to) {
+ int i;
+ for (i = 0; target[i] && to[i]; ++i)
+ if (target[i] != to[i]) {
+ /* the paths do not match */
+ return to;
+ }
+
+ if (!target[i] && !to[i]) {
+ /* both paths match completely */
+ return ".";
+ }
+
+ /* skip any leading seperators */
+ while (to[i] == '/')
+ ++i;
+
+ return &to[i];
+}
+
+/* Transforms target into a safe filename, replacing all '/' with '!' */
+char *transform_path(const char *target) {
+ char *ptr = (char*) target;
+ size_t escape = 0, i = 0;
+ while (*ptr++)
+ if (*ptr == '!') escape++;
+
+ ptr = safe_malloc((ptr-target) + escape + 1);
+ do {
+ if (*target == '/')
+ ptr[i++] = '!';
+ else if (*target == '!') {
+ ptr[i++] = '!';
+ ptr[i++] = '!';
+ } else
+ ptr[i++] = *target;
+ } while (*target++);
+
+ ptr[i] = '\0';
+ return ptr;
+}
+
+/* Sane and portable basename implementation */
+char *xbasename(const char *path) {
+ assert(path);
+ char *ptr = strrchr(path, '/');
+ return ptr? ptr+1 : (char*) path;
+}
+
+/* Checks if target exists and prints a debug message if access() failed
+ except if it failed with ENOENT. */
+bool fexists(const char *target) {
+ assert(target);
+ if (!access(target, F_OK))
+ return true;
+ if (errno != ENOENT)
+ debug("Failed to access %s: %s\n", target, strerror(errno));
+ return false;
+}
+
+/* Returns the size of fn, or -1 if the file doesn't exist. */
+off_t fsize(const char *fn) {
+ struct stat st;
+ if (stat(fn, &st)) {
+ if (errno != ENOENT)
+ fatal(ERRM_STAT, fn);
+ return -1;
+ }
+
+ return st.st_size;
+}