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