Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
path.c
Go to the documentation of this file.
00001 /** 00002 * @file path.c 00003 * @brief Path manipulation helper functions 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU General Public License 00011 * as published by the Free Software Foundation; either version 2 00012 * of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software Foundation, 00021 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00022 * 00023 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00024 * @version 1.7.6 00025 **/ 00026 00027 //Dependencies 00028 #include <string.h> 00029 #include <ctype.h> 00030 #include "path.h" 00031 00032 00033 /** 00034 * @brief Test if the path is absolute 00035 * @param[in] path NULL-terminated string that contains the path 00036 * @return TRUE is the path is absolute, else FALSE 00037 **/ 00038 00039 bool_t pathIsAbsolute(const char_t *path) 00040 { 00041 //Determine if the path is absolute or relative 00042 if(path[0] == '/' || path[0] == '\\') 00043 return TRUE; 00044 else 00045 return FALSE; 00046 } 00047 00048 00049 /** 00050 * @brief Test if the path is relative 00051 * @param[in] path NULL-terminated string that contains the path 00052 * @return TRUE is the path is relative, else FALSE 00053 **/ 00054 00055 bool_t pathIsRelative(const char_t *path) 00056 { 00057 //Determine if the path is absolute or relative 00058 if(path[0] == '/' || path[0] == '\\') 00059 return FALSE; 00060 else 00061 return TRUE; 00062 } 00063 00064 00065 /** 00066 * @brief Search a path for a file name 00067 * @param[in] path NULL-terminated string that contains the path to search 00068 * @return Pointer to the file name 00069 **/ 00070 00071 const char_t *pathFindFileName(const char_t *path) 00072 { 00073 size_t n; 00074 00075 //Retrieve the length of the path 00076 n = strlen(path); 00077 00078 //Skip trailing slash or backslash characters 00079 while(n > 0) 00080 { 00081 //Forward slash or backslash character found? 00082 if(path[n - 1] != '/' && path[n - 1] != '\\') 00083 break; 00084 00085 //Previous character 00086 n--; 00087 } 00088 00089 //Search the string for the last separator 00090 while(n > 0) 00091 { 00092 //Forward slash or backslash character found? 00093 if(path[n - 1] == '/' || path[n - 1] == '\\') 00094 break; 00095 00096 //Previous character 00097 n--; 00098 } 00099 00100 //Return a pointer to the file name 00101 return path + n; 00102 } 00103 00104 00105 /** 00106 * @brief Simplify a path 00107 * @param[in] path NULL-terminated string containing the path to be canonicalized 00108 **/ 00109 00110 void pathCanonicalize(char_t *path) 00111 { 00112 size_t i; 00113 size_t j; 00114 size_t k; 00115 00116 //Move to the beginning of the string 00117 i = 0; 00118 k = 0; 00119 00120 //Replace backslashes with forward slashes 00121 while(path[i] != '\0') 00122 { 00123 //Forward slash or backslash separator found? 00124 if(path[i] == '/' || path[i] == '\\') 00125 { 00126 path[k++] = '/'; 00127 while(path[i] == '/' || path[i] == '\\') i++; 00128 } 00129 else 00130 { 00131 path[k++] = path[i++]; 00132 } 00133 } 00134 00135 //Properly terminate the string with a NULL character 00136 path[k] = '\0'; 00137 00138 //Move back to the beginning of the string 00139 i = 0; 00140 j = 0; 00141 k = 0; 00142 00143 //Parse the entire string 00144 do 00145 { 00146 //Forward slash separator found? 00147 if(path[i] == '/' || path[i] == '\0') 00148 { 00149 //"." element found? 00150 if((i - j) == 1 && !strncmp(path + j, ".", 1)) 00151 { 00152 //Check whether the pathname is empty? 00153 if(k == 0) 00154 { 00155 if(path[i] == '\0') 00156 { 00157 path[k++] = '.'; 00158 } 00159 else if(path[i] == '/' && path[i + 1] == '\0') 00160 { 00161 path[k++] = '.'; 00162 path[k++] = '/'; 00163 } 00164 } 00165 else if(k > 1) 00166 { 00167 //Remove the final slash if necessary 00168 if(path[i] == '\0') 00169 k--; 00170 } 00171 } 00172 //".." element found? 00173 else if((i - j) == 2 && !strncmp(path + j, "..", 2)) 00174 { 00175 //Check whether the pathname is empty? 00176 if(k == 0) 00177 { 00178 path[k++] = '.'; 00179 path[k++] = '.'; 00180 00181 //Append a slash if necessary 00182 if(path[i] == '/') 00183 path[k++] = '/'; 00184 } 00185 else if(k > 1) 00186 { 00187 //Search the path for the previous slash 00188 for(j = 1; j < k; j++) 00189 { 00190 if(path[k - j - 1] == '/') 00191 break; 00192 } 00193 00194 //Slash separator found? 00195 if(j < k) 00196 { 00197 if(!strncmp(path + k - j, "..", 2)) 00198 { 00199 path[k++] = '.'; 00200 path[k++] = '.'; 00201 } 00202 else 00203 { 00204 k = k - j - 1; 00205 } 00206 00207 //Append a slash if necessary 00208 if(k == 0 && path[0] == '/') 00209 path[k++] = '/'; 00210 else if(path[i] == '/') 00211 path[k++] = '/'; 00212 } 00213 //No slash separator found? 00214 else 00215 { 00216 if(k == 3 && !strncmp(path, "..", 2)) 00217 { 00218 path[k++] = '.'; 00219 path[k++] = '.'; 00220 00221 //Append a slash if necessary 00222 if(path[i] == '/') 00223 path[k++] = '/'; 00224 } 00225 else if(path[i] == '\0') 00226 { 00227 k = 0; 00228 path[k++] = '.'; 00229 } 00230 else if(path[i] == '/' && path[i + 1] == '\0') 00231 { 00232 k = 0; 00233 path[k++] = '.'; 00234 path[k++] = '/'; 00235 } 00236 else 00237 { 00238 k = 0; 00239 } 00240 } 00241 } 00242 } 00243 else 00244 { 00245 //Copy directory name 00246 memmove(path + k, path + j, i - j); 00247 //Advance write pointer 00248 k += i - j; 00249 00250 //Append a slash if necessary 00251 if(path[i] == '/') 00252 path[k++] = '/'; 00253 } 00254 00255 //Move to the next token 00256 while(path[i] == '/') i++; 00257 j = i; 00258 } 00259 } while(path[i++] != '\0'); 00260 00261 //Properly terminate the string with a NULL character 00262 path[k] = '\0'; 00263 } 00264 00265 00266 /** 00267 * @brief Add a slash to the end of a string 00268 * @param[in,out] path NULL-terminated string that represents the path 00269 * @param[in] maxLen Maximum pathname length 00270 **/ 00271 00272 void pathAddSlash(char_t *path, size_t maxLen) 00273 { 00274 size_t n; 00275 00276 //Retrieve the length of the string 00277 n = strlen(path); 00278 00279 //Add a slash character only if necessary 00280 if(!n) 00281 { 00282 //Check the length of the resulting string 00283 if(maxLen >= 1) 00284 strcpy(path, "/"); 00285 } 00286 else if(path[n - 1] != '/' && path[n - 1] != '\\') 00287 { 00288 //Check the length of the resulting string 00289 if(maxLen >= (n + 1)) 00290 strcat(path, "/"); 00291 } 00292 } 00293 00294 00295 /** 00296 * @brief Remove the trailing slash from a given path 00297 * @param[in,out] path NULL-terminated string that contains the path 00298 **/ 00299 00300 void pathRemoveSlash(char_t *path) 00301 { 00302 char_t *end; 00303 00304 //Skip the leading slash character 00305 if(pathIsAbsolute(path)) 00306 path++; 00307 00308 //Search for the first slash character to be removed 00309 for(end = NULL; *path != '\0'; path++) 00310 { 00311 if(*path != '/' && *path != '\\') 00312 end = NULL; 00313 else if(!end) 00314 end = path; 00315 } 00316 00317 //Remove the trailing slash characters 00318 if(end) *end = '\0'; 00319 } 00320 00321 00322 /** 00323 * @brief Concatenate two paths 00324 * @param[in,out] path NULL-terminated string containing the first path 00325 * @param[in] more NULL-terminated string containing the second path 00326 * @param[in] maxLen Maximum pathname length 00327 **/ 00328 00329 void pathCombine(char_t *path, const char_t *more, size_t maxLen) 00330 { 00331 size_t n1; 00332 size_t n2; 00333 00334 //Append a slash character to the first path 00335 if(*path != '\0') 00336 pathAddSlash(path, maxLen); 00337 00338 //Skip any slash character at the beginning of the second path 00339 while(*more == '/' || *more == '\\') more++; 00340 00341 //Retrieve the length of the first path 00342 n1 = strlen(path); 00343 //Retrieve the length of second path 00344 n2 = strlen(more); 00345 00346 //Check the length of the resulting string 00347 if(n1 < maxLen) 00348 { 00349 //Limit the number of characters to be copied 00350 n2 = MIN(n2, maxLen - n1); 00351 //Concatenate the resulting string 00352 strncpy(path + n1, more, n2); 00353 //Properly terminate the string with a NULL character 00354 path[n1 + n2] = '\0'; 00355 } 00356 } 00357 00358 00359 /** 00360 * @brief Check whether a file name matches the specified pattern 00361 * @param[in] path NULL-terminated string that contains the path to be matched 00362 * @param[in] pattern NULL-terminated string that contains the pattern for 00363 * which to search. The pattern may contain wildcard characters 00364 * @return TRUE if the path matches the specified pattern, else FALSE 00365 **/ 00366 00367 bool_t pathMatch(const char_t *path, const char_t* pattern) 00368 { 00369 size_t i = 0; 00370 size_t j = 0; 00371 00372 //Parse the pattern string 00373 while(pattern[j] != '\0') 00374 { 00375 //Any wildcard character found? 00376 if(pattern[j] == '?') 00377 { 00378 //The question mark matches a single character 00379 if(path[i] == '\0') 00380 { 00381 return FALSE; 00382 } 00383 else 00384 { 00385 //Advance position in pathname 00386 i++; 00387 //Advance position in pattern string 00388 j++; 00389 } 00390 } 00391 else if(pattern[j] == '*') 00392 { 00393 //The asterisk sign matches zero or more characters 00394 if(path[i] == '\0') 00395 { 00396 //Advance position in pattern string 00397 j++; 00398 } 00399 else if(pathMatch(path + i, pattern + j + 1)) 00400 { 00401 return TRUE; 00402 } 00403 else 00404 { 00405 //Advance position in pathname 00406 i++; 00407 } 00408 } 00409 else 00410 { 00411 //Case insensitive comparison 00412 if(tolower((uint8_t) path[i]) != tolower((uint8_t) pattern[j])) 00413 { 00414 return FALSE; 00415 } 00416 else 00417 { 00418 //Advance position in pathname 00419 i++; 00420 //Advance position in pattern string 00421 j++; 00422 } 00423 } 00424 } 00425 00426 //Check whether the file name matches the specified pattern 00427 if(path[i] == '\0' && pattern[j] == '\0') 00428 return TRUE; 00429 else 00430 return FALSE; 00431 } 00432
Generated on Tue Jul 12 2022 17:10:15 by
