Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
common/path.c@0:8918a71cdbe9, 2017-02-04 (annotated)
- Committer:
- Sergunb
- Date:
- Sat Feb 04 18:15:49 2017 +0000
- Revision:
- 0:8918a71cdbe9
nothing else
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| Sergunb | 0:8918a71cdbe9 | 1 | /** |
| Sergunb | 0:8918a71cdbe9 | 2 | * @file path.c |
| Sergunb | 0:8918a71cdbe9 | 3 | * @brief Path manipulation helper functions |
| Sergunb | 0:8918a71cdbe9 | 4 | * |
| Sergunb | 0:8918a71cdbe9 | 5 | * @section License |
| Sergunb | 0:8918a71cdbe9 | 6 | * |
| Sergunb | 0:8918a71cdbe9 | 7 | * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. |
| Sergunb | 0:8918a71cdbe9 | 8 | * |
| Sergunb | 0:8918a71cdbe9 | 9 | * This program is free software; you can redistribute it and/or |
| Sergunb | 0:8918a71cdbe9 | 10 | * modify it under the terms of the GNU General Public License |
| Sergunb | 0:8918a71cdbe9 | 11 | * as published by the Free Software Foundation; either version 2 |
| Sergunb | 0:8918a71cdbe9 | 12 | * of the License, or (at your option) any later version. |
| Sergunb | 0:8918a71cdbe9 | 13 | * |
| Sergunb | 0:8918a71cdbe9 | 14 | * This program is distributed in the hope that it will be useful, |
| Sergunb | 0:8918a71cdbe9 | 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| Sergunb | 0:8918a71cdbe9 | 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| Sergunb | 0:8918a71cdbe9 | 17 | * GNU General Public License for more details. |
| Sergunb | 0:8918a71cdbe9 | 18 | * |
| Sergunb | 0:8918a71cdbe9 | 19 | * You should have received a copy of the GNU General Public License |
| Sergunb | 0:8918a71cdbe9 | 20 | * along with this program; if not, write to the Free Software Foundation, |
| Sergunb | 0:8918a71cdbe9 | 21 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| Sergunb | 0:8918a71cdbe9 | 22 | * |
| Sergunb | 0:8918a71cdbe9 | 23 | * @author Oryx Embedded SARL (www.oryx-embedded.com) |
| Sergunb | 0:8918a71cdbe9 | 24 | * @version 1.7.6 |
| Sergunb | 0:8918a71cdbe9 | 25 | **/ |
| Sergunb | 0:8918a71cdbe9 | 26 | |
| Sergunb | 0:8918a71cdbe9 | 27 | //Dependencies |
| Sergunb | 0:8918a71cdbe9 | 28 | #include <string.h> |
| Sergunb | 0:8918a71cdbe9 | 29 | #include <ctype.h> |
| Sergunb | 0:8918a71cdbe9 | 30 | #include "path.h" |
| Sergunb | 0:8918a71cdbe9 | 31 | |
| Sergunb | 0:8918a71cdbe9 | 32 | |
| Sergunb | 0:8918a71cdbe9 | 33 | /** |
| Sergunb | 0:8918a71cdbe9 | 34 | * @brief Test if the path is absolute |
| Sergunb | 0:8918a71cdbe9 | 35 | * @param[in] path NULL-terminated string that contains the path |
| Sergunb | 0:8918a71cdbe9 | 36 | * @return TRUE is the path is absolute, else FALSE |
| Sergunb | 0:8918a71cdbe9 | 37 | **/ |
| Sergunb | 0:8918a71cdbe9 | 38 | |
| Sergunb | 0:8918a71cdbe9 | 39 | bool_t pathIsAbsolute(const char_t *path) |
| Sergunb | 0:8918a71cdbe9 | 40 | { |
| Sergunb | 0:8918a71cdbe9 | 41 | //Determine if the path is absolute or relative |
| Sergunb | 0:8918a71cdbe9 | 42 | if(path[0] == '/' || path[0] == '\\') |
| Sergunb | 0:8918a71cdbe9 | 43 | return TRUE; |
| Sergunb | 0:8918a71cdbe9 | 44 | else |
| Sergunb | 0:8918a71cdbe9 | 45 | return FALSE; |
| Sergunb | 0:8918a71cdbe9 | 46 | } |
| Sergunb | 0:8918a71cdbe9 | 47 | |
| Sergunb | 0:8918a71cdbe9 | 48 | |
| Sergunb | 0:8918a71cdbe9 | 49 | /** |
| Sergunb | 0:8918a71cdbe9 | 50 | * @brief Test if the path is relative |
| Sergunb | 0:8918a71cdbe9 | 51 | * @param[in] path NULL-terminated string that contains the path |
| Sergunb | 0:8918a71cdbe9 | 52 | * @return TRUE is the path is relative, else FALSE |
| Sergunb | 0:8918a71cdbe9 | 53 | **/ |
| Sergunb | 0:8918a71cdbe9 | 54 | |
| Sergunb | 0:8918a71cdbe9 | 55 | bool_t pathIsRelative(const char_t *path) |
| Sergunb | 0:8918a71cdbe9 | 56 | { |
| Sergunb | 0:8918a71cdbe9 | 57 | //Determine if the path is absolute or relative |
| Sergunb | 0:8918a71cdbe9 | 58 | if(path[0] == '/' || path[0] == '\\') |
| Sergunb | 0:8918a71cdbe9 | 59 | return FALSE; |
| Sergunb | 0:8918a71cdbe9 | 60 | else |
| Sergunb | 0:8918a71cdbe9 | 61 | return TRUE; |
| Sergunb | 0:8918a71cdbe9 | 62 | } |
| Sergunb | 0:8918a71cdbe9 | 63 | |
| Sergunb | 0:8918a71cdbe9 | 64 | |
| Sergunb | 0:8918a71cdbe9 | 65 | /** |
| Sergunb | 0:8918a71cdbe9 | 66 | * @brief Search a path for a file name |
| Sergunb | 0:8918a71cdbe9 | 67 | * @param[in] path NULL-terminated string that contains the path to search |
| Sergunb | 0:8918a71cdbe9 | 68 | * @return Pointer to the file name |
| Sergunb | 0:8918a71cdbe9 | 69 | **/ |
| Sergunb | 0:8918a71cdbe9 | 70 | |
| Sergunb | 0:8918a71cdbe9 | 71 | const char_t *pathFindFileName(const char_t *path) |
| Sergunb | 0:8918a71cdbe9 | 72 | { |
| Sergunb | 0:8918a71cdbe9 | 73 | size_t n; |
| Sergunb | 0:8918a71cdbe9 | 74 | |
| Sergunb | 0:8918a71cdbe9 | 75 | //Retrieve the length of the path |
| Sergunb | 0:8918a71cdbe9 | 76 | n = strlen(path); |
| Sergunb | 0:8918a71cdbe9 | 77 | |
| Sergunb | 0:8918a71cdbe9 | 78 | //Skip trailing slash or backslash characters |
| Sergunb | 0:8918a71cdbe9 | 79 | while(n > 0) |
| Sergunb | 0:8918a71cdbe9 | 80 | { |
| Sergunb | 0:8918a71cdbe9 | 81 | //Forward slash or backslash character found? |
| Sergunb | 0:8918a71cdbe9 | 82 | if(path[n - 1] != '/' && path[n - 1] != '\\') |
| Sergunb | 0:8918a71cdbe9 | 83 | break; |
| Sergunb | 0:8918a71cdbe9 | 84 | |
| Sergunb | 0:8918a71cdbe9 | 85 | //Previous character |
| Sergunb | 0:8918a71cdbe9 | 86 | n--; |
| Sergunb | 0:8918a71cdbe9 | 87 | } |
| Sergunb | 0:8918a71cdbe9 | 88 | |
| Sergunb | 0:8918a71cdbe9 | 89 | //Search the string for the last separator |
| Sergunb | 0:8918a71cdbe9 | 90 | while(n > 0) |
| Sergunb | 0:8918a71cdbe9 | 91 | { |
| Sergunb | 0:8918a71cdbe9 | 92 | //Forward slash or backslash character found? |
| Sergunb | 0:8918a71cdbe9 | 93 | if(path[n - 1] == '/' || path[n - 1] == '\\') |
| Sergunb | 0:8918a71cdbe9 | 94 | break; |
| Sergunb | 0:8918a71cdbe9 | 95 | |
| Sergunb | 0:8918a71cdbe9 | 96 | //Previous character |
| Sergunb | 0:8918a71cdbe9 | 97 | n--; |
| Sergunb | 0:8918a71cdbe9 | 98 | } |
| Sergunb | 0:8918a71cdbe9 | 99 | |
| Sergunb | 0:8918a71cdbe9 | 100 | //Return a pointer to the file name |
| Sergunb | 0:8918a71cdbe9 | 101 | return path + n; |
| Sergunb | 0:8918a71cdbe9 | 102 | } |
| Sergunb | 0:8918a71cdbe9 | 103 | |
| Sergunb | 0:8918a71cdbe9 | 104 | |
| Sergunb | 0:8918a71cdbe9 | 105 | /** |
| Sergunb | 0:8918a71cdbe9 | 106 | * @brief Simplify a path |
| Sergunb | 0:8918a71cdbe9 | 107 | * @param[in] path NULL-terminated string containing the path to be canonicalized |
| Sergunb | 0:8918a71cdbe9 | 108 | **/ |
| Sergunb | 0:8918a71cdbe9 | 109 | |
| Sergunb | 0:8918a71cdbe9 | 110 | void pathCanonicalize(char_t *path) |
| Sergunb | 0:8918a71cdbe9 | 111 | { |
| Sergunb | 0:8918a71cdbe9 | 112 | size_t i; |
| Sergunb | 0:8918a71cdbe9 | 113 | size_t j; |
| Sergunb | 0:8918a71cdbe9 | 114 | size_t k; |
| Sergunb | 0:8918a71cdbe9 | 115 | |
| Sergunb | 0:8918a71cdbe9 | 116 | //Move to the beginning of the string |
| Sergunb | 0:8918a71cdbe9 | 117 | i = 0; |
| Sergunb | 0:8918a71cdbe9 | 118 | k = 0; |
| Sergunb | 0:8918a71cdbe9 | 119 | |
| Sergunb | 0:8918a71cdbe9 | 120 | //Replace backslashes with forward slashes |
| Sergunb | 0:8918a71cdbe9 | 121 | while(path[i] != '\0') |
| Sergunb | 0:8918a71cdbe9 | 122 | { |
| Sergunb | 0:8918a71cdbe9 | 123 | //Forward slash or backslash separator found? |
| Sergunb | 0:8918a71cdbe9 | 124 | if(path[i] == '/' || path[i] == '\\') |
| Sergunb | 0:8918a71cdbe9 | 125 | { |
| Sergunb | 0:8918a71cdbe9 | 126 | path[k++] = '/'; |
| Sergunb | 0:8918a71cdbe9 | 127 | while(path[i] == '/' || path[i] == '\\') i++; |
| Sergunb | 0:8918a71cdbe9 | 128 | } |
| Sergunb | 0:8918a71cdbe9 | 129 | else |
| Sergunb | 0:8918a71cdbe9 | 130 | { |
| Sergunb | 0:8918a71cdbe9 | 131 | path[k++] = path[i++]; |
| Sergunb | 0:8918a71cdbe9 | 132 | } |
| Sergunb | 0:8918a71cdbe9 | 133 | } |
| Sergunb | 0:8918a71cdbe9 | 134 | |
| Sergunb | 0:8918a71cdbe9 | 135 | //Properly terminate the string with a NULL character |
| Sergunb | 0:8918a71cdbe9 | 136 | path[k] = '\0'; |
| Sergunb | 0:8918a71cdbe9 | 137 | |
| Sergunb | 0:8918a71cdbe9 | 138 | //Move back to the beginning of the string |
| Sergunb | 0:8918a71cdbe9 | 139 | i = 0; |
| Sergunb | 0:8918a71cdbe9 | 140 | j = 0; |
| Sergunb | 0:8918a71cdbe9 | 141 | k = 0; |
| Sergunb | 0:8918a71cdbe9 | 142 | |
| Sergunb | 0:8918a71cdbe9 | 143 | //Parse the entire string |
| Sergunb | 0:8918a71cdbe9 | 144 | do |
| Sergunb | 0:8918a71cdbe9 | 145 | { |
| Sergunb | 0:8918a71cdbe9 | 146 | //Forward slash separator found? |
| Sergunb | 0:8918a71cdbe9 | 147 | if(path[i] == '/' || path[i] == '\0') |
| Sergunb | 0:8918a71cdbe9 | 148 | { |
| Sergunb | 0:8918a71cdbe9 | 149 | //"." element found? |
| Sergunb | 0:8918a71cdbe9 | 150 | if((i - j) == 1 && !strncmp(path + j, ".", 1)) |
| Sergunb | 0:8918a71cdbe9 | 151 | { |
| Sergunb | 0:8918a71cdbe9 | 152 | //Check whether the pathname is empty? |
| Sergunb | 0:8918a71cdbe9 | 153 | if(k == 0) |
| Sergunb | 0:8918a71cdbe9 | 154 | { |
| Sergunb | 0:8918a71cdbe9 | 155 | if(path[i] == '\0') |
| Sergunb | 0:8918a71cdbe9 | 156 | { |
| Sergunb | 0:8918a71cdbe9 | 157 | path[k++] = '.'; |
| Sergunb | 0:8918a71cdbe9 | 158 | } |
| Sergunb | 0:8918a71cdbe9 | 159 | else if(path[i] == '/' && path[i + 1] == '\0') |
| Sergunb | 0:8918a71cdbe9 | 160 | { |
| Sergunb | 0:8918a71cdbe9 | 161 | path[k++] = '.'; |
| Sergunb | 0:8918a71cdbe9 | 162 | path[k++] = '/'; |
| Sergunb | 0:8918a71cdbe9 | 163 | } |
| Sergunb | 0:8918a71cdbe9 | 164 | } |
| Sergunb | 0:8918a71cdbe9 | 165 | else if(k > 1) |
| Sergunb | 0:8918a71cdbe9 | 166 | { |
| Sergunb | 0:8918a71cdbe9 | 167 | //Remove the final slash if necessary |
| Sergunb | 0:8918a71cdbe9 | 168 | if(path[i] == '\0') |
| Sergunb | 0:8918a71cdbe9 | 169 | k--; |
| Sergunb | 0:8918a71cdbe9 | 170 | } |
| Sergunb | 0:8918a71cdbe9 | 171 | } |
| Sergunb | 0:8918a71cdbe9 | 172 | //".." element found? |
| Sergunb | 0:8918a71cdbe9 | 173 | else if((i - j) == 2 && !strncmp(path + j, "..", 2)) |
| Sergunb | 0:8918a71cdbe9 | 174 | { |
| Sergunb | 0:8918a71cdbe9 | 175 | //Check whether the pathname is empty? |
| Sergunb | 0:8918a71cdbe9 | 176 | if(k == 0) |
| Sergunb | 0:8918a71cdbe9 | 177 | { |
| Sergunb | 0:8918a71cdbe9 | 178 | path[k++] = '.'; |
| Sergunb | 0:8918a71cdbe9 | 179 | path[k++] = '.'; |
| Sergunb | 0:8918a71cdbe9 | 180 | |
| Sergunb | 0:8918a71cdbe9 | 181 | //Append a slash if necessary |
| Sergunb | 0:8918a71cdbe9 | 182 | if(path[i] == '/') |
| Sergunb | 0:8918a71cdbe9 | 183 | path[k++] = '/'; |
| Sergunb | 0:8918a71cdbe9 | 184 | } |
| Sergunb | 0:8918a71cdbe9 | 185 | else if(k > 1) |
| Sergunb | 0:8918a71cdbe9 | 186 | { |
| Sergunb | 0:8918a71cdbe9 | 187 | //Search the path for the previous slash |
| Sergunb | 0:8918a71cdbe9 | 188 | for(j = 1; j < k; j++) |
| Sergunb | 0:8918a71cdbe9 | 189 | { |
| Sergunb | 0:8918a71cdbe9 | 190 | if(path[k - j - 1] == '/') |
| Sergunb | 0:8918a71cdbe9 | 191 | break; |
| Sergunb | 0:8918a71cdbe9 | 192 | } |
| Sergunb | 0:8918a71cdbe9 | 193 | |
| Sergunb | 0:8918a71cdbe9 | 194 | //Slash separator found? |
| Sergunb | 0:8918a71cdbe9 | 195 | if(j < k) |
| Sergunb | 0:8918a71cdbe9 | 196 | { |
| Sergunb | 0:8918a71cdbe9 | 197 | if(!strncmp(path + k - j, "..", 2)) |
| Sergunb | 0:8918a71cdbe9 | 198 | { |
| Sergunb | 0:8918a71cdbe9 | 199 | path[k++] = '.'; |
| Sergunb | 0:8918a71cdbe9 | 200 | path[k++] = '.'; |
| Sergunb | 0:8918a71cdbe9 | 201 | } |
| Sergunb | 0:8918a71cdbe9 | 202 | else |
| Sergunb | 0:8918a71cdbe9 | 203 | { |
| Sergunb | 0:8918a71cdbe9 | 204 | k = k - j - 1; |
| Sergunb | 0:8918a71cdbe9 | 205 | } |
| Sergunb | 0:8918a71cdbe9 | 206 | |
| Sergunb | 0:8918a71cdbe9 | 207 | //Append a slash if necessary |
| Sergunb | 0:8918a71cdbe9 | 208 | if(k == 0 && path[0] == '/') |
| Sergunb | 0:8918a71cdbe9 | 209 | path[k++] = '/'; |
| Sergunb | 0:8918a71cdbe9 | 210 | else if(path[i] == '/') |
| Sergunb | 0:8918a71cdbe9 | 211 | path[k++] = '/'; |
| Sergunb | 0:8918a71cdbe9 | 212 | } |
| Sergunb | 0:8918a71cdbe9 | 213 | //No slash separator found? |
| Sergunb | 0:8918a71cdbe9 | 214 | else |
| Sergunb | 0:8918a71cdbe9 | 215 | { |
| Sergunb | 0:8918a71cdbe9 | 216 | if(k == 3 && !strncmp(path, "..", 2)) |
| Sergunb | 0:8918a71cdbe9 | 217 | { |
| Sergunb | 0:8918a71cdbe9 | 218 | path[k++] = '.'; |
| Sergunb | 0:8918a71cdbe9 | 219 | path[k++] = '.'; |
| Sergunb | 0:8918a71cdbe9 | 220 | |
| Sergunb | 0:8918a71cdbe9 | 221 | //Append a slash if necessary |
| Sergunb | 0:8918a71cdbe9 | 222 | if(path[i] == '/') |
| Sergunb | 0:8918a71cdbe9 | 223 | path[k++] = '/'; |
| Sergunb | 0:8918a71cdbe9 | 224 | } |
| Sergunb | 0:8918a71cdbe9 | 225 | else if(path[i] == '\0') |
| Sergunb | 0:8918a71cdbe9 | 226 | { |
| Sergunb | 0:8918a71cdbe9 | 227 | k = 0; |
| Sergunb | 0:8918a71cdbe9 | 228 | path[k++] = '.'; |
| Sergunb | 0:8918a71cdbe9 | 229 | } |
| Sergunb | 0:8918a71cdbe9 | 230 | else if(path[i] == '/' && path[i + 1] == '\0') |
| Sergunb | 0:8918a71cdbe9 | 231 | { |
| Sergunb | 0:8918a71cdbe9 | 232 | k = 0; |
| Sergunb | 0:8918a71cdbe9 | 233 | path[k++] = '.'; |
| Sergunb | 0:8918a71cdbe9 | 234 | path[k++] = '/'; |
| Sergunb | 0:8918a71cdbe9 | 235 | } |
| Sergunb | 0:8918a71cdbe9 | 236 | else |
| Sergunb | 0:8918a71cdbe9 | 237 | { |
| Sergunb | 0:8918a71cdbe9 | 238 | k = 0; |
| Sergunb | 0:8918a71cdbe9 | 239 | } |
| Sergunb | 0:8918a71cdbe9 | 240 | } |
| Sergunb | 0:8918a71cdbe9 | 241 | } |
| Sergunb | 0:8918a71cdbe9 | 242 | } |
| Sergunb | 0:8918a71cdbe9 | 243 | else |
| Sergunb | 0:8918a71cdbe9 | 244 | { |
| Sergunb | 0:8918a71cdbe9 | 245 | //Copy directory name |
| Sergunb | 0:8918a71cdbe9 | 246 | memmove(path + k, path + j, i - j); |
| Sergunb | 0:8918a71cdbe9 | 247 | //Advance write pointer |
| Sergunb | 0:8918a71cdbe9 | 248 | k += i - j; |
| Sergunb | 0:8918a71cdbe9 | 249 | |
| Sergunb | 0:8918a71cdbe9 | 250 | //Append a slash if necessary |
| Sergunb | 0:8918a71cdbe9 | 251 | if(path[i] == '/') |
| Sergunb | 0:8918a71cdbe9 | 252 | path[k++] = '/'; |
| Sergunb | 0:8918a71cdbe9 | 253 | } |
| Sergunb | 0:8918a71cdbe9 | 254 | |
| Sergunb | 0:8918a71cdbe9 | 255 | //Move to the next token |
| Sergunb | 0:8918a71cdbe9 | 256 | while(path[i] == '/') i++; |
| Sergunb | 0:8918a71cdbe9 | 257 | j = i; |
| Sergunb | 0:8918a71cdbe9 | 258 | } |
| Sergunb | 0:8918a71cdbe9 | 259 | } while(path[i++] != '\0'); |
| Sergunb | 0:8918a71cdbe9 | 260 | |
| Sergunb | 0:8918a71cdbe9 | 261 | //Properly terminate the string with a NULL character |
| Sergunb | 0:8918a71cdbe9 | 262 | path[k] = '\0'; |
| Sergunb | 0:8918a71cdbe9 | 263 | } |
| Sergunb | 0:8918a71cdbe9 | 264 | |
| Sergunb | 0:8918a71cdbe9 | 265 | |
| Sergunb | 0:8918a71cdbe9 | 266 | /** |
| Sergunb | 0:8918a71cdbe9 | 267 | * @brief Add a slash to the end of a string |
| Sergunb | 0:8918a71cdbe9 | 268 | * @param[in,out] path NULL-terminated string that represents the path |
| Sergunb | 0:8918a71cdbe9 | 269 | * @param[in] maxLen Maximum pathname length |
| Sergunb | 0:8918a71cdbe9 | 270 | **/ |
| Sergunb | 0:8918a71cdbe9 | 271 | |
| Sergunb | 0:8918a71cdbe9 | 272 | void pathAddSlash(char_t *path, size_t maxLen) |
| Sergunb | 0:8918a71cdbe9 | 273 | { |
| Sergunb | 0:8918a71cdbe9 | 274 | size_t n; |
| Sergunb | 0:8918a71cdbe9 | 275 | |
| Sergunb | 0:8918a71cdbe9 | 276 | //Retrieve the length of the string |
| Sergunb | 0:8918a71cdbe9 | 277 | n = strlen(path); |
| Sergunb | 0:8918a71cdbe9 | 278 | |
| Sergunb | 0:8918a71cdbe9 | 279 | //Add a slash character only if necessary |
| Sergunb | 0:8918a71cdbe9 | 280 | if(!n) |
| Sergunb | 0:8918a71cdbe9 | 281 | { |
| Sergunb | 0:8918a71cdbe9 | 282 | //Check the length of the resulting string |
| Sergunb | 0:8918a71cdbe9 | 283 | if(maxLen >= 1) |
| Sergunb | 0:8918a71cdbe9 | 284 | strcpy(path, "/"); |
| Sergunb | 0:8918a71cdbe9 | 285 | } |
| Sergunb | 0:8918a71cdbe9 | 286 | else if(path[n - 1] != '/' && path[n - 1] != '\\') |
| Sergunb | 0:8918a71cdbe9 | 287 | { |
| Sergunb | 0:8918a71cdbe9 | 288 | //Check the length of the resulting string |
| Sergunb | 0:8918a71cdbe9 | 289 | if(maxLen >= (n + 1)) |
| Sergunb | 0:8918a71cdbe9 | 290 | strcat(path, "/"); |
| Sergunb | 0:8918a71cdbe9 | 291 | } |
| Sergunb | 0:8918a71cdbe9 | 292 | } |
| Sergunb | 0:8918a71cdbe9 | 293 | |
| Sergunb | 0:8918a71cdbe9 | 294 | |
| Sergunb | 0:8918a71cdbe9 | 295 | /** |
| Sergunb | 0:8918a71cdbe9 | 296 | * @brief Remove the trailing slash from a given path |
| Sergunb | 0:8918a71cdbe9 | 297 | * @param[in,out] path NULL-terminated string that contains the path |
| Sergunb | 0:8918a71cdbe9 | 298 | **/ |
| Sergunb | 0:8918a71cdbe9 | 299 | |
| Sergunb | 0:8918a71cdbe9 | 300 | void pathRemoveSlash(char_t *path) |
| Sergunb | 0:8918a71cdbe9 | 301 | { |
| Sergunb | 0:8918a71cdbe9 | 302 | char_t *end; |
| Sergunb | 0:8918a71cdbe9 | 303 | |
| Sergunb | 0:8918a71cdbe9 | 304 | //Skip the leading slash character |
| Sergunb | 0:8918a71cdbe9 | 305 | if(pathIsAbsolute(path)) |
| Sergunb | 0:8918a71cdbe9 | 306 | path++; |
| Sergunb | 0:8918a71cdbe9 | 307 | |
| Sergunb | 0:8918a71cdbe9 | 308 | //Search for the first slash character to be removed |
| Sergunb | 0:8918a71cdbe9 | 309 | for(end = NULL; *path != '\0'; path++) |
| Sergunb | 0:8918a71cdbe9 | 310 | { |
| Sergunb | 0:8918a71cdbe9 | 311 | if(*path != '/' && *path != '\\') |
| Sergunb | 0:8918a71cdbe9 | 312 | end = NULL; |
| Sergunb | 0:8918a71cdbe9 | 313 | else if(!end) |
| Sergunb | 0:8918a71cdbe9 | 314 | end = path; |
| Sergunb | 0:8918a71cdbe9 | 315 | } |
| Sergunb | 0:8918a71cdbe9 | 316 | |
| Sergunb | 0:8918a71cdbe9 | 317 | //Remove the trailing slash characters |
| Sergunb | 0:8918a71cdbe9 | 318 | if(end) *end = '\0'; |
| Sergunb | 0:8918a71cdbe9 | 319 | } |
| Sergunb | 0:8918a71cdbe9 | 320 | |
| Sergunb | 0:8918a71cdbe9 | 321 | |
| Sergunb | 0:8918a71cdbe9 | 322 | /** |
| Sergunb | 0:8918a71cdbe9 | 323 | * @brief Concatenate two paths |
| Sergunb | 0:8918a71cdbe9 | 324 | * @param[in,out] path NULL-terminated string containing the first path |
| Sergunb | 0:8918a71cdbe9 | 325 | * @param[in] more NULL-terminated string containing the second path |
| Sergunb | 0:8918a71cdbe9 | 326 | * @param[in] maxLen Maximum pathname length |
| Sergunb | 0:8918a71cdbe9 | 327 | **/ |
| Sergunb | 0:8918a71cdbe9 | 328 | |
| Sergunb | 0:8918a71cdbe9 | 329 | void pathCombine(char_t *path, const char_t *more, size_t maxLen) |
| Sergunb | 0:8918a71cdbe9 | 330 | { |
| Sergunb | 0:8918a71cdbe9 | 331 | size_t n1; |
| Sergunb | 0:8918a71cdbe9 | 332 | size_t n2; |
| Sergunb | 0:8918a71cdbe9 | 333 | |
| Sergunb | 0:8918a71cdbe9 | 334 | //Append a slash character to the first path |
| Sergunb | 0:8918a71cdbe9 | 335 | if(*path != '\0') |
| Sergunb | 0:8918a71cdbe9 | 336 | pathAddSlash(path, maxLen); |
| Sergunb | 0:8918a71cdbe9 | 337 | |
| Sergunb | 0:8918a71cdbe9 | 338 | //Skip any slash character at the beginning of the second path |
| Sergunb | 0:8918a71cdbe9 | 339 | while(*more == '/' || *more == '\\') more++; |
| Sergunb | 0:8918a71cdbe9 | 340 | |
| Sergunb | 0:8918a71cdbe9 | 341 | //Retrieve the length of the first path |
| Sergunb | 0:8918a71cdbe9 | 342 | n1 = strlen(path); |
| Sergunb | 0:8918a71cdbe9 | 343 | //Retrieve the length of second path |
| Sergunb | 0:8918a71cdbe9 | 344 | n2 = strlen(more); |
| Sergunb | 0:8918a71cdbe9 | 345 | |
| Sergunb | 0:8918a71cdbe9 | 346 | //Check the length of the resulting string |
| Sergunb | 0:8918a71cdbe9 | 347 | if(n1 < maxLen) |
| Sergunb | 0:8918a71cdbe9 | 348 | { |
| Sergunb | 0:8918a71cdbe9 | 349 | //Limit the number of characters to be copied |
| Sergunb | 0:8918a71cdbe9 | 350 | n2 = MIN(n2, maxLen - n1); |
| Sergunb | 0:8918a71cdbe9 | 351 | //Concatenate the resulting string |
| Sergunb | 0:8918a71cdbe9 | 352 | strncpy(path + n1, more, n2); |
| Sergunb | 0:8918a71cdbe9 | 353 | //Properly terminate the string with a NULL character |
| Sergunb | 0:8918a71cdbe9 | 354 | path[n1 + n2] = '\0'; |
| Sergunb | 0:8918a71cdbe9 | 355 | } |
| Sergunb | 0:8918a71cdbe9 | 356 | } |
| Sergunb | 0:8918a71cdbe9 | 357 | |
| Sergunb | 0:8918a71cdbe9 | 358 | |
| Sergunb | 0:8918a71cdbe9 | 359 | /** |
| Sergunb | 0:8918a71cdbe9 | 360 | * @brief Check whether a file name matches the specified pattern |
| Sergunb | 0:8918a71cdbe9 | 361 | * @param[in] path NULL-terminated string that contains the path to be matched |
| Sergunb | 0:8918a71cdbe9 | 362 | * @param[in] pattern NULL-terminated string that contains the pattern for |
| Sergunb | 0:8918a71cdbe9 | 363 | * which to search. The pattern may contain wildcard characters |
| Sergunb | 0:8918a71cdbe9 | 364 | * @return TRUE if the path matches the specified pattern, else FALSE |
| Sergunb | 0:8918a71cdbe9 | 365 | **/ |
| Sergunb | 0:8918a71cdbe9 | 366 | |
| Sergunb | 0:8918a71cdbe9 | 367 | bool_t pathMatch(const char_t *path, const char_t* pattern) |
| Sergunb | 0:8918a71cdbe9 | 368 | { |
| Sergunb | 0:8918a71cdbe9 | 369 | size_t i = 0; |
| Sergunb | 0:8918a71cdbe9 | 370 | size_t j = 0; |
| Sergunb | 0:8918a71cdbe9 | 371 | |
| Sergunb | 0:8918a71cdbe9 | 372 | //Parse the pattern string |
| Sergunb | 0:8918a71cdbe9 | 373 | while(pattern[j] != '\0') |
| Sergunb | 0:8918a71cdbe9 | 374 | { |
| Sergunb | 0:8918a71cdbe9 | 375 | //Any wildcard character found? |
| Sergunb | 0:8918a71cdbe9 | 376 | if(pattern[j] == '?') |
| Sergunb | 0:8918a71cdbe9 | 377 | { |
| Sergunb | 0:8918a71cdbe9 | 378 | //The question mark matches a single character |
| Sergunb | 0:8918a71cdbe9 | 379 | if(path[i] == '\0') |
| Sergunb | 0:8918a71cdbe9 | 380 | { |
| Sergunb | 0:8918a71cdbe9 | 381 | return FALSE; |
| Sergunb | 0:8918a71cdbe9 | 382 | } |
| Sergunb | 0:8918a71cdbe9 | 383 | else |
| Sergunb | 0:8918a71cdbe9 | 384 | { |
| Sergunb | 0:8918a71cdbe9 | 385 | //Advance position in pathname |
| Sergunb | 0:8918a71cdbe9 | 386 | i++; |
| Sergunb | 0:8918a71cdbe9 | 387 | //Advance position in pattern string |
| Sergunb | 0:8918a71cdbe9 | 388 | j++; |
| Sergunb | 0:8918a71cdbe9 | 389 | } |
| Sergunb | 0:8918a71cdbe9 | 390 | } |
| Sergunb | 0:8918a71cdbe9 | 391 | else if(pattern[j] == '*') |
| Sergunb | 0:8918a71cdbe9 | 392 | { |
| Sergunb | 0:8918a71cdbe9 | 393 | //The asterisk sign matches zero or more characters |
| Sergunb | 0:8918a71cdbe9 | 394 | if(path[i] == '\0') |
| Sergunb | 0:8918a71cdbe9 | 395 | { |
| Sergunb | 0:8918a71cdbe9 | 396 | //Advance position in pattern string |
| Sergunb | 0:8918a71cdbe9 | 397 | j++; |
| Sergunb | 0:8918a71cdbe9 | 398 | } |
| Sergunb | 0:8918a71cdbe9 | 399 | else if(pathMatch(path + i, pattern + j + 1)) |
| Sergunb | 0:8918a71cdbe9 | 400 | { |
| Sergunb | 0:8918a71cdbe9 | 401 | return TRUE; |
| Sergunb | 0:8918a71cdbe9 | 402 | } |
| Sergunb | 0:8918a71cdbe9 | 403 | else |
| Sergunb | 0:8918a71cdbe9 | 404 | { |
| Sergunb | 0:8918a71cdbe9 | 405 | //Advance position in pathname |
| Sergunb | 0:8918a71cdbe9 | 406 | i++; |
| Sergunb | 0:8918a71cdbe9 | 407 | } |
| Sergunb | 0:8918a71cdbe9 | 408 | } |
| Sergunb | 0:8918a71cdbe9 | 409 | else |
| Sergunb | 0:8918a71cdbe9 | 410 | { |
| Sergunb | 0:8918a71cdbe9 | 411 | //Case insensitive comparison |
| Sergunb | 0:8918a71cdbe9 | 412 | if(tolower((uint8_t) path[i]) != tolower((uint8_t) pattern[j])) |
| Sergunb | 0:8918a71cdbe9 | 413 | { |
| Sergunb | 0:8918a71cdbe9 | 414 | return FALSE; |
| Sergunb | 0:8918a71cdbe9 | 415 | } |
| Sergunb | 0:8918a71cdbe9 | 416 | else |
| Sergunb | 0:8918a71cdbe9 | 417 | { |
| Sergunb | 0:8918a71cdbe9 | 418 | //Advance position in pathname |
| Sergunb | 0:8918a71cdbe9 | 419 | i++; |
| Sergunb | 0:8918a71cdbe9 | 420 | //Advance position in pattern string |
| Sergunb | 0:8918a71cdbe9 | 421 | j++; |
| Sergunb | 0:8918a71cdbe9 | 422 | } |
| Sergunb | 0:8918a71cdbe9 | 423 | } |
| Sergunb | 0:8918a71cdbe9 | 424 | } |
| Sergunb | 0:8918a71cdbe9 | 425 | |
| Sergunb | 0:8918a71cdbe9 | 426 | //Check whether the file name matches the specified pattern |
| Sergunb | 0:8918a71cdbe9 | 427 | if(path[i] == '\0' && pattern[j] == '\0') |
| Sergunb | 0:8918a71cdbe9 | 428 | return TRUE; |
| Sergunb | 0:8918a71cdbe9 | 429 | else |
| Sergunb | 0:8918a71cdbe9 | 430 | return FALSE; |
| Sergunb | 0:8918a71cdbe9 | 431 | } |
| Sergunb | 0:8918a71cdbe9 | 432 |