GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_directory_default_set.c Lines: 79 79 100.0 %
Date: 2024-01-10 21:53:23 Branches: 58 58 100.0 %

Line Branch Exec Source
1
/**************************************************************************/
2
/*                                                                        */
3
/*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4
/*                                                                        */
5
/*       This software is licensed under the Microsoft Software License   */
6
/*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7
/*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8
/*       and in the root directory of this software.                      */
9
/*                                                                        */
10
/**************************************************************************/
11
12
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** FileX Component                                                       */
17
/**                                                                       */
18
/**   Directory                                                           */
19
/**                                                                       */
20
/**************************************************************************/
21
/**************************************************************************/
22
23
#define FX_SOURCE_CODE
24
25
26
/* Include necessary system files.  */
27
28
#include "fx_api.h"
29
#include "fx_system.h"
30
#include "fx_file.h"
31
#include "fx_utility.h"
32
#include "fx_directory.h"
33
#ifdef FX_ENABLE_EXFAT
34
#include "fx_directory_exFAT.h"
35
#endif /* FX_ENABLE_EXFAT */
36
37
#ifndef FX_NO_LOCAL_PATH
38
FX_LOCAL_PATH_SETUP
39
#endif
40
41
42
/**************************************************************************/
43
/*                                                                        */
44
/*  FUNCTION                                               RELEASE        */
45
/*                                                                        */
46
/*    _fx_directory_default_set                           PORTABLE C      */
47
/*                                                           6.1          */
48
/*  AUTHOR                                                                */
49
/*                                                                        */
50
/*    William E. Lamie, Microsoft Corporation                             */
51
/*                                                                        */
52
/*  DESCRIPTION                                                           */
53
/*                                                                        */
54
/*    This function sets the default directory of the media to the path   */
55
/*    specified by the caller.  If this path is not found, an error code  */
56
/*    is returned.                                                        */
57
/*                                                                        */
58
/*  INPUT                                                                 */
59
/*                                                                        */
60
/*    media_ptr                             Media control block pointer   */
61
/*    new_path_name                         New path to set current       */
62
/*                                            working directory to        */
63
/*                                                                        */
64
/*  OUTPUT                                                                */
65
/*                                                                        */
66
/*    return status                                                       */
67
/*                                                                        */
68
/*  CALLS                                                                 */
69
/*                                                                        */
70
/*    _fx_directory_search                  Search for the directory name */
71
/*                                          in the directory structure    */
72
/*    _fx_utility_absolute_path_get         Get absolute path             */
73
/*                                                                        */
74
/*  CALLED BY                                                             */
75
/*                                                                        */
76
/*    Application Code                                                    */
77
/*                                                                        */
78
/*  RELEASE HISTORY                                                       */
79
/*                                                                        */
80
/*    DATE              NAME                      DESCRIPTION             */
81
/*                                                                        */
82
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
83
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
84
/*                                            resulting in version 6.1    */
85
/*                                                                        */
86
/**************************************************************************/
87
211
UINT  _fx_directory_default_set(FX_MEDIA *media_ptr, CHAR *new_path_name)
88
{
89
90
UINT         status;
91
FX_DIR_ENTRY dir_entry;
92
CHAR        *path_string_ptr;
93
UINT         path_string_capacity;
94
FX_PATH     *path_ptr;
95
UINT         i;
96
97
#ifdef FX_ENABLE_EXFAT
98
CHAR         abs_str[FX_MAXIMUM_PATH]; /* TODO: possible will be better to use dynamic memory for exFAT only.  */
99
#endif /* FX_ENABLE_EXFAT */
100
101
102
#ifndef FX_MEDIA_STATISTICS_DISABLE
103
104
    /* Increment the number of times this service has been called.  */
105
211
    media_ptr -> fx_media_directory_default_sets++;
106
#endif
107
108
    /* Setup pointer to media name buffer.  */
109
211
    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
110
111
    /* Clear the short name string.  */
112
211
    dir_entry.fx_dir_entry_short_name[0] =  0;
113
114
    /* Clear the long name string.  */
115
211
    dir_entry.fx_dir_entry_name[0] =  (CHAR)0;
116
117
    /* Check the media to make sure it is open.  */
118
211
    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
119
    {
120
121
        /* Return the media not opened error.  */
122
1
        return(FX_MEDIA_NOT_OPEN);
123
    }
124
125
    /* If trace is enabled, insert this event into the trace buffer.  */
126
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_DEFAULT_SET, media_ptr, new_path_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
127
128
    /* Protect against other threads accessing the media.  */
129
210
    FX_PROTECT
130
131
    /* Setup the path string pointer to the start of the current path.  */
132
210
    path_string_ptr =  &(media_ptr -> fx_media_default_path.fx_path_string[0]);
133
134
#ifdef FX_ENABLE_EXFAT
135
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
136
    {
137
138
        /* Get the absolute path.  */
139
        if (_fx_utility_absolute_path_get(path_string_ptr, new_path_name, abs_str) == FX_SUCCESS)
140
        {
141
142
            new_path_name = &(abs_str[0]);
143
        }
144
        else
145
        {
146
147
            /* Release media protection.  */
148
            FX_UNPROTECT
149
150
            /* Invalid Path - Return the error code.  */
151
            return(FX_INVALID_PATH);
152
        }
153
    }
154
#endif /* FX_ENABLE_EXFAT */
155
156
    /* Look for a root directory selection.  */
157


210
    if ((!new_path_name) || (((new_path_name[0] == '\\') || (new_path_name[0] == '/')) && (new_path_name[1] == (CHAR)0)))
158
    {
159
160
        /* Set the media current working directory to the root.  */
161
11
        media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0] =  (CHAR) 0;
162
11
        media_ptr -> fx_media_default_path.fx_path_string[0] =                       (CHAR) 0;
163
11
        media_ptr -> fx_media_default_path.fx_path_string[FX_MAXIMUM_PATH - 2] =     (CHAR) 0;
164
    }
