GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_directory_default_set.c Lines: 79 79 100.0 %
Date: 2026-03-06 18:49:02 Branches: 58 58 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present Eclipse ThreadX contributors
4
 *
5
 * This program and the accompanying materials are made available under the
6
 * terms of the MIT License which is available at
7
 * https://opensource.org/licenses/MIT.
8
 *
9
 * SPDX-License-Identifier: MIT
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
34
#ifndef FX_NO_LOCAL_PATH
35
FX_LOCAL_PATH_SETUP
36
#endif
37
38
39
/**************************************************************************/
40
/*                                                                        */
41
/*  FUNCTION                                               RELEASE        */
42
/*                                                                        */
43
/*    _fx_directory_default_set                           PORTABLE C      */
44
/*                                                           6.1          */
45
/*  AUTHOR                                                                */
46
/*                                                                        */
47
/*    William E. Lamie, Microsoft Corporation                             */
48
/*                                                                        */
49
/*  DESCRIPTION                                                           */
50
/*                                                                        */
51
/*    This function sets the default directory of the media to the path   */
52
/*    specified by the caller.  If this path is not found, an error code  */
53
/*    is returned.                                                        */
54
/*                                                                        */
55
/*  INPUT                                                                 */
56
/*                                                                        */
57
/*    media_ptr                             Media control block pointer   */
58
/*    new_path_name                         New path to set current       */
59
/*                                            working directory to        */
60
/*                                                                        */
61
/*  OUTPUT                                                                */
62
/*                                                                        */
63
/*    return status                                                       */
64
/*                                                                        */
65
/*  CALLS                                                                 */
66
/*                                                                        */
67
/*    _fx_directory_search                  Search for the directory name */
68
/*                                          in the directory structure    */
69
/*    _fx_utility_absolute_path_get         Get absolute path             */
70
/*                                                                        */
71
/*  CALLED BY                                                             */
72
/*                                                                        */
73
/*    Application Code                                                    */
74
/*                                                                        */
75
/**************************************************************************/
76
211
UINT  _fx_directory_default_set(FX_MEDIA *media_ptr, CHAR *new_path_name)
77
{
78
79
UINT         status;
80
FX_DIR_ENTRY dir_entry;
81
CHAR        *path_string_ptr;
82
UINT         path_string_capacity;
83
FX_PATH     *path_ptr;
84
UINT         i;
85
86
87
88
#ifndef FX_MEDIA_STATISTICS_DISABLE
89
90
    /* Increment the number of times this service has been called.  */
91
211
    media_ptr -> fx_media_directory_default_sets++;
92
#endif
93
94
    /* Setup pointer to media name buffer.  */
95
211
    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
96
97
    /* Clear the short name string.  */
98
211
    dir_entry.fx_dir_entry_short_name[0] =  0;
99
100
    /* Clear the long name string.  */
101
211
    dir_entry.fx_dir_entry_name[0] =  (CHAR)0;
102
103
    /* Check the media to make sure it is open.  */
104
211
    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
105
    {
106
107
        /* Return the media not opened error.  */
108
1
        return(FX_MEDIA_NOT_OPEN);
109
    }
110
111
    /* If trace is enabled, insert this event into the trace buffer.  */
112
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_DEFAULT_SET, media_ptr, new_path_name, 0, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
113
114
    /* Protect against other threads accessing the media.  */
115
210
    FX_PROTECT
116
117
    /* Setup the path string pointer to the start of the current path.  */
118
210
    path_string_ptr =  &(media_ptr -> fx_media_default_path.fx_path_string[0]);
119
120
121
    /* Look for a root directory selection.  */
122


210
    if ((!new_path_name) || (((new_path_name[0] == '\\') || (new_path_name[0] == '/')) && (new_path_name[1] == (CHAR)0)))
123
    {
124
125
        /* Set the media current working directory to the root.  */
126
11
        media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0] =  (CHAR) 0;
127
11
        media_ptr -> fx_media_default_path.fx_path_string[0] =                       (CHAR) 0;
128
11
        media_ptr -> fx_media_default_path.fx_path_string[FX_MAXIMUM_PATH - 2] =     (CHAR) 0;
129
    }
130
    else
