Initial public busybox upstream commit
[busybox4maemo] / 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 tarball for details.
8  */
9
10 #include "libbb.h"
11
12 char *bb_simplify_path(const char *path)
13 {
14         char *s, *start, *p;
15
16         if (path[0] == '/')
17                 start = xstrdup(path);
18         else {
19                 s = xrealloc_getcwd_or_warn(NULL);
20                 start = concat_path_file(s, path);
21                 free(s);
22         }
23         p = s = start;
24
25         do {
26                 if (*p == '/') {
27                         if (*s == '/') {        /* skip duplicate (or initial) slash */
28                                 continue;
29                         }
30                         if (*s == '.') {
31                                 if (s[1] == '/' || !s[1]) {     /* remove extra '.' */
32                                         continue;
33                                 }
34                                 if ((s[1] == '.') && (s[2] == '/' || !s[2])) {
35                                         ++s;
36                                         if (p > start) {
37                                                 while (*--p != '/')     /* omit previous dir */
38                                                         continue;
39                                         }
40                                         continue;
41                                 }
42                         }
43                 }
44                 *++p = *s;
45         } while (*++s);
46
47         if ((p == start) || (*p != '/')) {      /* not a trailing slash */
48                 ++p;                                    /* so keep last character */
49         }
50         *p = 0;
51
52         return start;
53 }