165
    else
166
    {
167
168
        /* Search the system for the supplied path and directory name.  */
169
199
        status =  _fx_directory_search(media_ptr, new_path_name, &dir_entry, FX_NULL, FX_NULL);
170
171
        /* Determine if the search failed or if the entry found is not a
172
           directory.  */
173

199
        if ((status != FX_SUCCESS) || (!(dir_entry.fx_dir_entry_attributes & FX_DIRECTORY)))
174
        {
175
176
            /* Release media protection.  */
177
2
            FX_UNPROTECT
178
179
            /* Invalid Path - Return the error code.  */
180
2
            return(FX_INVALID_PATH);
181
        }
182
183
        /* Now update the current path string.  */
184
185
        /* Setup the path string's capacity.  */
186
197
        path_string_capacity =  FX_MAXIMUM_PATH - 1;
187
188
        /* Determine if the new path is relative from the current path.  */
189

197
        if ((new_path_name[0] != '\\') && (new_path_name[0] != '/'))
190
        {
191
192
            /* Yes, a relative path was found.  */
193
194
            /* First check for a local path pointer stored in the thread control block.
195
               This is only available in ThreadX Version 4 and above.  */
196
#ifndef FX_NO_LOCAL_PATH
197
173
            if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
198
            {
199
200
            CHAR *saved_name_ptr;
201
202
                /* First, save the name pointer of the default path.  */
203
1
                saved_name_ptr =  media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name;
204
205
                /* Setup the default path pointer to the local path.  */
206
1
                path_ptr =  (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
207
208
                /* Copy the local path to the default path.  */
209
1
                media_ptr -> fx_media_default_path =  *path_ptr;
210
211
                /* Restore the name pointer of the default path.  */
212
1
                media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name =  saved_name_ptr;
213
214
                /* Set the path pointer to the default pointer.  */
215
1
                path_ptr =  &media_ptr -> fx_media_default_path;
216
            }
217
            else
218
            {
219
220
                /* Setup the default path to the global media path.  */
221
172
                path_ptr =  &media_ptr -> fx_media_default_path;
222
            }
223
#else
224
225
            /* Setup the default path to the global media path.  */
226
            path_ptr =  &media_ptr -> fx_media_default_path;
227
#endif
228
229
            /* First, check the current path for string overflow.  If this is set,
230
               don't attempt to update the current path with relative information.
231
               The path won't be valid again until a complete path is given.  */
232
173
            if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
233
            {
234
235
                /* Yes, don't update the string, just finish the path set processing.  */
236
237
                /* Determine if we are at the root directory.  */
238
57
                if (!dir_entry.fx_dir_entry_cluster)
239
                {
240
                    /* Set the current directory back to the root directory.  */
241
4
                    path_ptr -> fx_path_directory.fx_dir_entry_name[0] =  (CHAR) 0;
242
243
                    /* Set name to NULL.  */
244
4
                    dir_entry.fx_dir_entry_name[0] =  (CHAR) 0;
245
246
                    /* Clear the current path string.  */
247
4
                    path_ptr -> fx_path_string[0] =  (CHAR)0;
248
249
                    /* Clear the overflow flag in the current path string... just in
250
                       case! */
251
4
                    path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] =  (CHAR)0;
252
                }
253
254
                /* Copy the new directory entry into the media control block.  */
255
57
                path_ptr -> fx_path_directory =  dir_entry;
256
257
                /* Copy the name into the path name buffer.  */
258
784
                for (i = 0; dir_entry.fx_dir_entry_name[i]; i++)
259
                {
260
727
                    path_ptr -> fx_path_name_buffer[i] =  dir_entry.fx_dir_entry_name[i];
261
                }
262
263
                /* Reassign the pointer.  */
264
57
                path_ptr -> fx_path_directory.fx_dir_entry_name =  path_ptr -> fx_path_name_buffer;
265
266
                /* Release media protection.  */
267
57
                FX_UNPROTECT
268
269
                /* Default directory set is complete, return status.  */
270
57
                return(FX_SUCCESS);
271
            }
272
273
            /* Move the current path starting pointer to the end of the current
274
               path string.  */
275

11640
            while ((path_string_capacity) && (*path_string_ptr != FX_NULL))
276
            {
277
11524
                path_string_ptr++;
278
11524
                path_string_capacity--;
279
            }
280
281
            /* If room, place the \ character in the path string.  */
282
116
            if (path_string_capacity)
283
            {
284
285
                /* There is room, place the directory marker in the string.  */
286
115
                *path_string_ptr++ =  '\\';
287
115
                path_string_capacity--;
288
            }
289
        }
290
        else
291
        {
292
293
            /* Setup the default path pointer.  */
294
295
            /* First check for a local path pointer stored in the thread control block.
296
               This is only available in ThreadX Version 4 and above.  */
297
#ifndef FX_NO_LOCAL_PATH
298
24
            if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
299
            {
300
301
            CHAR *saved_name_ptr;
302
303
                /* First, save the name pointer of the default path.  */
304
1
                saved_name_ptr =  media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name;
305
306
                /* Setup the default path pointer to the local path.  */
307
1
                path_ptr =  (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
308
309
                /* Copy the local path to the default path.  */
310
1
                media_ptr -> fx_media_default_path =  *path_ptr;
311
312
                /* Restore the name pointer of the default path.  */
313
1
                media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name =  saved_name_ptr;
314
315
                /* Set the path pointer to the default pointer.  */
316
1
                path_ptr =  &media_ptr -> fx_media_default_path;
317
            }
318
            else
319
            {
320
321
                /* Setup the default path to the global media path.  */
322
23
                path_ptr =  &media_ptr -> fx_media_default_path;
323
            }
324
#else
325
326
            /* Setup the default path to the global media path.  */
327
            path_ptr =  &media_ptr -> fx_media_default_path;
328
#endif
329
330
            /* Complete path name given.  Check to see if we need to clear an
331
               overflow character from a previous current path string update.  */
332
24
            if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
333
            {
334
2
                path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
335
            }
336
        }
337
338
        /* Copy what we can into the current path.  */
339
3143
        while (*new_path_name)
340
        {
341
342
            /* Determine if there is a ".." character sequence that specifies the
343
               previous path.  */
344

3012
            if ((*new_path_name == '.') && (*(new_path_name + 1) == '.'))
345
            {
346
347
                /* Yes, a backward path is found.  The current path pointer
348
                   must be moved back to just after the previous \ character.  */
349
350
                /* Skip the current \0 that is at the end of the current path.  */
351
4
                path_string_capacity =  path_string_capacity + 2;
352
4
                path_string_ptr =       path_string_ptr - 2;
353
354
75
                while (path_string_capacity <= (FX_MAXIMUM_PATH - 1))
355
                {
356
357
                    /* Move the current path pointer backwards until
358
                       a \ character is found.  */
359
360

73
                    if ((*path_string_ptr == '\\') || (*path_string_ptr == '/'))
361
                    {
362
363
                        /* Yes, we have successfully backed up one directory.  */
364
                        break;
365
                    }
366
367
                    /* Backup another character.  */
368
71
                    path_string_capacity++;
369
71
                    path_string_ptr--;
370
                }
371
372
                /* Adjust the new directory pointer past the .. characters  */
373
4
                new_path_name =  new_path_name + 2;
374
            }
375
            else
376
            {
377
378
                /* Normal characters that need to be copied into the current path.  */
379
380
3008
                if (path_string_capacity)
381
                {
382
383
                    /* Copy character from the new path into the current path string.  */
384
2999
                    *path_string_ptr++ =  *new_path_name++;
385
386
2999
                    path_string_capacity--;
387
                }
388
                else
389
                {
390
391
                    /* No more room in the current path string!  */
392
9
                    break;
393
                }
394
            }
395
        }
396
397
        /* Determine if there is still room in the current path string.  */
398
140
        if (path_string_capacity)
399
        {
400
401
            /* Yes, there is still room, place a NULL character at the
402
               end of the path.  */
403
129
            *path_string_ptr =  (CHAR)FX_NULL;
404
        }
405
        else
406
        {
407
408
            /* No more room.  Determine if the entire path was successfully
409
               copied into the current path.  */
410
11
            if (*new_path_name)
411
            {
412
413
                /* No, we couldn't fit the entire path.  Place a "*" character
414
                   at the end to indicate that we had overflow.  Note that
415
                   the path is kept just the the directory default get call, so
416
                   the new default path is valid.  */
417
9
                path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] =  '*';
418
            }
419
        }
420
421
        /* Determine if we are at the root directory.  */
422
#ifdef FX_ENABLE_EXFAT
423
        if ((!dir_entry.fx_dir_entry_cluster) && (media_ptr -> fx_media_FAT_type != FX_exFAT))
424
#else
425
140
        if (!dir_entry.fx_dir_entry_cluster)
426
#endif
427
        {
428
429
            /* Set the current directory back to the root directory.  */
430
2
            dir_entry.fx_dir_entry_name[0] =      (CHAR)0;
431
2
            path_ptr -> fx_path_name_buffer[0] =  (CHAR)0;
432
        }
433
434
        /* Copy the new directory entry into the media control block.  */
435
140
        path_ptr -> fx_path_directory =  dir_entry;
436
437
        /* Copy the name.  */
438
2923
        for (i = 0; dir_entry.fx_dir_entry_name[i]; i++)
439
        {
440
2783
            path_ptr -> fx_path_name_buffer[i] =  dir_entry.fx_dir_entry_name[i];
441
        }
442
443
        /* Reassign the pointer.  */
444
140
        path_ptr -> fx_path_directory.fx_dir_entry_name =  path_ptr -> fx_path_name_buffer;
445
    }
446
447
    /* Release media protection.  */
448
151
    FX_UNPROTECT
449
450
    /* Default directory set is complete, return status.  */
451
151
    return(FX_SUCCESS);
452
}
453