1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** FileX Component */
16 /** */
17 /** Directory */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define FX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "fx_api.h"
28 #include "fx_system.h"
29 #include "fx_file.h"
30 #include "fx_utility.h"
31 #include "fx_directory.h"
32
33 #ifndef FX_NO_LOCAL_PATH
34 FX_LOCAL_PATH_SETUP
35 #endif
36
37
38 /**************************************************************************/
39 /* */
40 /* FUNCTION RELEASE */
41 /* */
42 /* _fx_directory_default_set PORTABLE C */
43 /* 6.1 */
44 /* AUTHOR */
45 /* */
46 /* William E. Lamie, Microsoft Corporation */
47 /* */
48 /* DESCRIPTION */
49 /* */
50 /* This function sets the default directory of the media to the path */
51 /* specified by the caller. If this path is not found, an error code */
52 /* is returned. */
53 /* */
54 /* INPUT */
55 /* */
56 /* media_ptr Media control block pointer */
57 /* new_path_name New path to set current */
58 /* working directory to */
59 /* */
60 /* OUTPUT */
61 /* */
62 /* return status */
63 /* */
64 /* CALLS */
65 /* */
66 /* _fx_directory_search Search for the directory name */
67 /* in the directory structure */
68 /* _fx_utility_absolute_path_get Get absolute path */
69 /* */
70 /* CALLED BY */
71 /* */
72 /* Application Code */
73 /* */
74 /* RELEASE HISTORY */
75 /* */
76 /* DATE NAME DESCRIPTION */
77 /* */
78 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
79 /* 09-30-2020 William E. Lamie Modified comment(s), */
80 /* resulting in version 6.1 */
81 /* */
82 /**************************************************************************/
_fx_directory_default_set(FX_MEDIA * media_ptr,CHAR * new_path_name)83 UINT _fx_directory_default_set(FX_MEDIA *media_ptr, CHAR *new_path_name)
84 {
85
86 UINT status;
87 FX_DIR_ENTRY dir_entry;
88 CHAR *path_string_ptr;
89 UINT path_string_capacity;
90 FX_PATH *path_ptr;
91 UINT i;
92
93
94
95 #ifndef FX_MEDIA_STATISTICS_DISABLE
96
97 /* Increment the number of times this service has been called. */
98 media_ptr -> fx_media_directory_default_sets++;
99 #endif
100
101 /* Setup pointer to media name buffer. */
102 dir_entry.fx_dir_entry_name = media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
103
104 /* Clear the short name string. */
105 dir_entry.fx_dir_entry_short_name[0] = 0;
106
107 /* Clear the long name string. */
108 dir_entry.fx_dir_entry_name[0] = (CHAR)0;
109
110 /* Check the media to make sure it is open. */
111 if (media_ptr -> fx_media_id != FX_MEDIA_ID)
112 {
113
114 /* Return the media not opened error. */
115 return(FX_MEDIA_NOT_OPEN);
116 }
117
118 /* If trace is enabled, insert this event into the trace buffer. */
119 FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_DEFAULT_SET, media_ptr, new_path_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
120
121 /* Protect against other threads accessing the media. */
122 FX_PROTECT
123
124 /* Setup the path string pointer to the start of the current path. */
125 path_string_ptr = &(media_ptr -> fx_media_default_path.fx_path_string[0]);
126
127
128 /* Look for a root directory selection. */
129 if ((!new_path_name) || (((new_path_name[0] == '\\') || (new_path_name[0] == '/')) && (new_path_name[1] == (CHAR)0)))
130 {
131
132 /* Set the media current working directory to the root. */
133 media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0] = (CHAR) 0;
134 media_ptr -> fx_media_default_path.fx_path_string[0] = (CHAR) 0;
135 media_ptr -> fx_media_default_path.fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR) 0;
136 }
137 else
138 {
139
140 /* Search the system for the supplied path and directory name. */
141 status = _fx_directory_search(media_ptr, new_path_name, &dir_entry, FX_NULL, FX_NULL);
142
143 /* Determine if the search failed or if the entry found is not a
144 directory. */
145 if ((status != FX_SUCCESS) || (!(dir_entry.fx_dir_entry_attributes & FX_DIRECTORY)))
146 {
147
148 /* Release media protection. */
149 FX_UNPROTECT
150
151 /* Invalid Path - Return the error code. */
152 return(FX_INVALID_PATH);
153 }
154
155 /* Now update the current path string. */
156
157 /* Setup the path string's capacity. */
158 path_string_capacity = FX_MAXIMUM_PATH - 1;
159
160 /* Determine if the new path is relative from the current path. */
161 if ((new_path_name[0] != '\\') && (new_path_name[0] != '/'))
162 {
163
164 /* Yes, a relative path was found. */
165
166 /* First check for a local path pointer stored in the thread control block.
167 This is only available in ThreadX Version 4 and above. */
168 #ifndef FX_NO_LOCAL_PATH
169 if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
170 {
171
172 CHAR *saved_name_ptr;
173
174 /* First, save the name pointer of the default path. */
175 saved_name_ptr = media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name;
176
177 /* Setup the default path pointer to the local path. */
178 path_ptr = (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
179
180 /* Copy the local path to the default path. */
181 media_ptr -> fx_media_default_path = *path_ptr;
182
183 /* Restore the name pointer of the default path. */
184 media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name = saved_name_ptr;
185
186 /* Set the path pointer to the default pointer. */
187 path_ptr = &media_ptr -> fx_media_default_path;
188 }
189 else
190 {
191
192 /* Setup the default path to the global media path. */
193 path_ptr = &media_ptr -> fx_media_default_path;
194 }
195 #else
196
197 /* Setup the default path to the global media path. */
198 path_ptr = &media_ptr -> fx_media_default_path;
199 #endif
200
201 /* First, check the current path for string overflow. If this is set,
202 don't attempt to update the current path with relative information.
203 The path won't be valid again until a complete path is given. */
204 if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
205 {
206
207 /* Yes, don't update the string, just finish the path set processing. */
208
209 /* Determine if we are at the root directory. */
210 if (!dir_entry.fx_dir_entry_cluster)
211 {
212 /* Set the current directory back to the root directory. */
213 path_ptr -> fx_path_directory.fx_dir_entry_name[0] = (CHAR) 0;
214
215 /* Set name to NULL. */
216 dir_entry.fx_dir_entry_name[0] = (CHAR) 0;
217
218 /* Clear the current path string. */
219 path_ptr -> fx_path_string[0] = (CHAR)0;
220
221 /* Clear the overflow flag in the current path string... just in
222 case! */
223 path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
224 }
225
226 /* Copy the new directory entry into the media control block. */
227 path_ptr -> fx_path_directory = dir_entry;
228
229 /* Copy the name into the path name buffer. */
230 for (i = 0; dir_entry.fx_dir_entry_name[i]; i++)
231 {
232 path_ptr -> fx_path_name_buffer[i] = dir_entry.fx_dir_entry_name[i];
233 }
234
235 /* Reassign the pointer. */
236 path_ptr -> fx_path_directory.fx_dir_entry_name = path_ptr -> fx_path_name_buffer;
237
238 /* Release media protection. */
239 FX_UNPROTECT
240
241 /* Default directory set is complete, return status. */
242 return(FX_SUCCESS);
243 }
244
245 /* Move the current path starting pointer to the end of the current
246 path string. */
247 while ((path_string_capacity) && (*path_string_ptr != FX_NULL))
248 {
249 path_string_ptr++;
250 path_string_capacity--;
251 }
252
253 /* If room, place the \ character in the path string. */
254 if (path_string_capacity)
255 {
256
257 /* There is room, place the directory marker in the string. */
258 *path_string_ptr++ = '\\';
259 path_string_capacity--;
260 }
261 }
262 else
263 {
264
265 /* Setup the default path pointer. */
266
267 /* First check for a local path pointer stored in the thread control block.
268 This is only available in ThreadX Version 4 and above. */
269 #ifndef FX_NO_LOCAL_PATH
270 if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
271 {
272
273 CHAR *saved_name_ptr;
274
275 /* First, save the name pointer of the default path. */
276 saved_name_ptr = media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name;
277
278 /* Setup the default path pointer to the local path. */
279 path_ptr = (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
280
281 /* Copy the local path to the default path. */
282 media_ptr -> fx_media_default_path = *path_ptr;
283
284 /* Restore the name pointer of the default path. */
285 media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name = saved_name_ptr;
286
287 /* Set the path pointer to the default pointer. */
288 path_ptr = &media_ptr -> fx_media_default_path;
289 }
290 else
291 {
292
293 /* Setup the default path to the global media path. */
294 path_ptr = &media_ptr -> fx_media_default_path;
295 }
296 #else
297
298 /* Setup the default path to the global media path. */
299 path_ptr = &media_ptr -> fx_media_default_path;
300 #endif
301
302 /* Complete path name given. Check to see if we need to clear an
303 overflow character from a previous current path string update. */
304 if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
305 {
306 path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
307 }
308 }
309
310 /* Copy what we can into the current path. */
311 while (*new_path_name)
312 {
313
314 /* Determine if there is a ".." character sequence that specifies the
315 previous path. */
316 if ((*new_path_name == '.') && (*(new_path_name + 1) == '.'))
317 {
318
319 /* Yes, a backward path is found. The current path pointer
320 must be moved back to just after the previous \ character. */
321
322 /* Skip the current \0 that is at the end of the current path. */
323 path_string_capacity = path_string_capacity + 2;
324 path_string_ptr = path_string_ptr - 2;
325
326 while (path_string_capacity <= (FX_MAXIMUM_PATH - 1))
327 {
328
329 /* Move the current path pointer backwards until
330 a \ character is found. */
331
332 if ((*path_string_ptr == '\\') || (*path_string_ptr == '/'))
333 {
334
335 /* Yes, we have successfully backed up one directory. */
336 break;
337 }
338
339 /* Backup another character. */
340 path_string_capacity++;
341 path_string_ptr--;
342 }
343
344 /* Adjust the new directory pointer past the .. characters */
345 new_path_name = new_path_name + 2;
346 }
347 else
348 {
349
350 /* Normal characters that need to be copied into the current path. */
351
352 if (path_string_capacity)
353 {
354
355 /* Copy character from the new path into the current path string. */
356 *path_string_ptr++ = *new_path_name++;
357
358 path_string_capacity--;
359 }
360 else
361 {
362
363 /* No more room in the current path string! */
364 break;
365 }
366 }
367 }
368
369 /* Determine if there is still room in the current path string. */
370 if (path_string_capacity)
371 {
372
373 /* Yes, there is still room, place a NULL character at the
374 end of the path. */
375 *path_string_ptr = (CHAR)FX_NULL;
376 }
377 else
378 {
379
380 /* No more room. Determine if the entire path was successfully
381 copied into the current path. */
382 if (*new_path_name)
383 {
384
385 /* No, we couldn't fit the entire path. Place a "*" character
386 at the end to indicate that we had overflow. Note that
387 the path is kept just the the directory default get call, so
388 the new default path is valid. */
389 path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = '*';
390 }
391 }
392
393 /* Determine if we are at the root directory. */
394 if (!dir_entry.fx_dir_entry_cluster)
395 {
396
397 /* Set the current directory back to the root directory. */
398 dir_entry.fx_dir_entry_name[0] = (CHAR)0;
399 path_ptr -> fx_path_name_buffer[0] = (CHAR)0;
400 }
401
402 /* Copy the new directory entry into the media control block. */
403 path_ptr -> fx_path_directory = dir_entry;
404
405 /* Copy the name. */
406 for (i = 0; dir_entry.fx_dir_entry_name[i]; i++)
407 {
408 path_ptr -> fx_path_name_buffer[i] = dir_entry.fx_dir_entry_name[i];
409 }
410
411 /* Reassign the pointer. */
412 path_ptr -> fx_path_directory.fx_dir_entry_name = path_ptr -> fx_path_name_buffer;
413 }
414
415 /* Release media protection. */
416 FX_UNPROTECT
417
418 /* Default directory set is complete, return status. */
419 return(FX_SUCCESS);
420 }
421
422