blob: 55890325e14112f3cb235685950146cc2ce283bb (
plain)
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
|
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// FIXME: This is nowhere near complete
char *realpath(const char *filename, char *resolvedname) {
assert(resolvedname);
// FIXME: This really should have bounds checking
char cwd[256];
getcwd(cwd, 256);
strcat(cwd, filename);
const char *path = cwd;
char *result = resolvedname;
// It has to be a absolute path
if ('/' != *path)
return 0;
const char *result_start = result;
int start_directory = 0;
int should_insert_slash = 0;
for (; *path; path++) {
if (start_directory) {
start_directory = 0;
if ('/' == *path) {
path++;
} else if (0 == memcmp(path, "./", 2) || 0 == memcmp(path, ".\0", 2)) {
path++;
} else if (0 == memcmp(path, "../", 3) || 0 == memcmp(path, "..\0", 3)) {
path += 2;
if (result_start + 2 > result) {
// The path is probably something like "/.." or
// "/../foo". A "/.." should become a "/"
// Therefore it skips going back to the parent
if (*path == '/') {
if (result_start == result)
return 0;
result--;
}
} else {
if ('/' != *path) {
should_insert_slash = 1;
}
result--;
result--;
for (; result_start <= result && '/' != *result; result--)
;
}
}
}
start_directory = ('/' == *path);
if ('\0' == *path)
break;
*result = *path;
result++;
}
if (should_insert_slash) {
*result = '/';
result++;
}
*result = '\0';
return 1;
}
|