1 /*
2 * Copyright (c) 2019, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /*
31 =======================================================================
32
33 FILE: std_path.c
34
35 =======================================================================
36 =======================================================================
37 */
38
39 #include "AEEstd.h"
40 #include "AEEBufBound.h"
41 #include <string.h>
42 /*===========================================================================
43
44 ===========================================================================*/
std_makepath(const char * cpszDir,const char * cpszFile,char * pszOut,int nOutLen)45 int std_makepath(const char* cpszDir, const char* cpszFile,
46 char* pszOut, int nOutLen)
47 {
48 BufBound bb;
49
50 BufBound_Init(&bb, pszOut, nOutLen);
51
52 BufBound_Puts(&bb, cpszDir);
53
54 if (('\0' != cpszDir[0]) && /* non-empty dir */
55 ('/' != cpszDir[std_strlen(cpszDir)-1])) { /* no slash at end of dir */
56 BufBound_Putc(&bb, '/');
57 }
58 if ('/' == cpszFile[0]) {
59 cpszFile++;
60 }
61
62 BufBound_Puts(&bb, cpszFile);
63
64 BufBound_ForceNullTerm(&bb);
65
66 return BufBound_Wrote(&bb) - 1;
67
68 }
69
70 /*===========================================================================
71
72 ===========================================================================*/
std_splitpath(const char * cpszPath,const char * cpszDir)73 char* std_splitpath(const char* cpszPath, const char* cpszDir)
74 {
75 const char* cpsz = cpszPath;
76
77 while ( ! ('\0' == cpszDir[0] ||
78 ('/' == cpszDir[0] && '\0' == cpszDir[1])) ){
79
80 if (*cpszDir != *cpsz) {
81 return 0;
82 }
83
84 ++cpsz;
85 ++cpszDir;
86 }
87
88 /* Found the filename part of the path.
89 It should begin with a '/' unless there is no filename */
90 if ('/' == *cpsz) {
91 cpsz++;
92 }
93 else if ('\0' != *cpsz) {
94 cpsz = 0;
95 }
96
97 return (char*)cpsz;
98 }
99
std_cleanpath(char * pszPath)100 char* std_cleanpath(char* pszPath)
101 {
102 char* pszStart = pszPath;
103 char* pc;
104 char* pcEnd = pszStart+std_strlen(pszStart);
105
106 /* preserve leading slash */
107 if ('/' == pszStart[0]) {
108 pszStart++;
109 }
110
111 pc = pszStart;
112
113 while ((char*)0 != (pc = std_strstr(pc, "/."))) {
114 char* pcDelFrom;
115
116 if ('/' == pc[2] || '\0' == pc[2]) {
117 /* delete "/." */
118 pcDelFrom = pc;
119 pc += 2;
120 } else if ('.' == pc[2] && ('/' == pc[3] || '\0' == pc[3])) {
121 /* delete "/element/.." */
122 pcDelFrom = std_memrchrbegin(pszStart, '/', pc - pszStart);
123 pc += 3;
124 } else {
125 pc += 2;
126 continue;
127 }
128
129 std_memmove(pcDelFrom, pc, pcEnd-pcDelFrom);
130
131 pc = pcDelFrom;
132 }
133
134 /* eliminate leading "../" */
135 while (pszStart == std_strstr(pszStart, "../")) {
136 std_memmove(pszStart, pszStart+2, pcEnd-pszStart);
137 }
138
139 /* eliminate leading "./" */
140 while (pszStart == std_strstr(pszStart, "./")) {
141 std_memmove(pszStart, pszStart+1, pcEnd-pszStart);
142 }
143
144 if (!strncmp(pszStart,"..",2) || !strncmp(pszStart,".",1)) {
145 pszStart[0] = '\0';
146 }
147
148 /* whack double '/' */
149 while ((char*)0 != (pc = std_strstr(pszPath, "//"))) {
150 std_memmove(pc, pc+1, pcEnd-pc);
151 }
152
153 return pszPath;
154 }
155
std_basename(const char * cpszFile)156 char* std_basename(const char* cpszFile)
157 {
158 const char* cpsz;
159
160 if ((char*)0 != (cpsz = std_strrchr(cpszFile,'/'))) {
161 cpszFile = cpsz+1;
162 }
163
164 return (char*)cpszFile;
165 }
166