agendafs
A filesystem for your calendar.
git clone git://mccd.space/agendafs| Log | Files | Refs | README | LICENSE | Mail | Website |
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