Start 1.33.0 development cycle
[oweals/busybox.git] / libbb / simplify_path.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * bb_simplify_path implementation for busybox
4  *
5  * Copyright (C) 2001  Manuel Novoa III  <mjn3@codepoet.org>
6  *
7  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8  */
9 #include "libbb.h"
10
11 char* FAST_FUNC bb_simplify_abs_path_inplace(char *start)
12 {
13         char *s, *p;
14
15         p = s = start;
16         do {
17                 if (*p == '/') {
18                         if (*s == '/') {  /* skip duplicate (or initial) slash */
19                                 continue;
20                         }
21                         if (*s == '.') {
22                                 if (s[1] == '/' || !s[1]) {  /* remove extra '.' */
23                                         continue;
24                                 }
25                                 if ((s[1] == '.') && (s[2] == '/' || !s[2])) {
26                                         ++s;
27                                         if (p > start) {
28                                                 while (*--p != '/')  /* omit previous dir */
29                                                         continue;
30                                         }
31                                         continue;
32                                 }
33                         }
34                 }
35                 *++p = *s;
36         } while (*++s);
37
38         if ((p == start) || (*p != '/')) {  /* not a trailing slash */
39                 ++p;  /* so keep last character */
40         }
41         *p = '\0';
42         return p;
43 }
44
45 char* FAST_FUNC bb_simplify_path(const char *path)
46 {
47         char *s, *p;
48
49         if (path[0] == '/')
50                 s = xstrdup(path);
51         else {
52                 p = xrealloc_getcwd_or_warn(NULL);
53                 s = concat_path_file(p, path);
54                 free(p);
55         }
56
57         bb_simplify_abs_path_inplace(s);
58         return s;
59 }