diff options
Diffstat (limited to 'lib/x1000-installer/test_lib/pathfuncs.c')
-rw-r--r-- | lib/x1000-installer/test_lib/pathfuncs.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/lib/x1000-installer/test_lib/pathfuncs.c b/lib/x1000-installer/test_lib/pathfuncs.c new file mode 100644 index 0000000000..341efd4730 --- /dev/null +++ b/lib/x1000-installer/test_lib/pathfuncs.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2014 by Michael Sevakis | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "pathfuncs.h" | ||
23 | #include "strlcpy.h" | ||
24 | #include "system.h" | ||
25 | #include <string.h> | ||
26 | |||
27 | static const char* GOBBLE_PATH_SEPCH(const char* p) | ||
28 | { | ||
29 | int c; | ||
30 | while((c = *p) == PATH_SEPCH) | ||
31 | ++p; | ||
32 | return p; | ||
33 | } | ||
34 | |||
35 | static const char* GOBBLE_PATH_COMP(const char* p) | ||
36 | { | ||
37 | int c; | ||
38 | while((c = *p) && c != PATH_SEPCH) | ||
39 | ++p; | ||
40 | return p; | ||
41 | } | ||
42 | |||
43 | /* Strips the trailing component from the path | ||
44 | * "" *nameptr->NUL, len=0: "" | ||
45 | * "/" *nameptr->/, len=1: "/" | ||
46 | * "//" *nameptr->2nd /, len=1: "/" | ||
47 | * "/a" *nameptr->/, len=1: "/" | ||
48 | * "a/" *nameptr->a, len=0: "" | ||
49 | * "/a/bc" *nameptr->/, len=2: "/a" | ||
50 | * "d" *nameptr->d, len=0: "" | ||
51 | * "ef/gh" *nameptr->e, len=2: "ef" | ||
52 | * | ||
53 | * Notes: * Interpret len=0 as ".". | ||
54 | * * In the same string, path_dirname() returns a pointer with the | ||
55 | * same or lower address as path_basename(). | ||
56 | * * Pasting a separator between the returns of path_dirname() and | ||
57 | * path_basename() will result in a path equivalent to the input. | ||
58 | * | ||
59 | */ | ||
60 | size_t path_dirname(const char *name, const char **nameptr) | ||
61 | { | ||
62 | const char *p = GOBBLE_PATH_SEPCH(name); | ||
63 | const char *q = name; | ||
64 | const char *r = p; | ||
65 | |||
66 | while (*(p = GOBBLE_PATH_COMP(p))) | ||
67 | { | ||
68 | const char *s = p; | ||
69 | |||
70 | if (!*(p = GOBBLE_PATH_SEPCH(p))) | ||
71 | break; | ||
72 | |||
73 | q = s; | ||
74 | } | ||
75 | |||
76 | if (q == name && r > name) | ||
77 | name = r, q = name--; /* root - return last slash */ | ||
78 | |||
79 | *nameptr = name; | ||
80 | return q - name; | ||
81 | } | ||
82 | |||
83 | /* Appends one path to another, adding separators between components if needed. | ||
84 | * Return value and behavior is otherwise as strlcpy so that truncation may be | ||
85 | * detected. | ||
86 | * | ||
87 | * For basepath and component: | ||
88 | * PA_SEP_HARD adds a separator even if the base path is empty | ||
89 | * PA_SEP_SOFT adds a separator only if the base path is not empty | ||
90 | */ | ||
91 | size_t path_append(char *buf, const char *basepath, | ||
92 | const char *component, size_t bufsize) | ||
93 | { | ||
94 | const char *base = basepath && basepath[0] ? basepath : buf; | ||
95 | if (!base) | ||
96 | return bufsize; /* won't work to get lengths from buf */ | ||
97 | |||
98 | if (!buf) | ||
99 | bufsize = 0; | ||
100 | |||
101 | if (path_is_absolute(component)) | ||
102 | { | ||
103 | /* 'component' is absolute; replace all */ | ||
104 | basepath = component; | ||
105 | component = ""; | ||
106 | } | ||
107 | |||
108 | /* if basepath is not null or empty, buffer contents are replaced, | ||
109 | otherwise buf contains the base path */ | ||
110 | size_t len = base == buf ? strlen(buf) : my_strlcpy(buf, basepath, bufsize); | ||
111 | |||
112 | bool separate = false; | ||
113 | |||
114 | if (!basepath || !component) | ||
115 | separate = !len || base[len-1] != PATH_SEPCH; | ||
116 | else if (component[0]) | ||
117 | separate = len && base[len-1] != PATH_SEPCH; | ||
118 | |||
119 | /* caller might lie about size of buf yet use buf as the base */ | ||
120 | if (base == buf && bufsize && len >= bufsize) | ||
121 | buf[bufsize - 1] = '\0'; | ||
122 | |||
123 | buf += len; | ||
124 | bufsize -= MIN(len, bufsize); | ||
125 | |||
126 | if (separate && (len++, bufsize > 0) && --bufsize > 0) | ||
127 | *buf++ = PATH_SEPCH; | ||
128 | |||
129 | return len + my_strlcpy(buf, component ?: "", bufsize); | ||
130 | } | ||