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