1 /*
2 * Copyright 2008-2013 Various Authors
3 * Copyright 2004 Timo Hirvonen
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "path.h"
20 #include "xmalloc.h"
21
22 #include <stdlib.h>
23 #include <unistd.h>
24
get_extension(const char * filename)25 const char *get_extension(const char *filename)
26 {
27 const char *ext;
28
29 ext = filename + strlen(filename) - 1;
30 while (ext >= filename && *ext != '/') {
31 if (*ext == '.') {
32 ext++;
33 return ext;
34 }
35 ext--;
36 }
37 return NULL;
38 }
39
path_basename(const char * path)40 const char *path_basename(const char *path)
41 {
42 const char *f;
43
44 f = strrchr(path, '/');
45
46 return f ? f + 1 : path;
47 }
48
path_strip(char * str)49 void path_strip(char *str)
50 {
51 int i, s, d;
52
53 i = 0;
54 if (str[0] == '/')
55 i = 1;
56 while (str[i]) {
57 if (str[i] == '/') {
58 d = i;
59 s = i + 1;
60 while (str[s] && str[s] == '/')
61 s++;
62 s--;
63 do {
64 str[d++] = str[++s];
65 } while (str[s]);
66 } else if (i && str[i] == '.') {
67 if (str[i + 1] == '/') {
68 d = i;
69 s = i + 1;
70 do {
71 str[d++] = str[++s];
72 } while (str[s]);
73 } else if (str[i + 1] == 0) {
74 str[i] = 0;
75 break;
76 } else if (str[i + 1] == '.' &&
77 (str[i + 2] == '/' || str[i + 2] == 0)) {
78 /* aaa/bbb/../ccc */
79 /* aaa/ccc */
80 if (str[i + 2]) {
81 s = i + 3; /* ccc */
82 } else {
83 s = i + 2;
84 }
85 d = i - 1; /* /../ccc */
86 do {
87 if (d == 0)
88 break;
89 d--;
90 } while (str[d] != '/');
91 d++;
92 /* std[d] is bbb/../ccc */
93 i = d;
94 s--;
95 do {
96 str[d++] = str[++s];
97 } while (str[s]);
98 } else {
99 while (str[i] && str[i] != '/')
100 i++;
101 if (str[i])
102 i++;
103 }
104 } else {
105 while (str[i] && str[i] != '/')
106 i++;
107 if (str[i])
108 i++;
109 }
110 }
111 if (i > 1 && str[i - 1] == '/')
112 str[i - 1] = 0;
113 }
114
path_absolute_cwd(const char * src,const char * cwd)115 char *path_absolute_cwd(const char *src, const char *cwd)
116 {
117 char *str;
118
119 if (src[0] == '/') {
120 /* already absolute */
121 str = xstrdup(src);
122 } else {
123 int src_len;
124 int cwd_len;
125
126 src_len = strlen(src);
127 cwd_len = strlen(cwd);
128 str = xnew(char, cwd_len + 1 + src_len + 1);
129 memcpy(str, cwd, cwd_len);
130 str[cwd_len] = '/';
131 memcpy(str + cwd_len + 1, src, src_len + 1);
132 }
133 path_strip(str);
134 return str;
135 }
136
path_absolute(const char * src)137 char *path_absolute(const char *src)
138 {
139 char cwd[1024];
140
141 if (!getcwd(cwd, sizeof(cwd))) {
142 cwd[0] = '/';
143 cwd[1] = 0;
144 }
145 return path_absolute_cwd(src, cwd);
146 }
147