131
    {
132
133
        /* Search the system for the supplied path and directory name.  */
134
199
        status =  _fx_directory_search(media_ptr, new_path_name, &dir_entry, FX_NULL, FX_NULL);
135
136
        /* Determine if the search failed or if the entry found is not a
137
           directory.  */
138

199
        if ((status != FX_SUCCESS) || (!(dir_entry.fx_dir_entry_attributes & FX_DIRECTORY)))
139
        {
140
141
            /* Release media protection.  */
142
2
            FX_UNPROTECT
143
144
            /* Invalid Path - Return the error code.  */
145
2
            return(FX_INVALID_PATH);
146
        }
147
148
        /* Now update the current path string.  */
149
150
        /* Setup the path string's capacity.  */
151
197
        path_string_capacity =  FX_MAXIMUM_PATH - 1;
152
153
        /* Determine if the new path is relative from the current path.  */
154

197
        if ((new_path_name[0] != '\\') && (new_path_name[0] != '/'))
155
        {
156
157
            /* Yes, a relative path was found.  */
158
159
            /* First check for a local path pointer stored in the thread control block.
160
               This is only available in ThreadX Version 4 and above.  */
161
#ifndef FX_NO_LOCAL_PATH
162
173
            if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
163
            {
164
165
            CHAR *saved_name_ptr;
166
167
                /* First, save the name pointer of the default path.  */
168
1
                saved_name_ptr =  media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name;
169
170
                /* Setup the default path pointer to the local path.  */
171
1
                path_ptr =  (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
172
173
                /* Copy the local path to the default path.  */
174
1
                media_ptr -> fx_media_default_path =  *path_ptr;
175
176
                /* Restore the name pointer of the default path.  */
177
1
                media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name =  saved_name_ptr;
178
179
                /* Set the path pointer to the default pointer.  */
180
1
                path_ptr =  &media_ptr -> fx_media_default_path;
181
            }
182
            else
183
            {
184
185
                /* Setup the default path to the global media path.  */
186
172
                path_ptr =  &media_ptr -> fx_media_default_path;
187
            }
188
#else
189
190
            /* Setup the default path to the global media path.  */
191
            path_ptr =  &media_ptr -> fx_media_default_path;
192
#endif
193
194
            /* First, check the current path for string overflow.  If this is set,
195
               don't attempt to update the current path with relative information.
196
               The path won't be valid again until a complete path is given.  */
197
173
            if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
198
            {
199
200
                /* Yes, don't update the string, just finish the path set processing.  */
201
202
                /* Determine if we are at the root directory.  */
203
57
                if (!dir_entry.fx_dir_entry_cluster)
204
                {
205
                    /* Set the current directory back to the root directory.  */
206
4
                    path_ptr -> fx_path_directory.fx_dir_entry_name[0] =  (CHAR) 0;
207
208
                    /* Set name to NULL.  */
209
4
                    dir_entry.fx_dir_entry_name[0] =  (CHAR) 0;
210
211
                    /* Clear the current path string.  */
212
4
                    path_ptr -> fx_path_string[0] =  (CHAR)0;
213
214
                    /* Clear the overflow flag in the current path string... just in
215
                       case! */
216
4
                    path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] =  (CHAR)0;
217
                }
218
219
                /* Copy the new directory entry into the media control block.  */
220
57
                path_ptr -> fx_path_directory =  dir_entry;
221
222
                /* Copy the name into the path name buffer.  */
223
784
                for (i = 0; dir_entry.fx_dir_entry_name[i]; i++)
224
                {
225
727
                    path_ptr -> fx_path_name_buffer[i] =  dir_entry.fx_dir_entry_name[i];
226
                }
227
228
                /* Reassign the pointer.  */
229
57
                path_ptr -> fx_path_directory.fx_dir_entry_name =  path_ptr -> fx_path_name_buffer;
230
231
                /* Release media protection.  */
232
57
                FX_UNPROTECT
233
234
                /* Default directory set is complete, return status.  */
235
57
                return(FX_SUCCESS);
236
            }
237
238
            /* Move the current path starting pointer to the end of the current
239
               path string.  */
240

11640
            while ((path_string_capacity) && (*path_string_ptr != FX_NULL))
241
            {
242
11524
                path_string_ptr++;
243
11524
                path_string_capacity--;
244
            }
245
246
            /* If room, place the \ character in the path string.  */
247
116
            if (path_string_capacity)
248
            {
249
250
                /* There is room, place the directory marker in the string.  */
251
115
                *path_string_ptr++ =  '\\';
252
115
                path_string_capacity--;
253
            }
254
        }
255
        else
256
        {
257
258
            /* Setup the default path pointer.  */
259
260
            /* First check for a local path pointer stored in the thread control block.
261
               This is only available in ThreadX Version 4 and above.  */
262
#ifndef FX_NO_LOCAL_PATH
263
24
            if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
264
            {
265
266
            CHAR *saved_name_ptr;
267
268
                /* First, save the name pointer of the default path.  */
269
1
                saved_name_ptr =  media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name;
270
271
                /* Setup the default path pointer to the local path.  */
272
1
                path_ptr =  (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
273
274
                /* Copy the local path to the default path.  */
275
1
                media_ptr -> fx_media_default_path =  *path_ptr;
276
277
                /* Restore the name pointer of the default path.  */
278
1
                media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name =  saved_name_ptr;
279
280
                /* Set the path pointer to the default pointer.  */
281
1
                path_ptr =  &media_ptr -> fx_media_default_path;
282
            }
283
            else
284
            {
285
286
                /* Setup the default path to the global media path.  */
287
23
                path_ptr =  &media_ptr -> fx_media_default_path;
288
            }
289
#else
290
291
            /* Setup the default path to the global media path.  */
292
            path_ptr =  &media_ptr -> fx_media_default_path;
293
#endif
294
295
            /* Complete path name given.  Check to see if we need to clear an
296
               overflow character from a previous current path string update.  */
297
24
            if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
298
            {
299
2
                path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
300
            }
301
        }
302
303
        /* Copy what we can into the current path.  */
304
3143
        while (*new_path_name)
305
        {
306
307
            /* Determine if there is a ".." character sequence that specifies the
308
               previous path.  */
309

3012
            if ((*new_path_name == '.') && (*(new_path_name + 1) == '.'))
310
            {
311
312
                /* Yes, a backward path is found.  The current path pointer
313
                   must be moved back to just after the previous \ character.  */
314
315
                /* Skip the current \0 that is at the end of the current path.  */
316
4
                path_string_capacity =  path_string_capacity + 2;
317
4
                path_string_ptr =       path_string_ptr - 2;
318
319
75
                while (path_string_capacity <= (FX_MAXIMUM_PATH - 1))
320
                {
321
322
                    /* Move the current path pointer backwards until
323
                       a \ character is found.  */
324
325

73
                    if ((*path_string_ptr == '\\') || (*path_string_ptr == '/'))
326
                    {
327
328
                        /* Yes, we have successfully backed up one directory.  */
329
                        break;
330
                    }
331
332
                    /* Backup another character.  */
333
71
                    path_string_capacity++;
334
71
                    path_string_ptr--;
335
                }
336
337
                /* Adjust the new directory pointer past the .. characters  */
338
4
                new_path_name =  new_path_name + 2;
339
            }
340
            else
341
            {
342
343
                /* Normal characters that need to be copied into the current path.  */
344
345
3008
                if (path_string_capacity)
346
                {
347
348
                    /* Copy character from the new path into the current path string.  */
349
2999
                    *path_string_ptr++ =  *new_path_name++;
350
351
2999
                    path_string_capacity--;
352
                }
353
                else
354
                {
355
356
                    /* No more room in the current path string!  */
357
9
                    break;
358
                }
359
            }
360
        }
361
362
        /* Determine if there is still room in the current path string.  */
363
140
        if (path_string_capacity)
364
        {
365
366
            /* Yes, there is still room, place a NULL character at the
367
               end of the path.  */
368
129
            *path_string_ptr =  (CHAR)FX_NULL;
369
        }
370
        else
371
        {
372
373
            /* No more room.  Determine if the entire path was successfully
374
               copied into the current path.  */
375
11
            if (*new_path_name)
376
            {
377
378
                /* No, we couldn't fit the entire path.  Place a "*" character
379
                   at the end to indicate that we had overflow.  Note that
380
                   the path is kept just the the directory default get call, so
381
                   the new default path is valid.  */
382
9
                path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] =  '*';
383
            }
384
        }
385
386
        /* Determine if we are at the root directory.  */
387
140
        if (!dir_entry.fx_dir_entry_cluster)
388
        {
389
390
            /* Set the current directory back to the root directory.  */
391
2
            dir_entry.fx_dir_entry_name[0] =      (CHAR)0;
392
2
            path_ptr -> fx_path_name_buffer[0] =  (CHAR)0;
393
        }
394
395
        /* Copy the new directory entry into the media control block.  */
396
140
        path_ptr -> fx_path_directory =  dir_entry;
397
398
        /* Copy the name.  */
399
2923
        for (i = 0; dir_entry.fx_dir_entry_name[i]; i++)
400
        {
401
2783
            path_ptr -> fx_path_name_buffer[i] =  dir_entry.fx_dir_entry_name[i];
402
        }
403
404
        /* Reassign the pointer.  */
405
140
        path_ptr -> fx_path_directory.fx_dir_entry_name =  path_ptr -> fx_path_name_buffer;
406
    }
407
408
    /* Release media protection.  */
409
151
    FX_UNPROTECT
410
411
    /* Default directory set is complete, return status.  */
412
151
    return(FX_SUCCESS);
413
}
414