1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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;
}
|