-
Notifications
You must be signed in to change notification settings - Fork 0
/
pathresolve.c
138 lines (116 loc) · 3.49 KB
/
pathresolve.c
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Returns a pointer to the @n'th char matching
* @c in string @str, starting the search from right or
* end-of-string, rather than starting from left, as rindex
* function does.
*/
char *
libgf_rrindex (char *str, int c, int n)
{
int len = 0;
int occurrence = 0;
if (str == NULL)
return NULL;
len = strlen (str);
/* Point to last character of string. */
str += (len - 1);
while (len > 0) {
if ((int)*str == c) {
++occurrence;
if (occurrence == n)
break;
}
--len;
--str;
}
return str;
}
char *
libgf_trim_to_prev_dir (char * path)
{
char *idx = NULL;
if (!path)
return NULL;
/* Check if we're already at root, if yes
* then there is no prev dir.
*/
if (strlen (path) == 1)
return path;
idx = libgf_rrindex (path, '/', 1);
/* Move to the char after the / */
++idx;
*idx = '\0';
return path;
}
/* Performs a lightweight path resolution that only
* looks for . and .. and replaces those with the
* proper names.
*
* FIXME: This is a stop-gap measure till we have full
* fledge path resolution going in here.
* Function returns path strdup'ed so remember to FREE the
* string as required.
*/
char *
libgf_resolve_path_light (char *path)
{
char *respath = NULL;
char *saveptr = NULL;
char *tok = NULL;
char *mypath = NULL;
int len = 0;
int addslash = 0;
if (!path)
goto out;
/* We dont as yet support relative paths anywhere in
* the lib.
*/
if (path[0] != '/')
goto out;
mypath = strdup (path);
len = strlen (mypath);
respath = calloc (strlen(mypath) + 1, sizeof (char));
if (respath == NULL)
goto out;
/* The path only contains a / or a //, so simply add a /
* and return.
* This needs special handling because the loop below does
* not allow us to do so through strtok.
*/
if (((mypath[0] == '/') && (len == 1))
|| (strcmp (mypath, "//") == 0)) {
strcat (respath, "/");
goto out;
}
tok = strtok_r (mypath, "/", &saveptr);
addslash = 0;
strcat (respath, "/");
while (tok) {
if (addslash) {
if ((strcmp (tok, ".") != 0)
&& (strcmp (tok, "..") != 0)) {
strcat (respath, "/");
}
}
if ((strcmp (tok, ".") != 0) && (strcmp (tok, "..") != 0)) {
strcat (respath, tok);
addslash = 1;
} else if ((strcmp (tok, "..") == 0)) {
libgf_trim_to_prev_dir (respath);
addslash = 0;
}
tok = strtok_r (NULL, "/", &saveptr);
}
out:
if (mypath)
free (mypath);
return respath;
}
int
main (int argc, char *argv[])
{
fprintf (stdout, "%s\n", libgf_resolve_path_light (argv [1]));
return 0;
}