agendafs

A filesystem for your calendar.

git clone git://mccd.space/agendafs

path.c (2503B)

      1 #include "path.h"
      2 #include "arena.h"
      3 #include <assert.h>
      4 #include <errno.h>
      5 #include <stdbool.h>
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 
     10 path *
     11 without_file_extension(arena *m, const path *p)
     12 {
     13 	char *cpy = rstrdup(m, p);
     14 	char *last_dot = strrchr(cpy, '.');
     15 	char *last_slash = strrchr(cpy, '/');
     16 
     17 	// Only remove the extension if dot is after
     18 	if (last_dot && (!last_slash || last_dot > last_slash)) {
     19 		*last_dot = '\0';
     20 	}
     21 	return cpy;
     22 }
     23 
     24 path *
     25 get_file_extension(arena *m, const path *p)
     26 {
     27 	char *cpy = rstrdup(m, p);
     28 	char *last_dot = strrchr(cpy, '.');
     29 	if (last_dot) {
     30 		last_dot++;
     31 	}
     32 
     33 	return last_dot;
     34 }
     35 
     36 bool
     37 pathIsHidden(const path *p)
     38 {
     39 	return p[0] == '.';
     40 }
     41 
     42 path *
     43 append_path(arena *m, const path *parentp, const char *childp)
     44 {
     45 	char *filepath = NULL;
     46 	size_t res = asprintf(&filepath, "%s/%s", parentp, childp);
     47 	assert(res != -1);
     48 	arena_register(m, filepath, free);
     49 	return filepath;
     50 }
     51 
     52 const path *
     53 get_filename(const char *full_path)
     54 {
     55 	char *base_name = strrchr(full_path, '/');
     56 	if (!base_name)
     57 		return (char *)full_path;
     58 	return base_name + 1;
     59 }
     60 
     61 char *
     62 get_parent_path(arena *ar, const char *path)
     63 {
     64 	char *path_copy = rstrdup(ar, path);
     65 
     66 	char *last_slash = strrchr(path_copy, '/');
     67 	if (last_slash == NULL) {
     68 		return NULL;
     69 	}
     70 
     71 	// If they are the same, it means the parent is root
     72 	if (strcmp(last_slash, path_copy) == 0) {
     73 		return "/";
     74 	}
     75 
     76 	*last_slash = '\0';
     77 	return path_copy;
     78 }
     79 
     80 size_t
     81 split_path(arena *m, const path *p, char **segments)
     82 {
     83 	char *path_copy = rstrdup(m, p);
     84 
     85 	size_t count = 0;
     86 	char *segment;
     87 
     88 	char *saveptr;
     89 	segment = strtok_r(path_copy, "/", &saveptr);
     90 	while (segment) {
     91 		segments[count++] = rstrdup(m, segment);
     92 		segment = strtok_r(NULL, "/", &saveptr);
     93 	}
     94 	return count;
     95 }
     96 
     97 size_t
     98 write_to_file(const path *filepath, const char *content)
     99 {
    100 	FILE *f = fopen(filepath, "w");
    101 	if (!f) {
    102 		perror("Failed to open file");
    103 		return -EIO;
    104 	}
    105 	fputs(content, f);
    106 	fclose(f);
    107 	return 0;
    108 }
    109 
    110 // Creates a new path
    111 // my-file.txt -> my-file.1.txt
    112 // Caller is responsible for freeing memory
    113 path *
    114 filename_numbered(const char *filename, size_t n)
    115 {
    116 	const char *ext = strrchr(filename, '.');
    117 	char *new_filename;
    118 	size_t len = 0;
    119 
    120 	FILE *stream = open_memstream(&new_filename, &len);
    121 	assert(stream);
    122 
    123 	if (ext) {
    124 		size_t base_len = ext - filename;
    125 		fwrite(filename, 1, base_len, stream);
    126 		fprintf(stream, ".%zu%s", n, ext);
    127 	}
    128 	else {
    129 		fprintf(stream, "%s.%zu", filename, n);
    130 	}
    131 
    132 	fclose(stream);
    133 
    134 	return new_filename;
    135 }
    136