GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_directory_default_set.c Lines: 79 79 100.0 %
Date: 2024-03-11 05:15:45 Branches: 58 58 100.0 %

Line Branch Exec Source
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
/**************************************************************************/
83
211
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
211
    media_ptr -> fx_media_directory_default_sets++;
99
#endif
100
101
    /* Setup pointer to media name buffer.  */
102
211
    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
211
    dir_entry.fx_dir_entry_short_name[0] =  0;
106
107
    /* Clear the long name string.  */
108
211
    dir_entry.fx_dir_entry_name[0] =  (CHAR)0;
109
110
    /* Check the media to make sure it is open.  */
111
211
    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
112
    {
113
114
        /* Return the media not opened error.  */
115
1
        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
210
    FX_PROTECT
123
124
    /* Setup the path string pointer to the start of the current path.  */
125
210
    path_string_ptr =  &(media_ptr -> fx_media_default_path.fx_path_string[0]);
126
127
128
    /* Look for a root directory selection.  */
129


210
    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
11
        media_ptr -> fx_media_default_path.fx_path_directory.fx_dir_entry_name[0] =  (CHAR) 0;
134
11
        media_ptr -> fx_media_default_path.fx_path_string[0] =                       (CHAR) 0;
135
11
        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
199
        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

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

197
        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
173
            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
1
                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
1
                path_ptr =  (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
179
180
                /* Copy the local path to the default path.  */
181
1
                media_ptr -> fx_media_default_path =  *path_ptr;
182
183
                /* Restore the name pointer of the default path.  */
184
1
                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
1
                path_ptr =  &media_ptr -> fx_media_default_path;
188
            }
189
            else
190
            {
191
192
                /* Setup the default path to the global media path.  */
193
172
                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
173
            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
57
                if (!dir_entry.fx_dir_entry_cluster)
211
                {
212
                    /* Set the current directory back to the root directory.  */
213
4
                    path_ptr -> fx_path_directory.fx_dir_entry_name[0] =  (CHAR) 0;
214
215
                    /* Set name to NULL.  */
216
4
                    dir_entry.fx_dir_entry_name[0] =  (CHAR) 0;
217
218
                    /* Clear the current path string.  */
219
4
                    path_ptr -> fx_path_string[0] =  (CHAR)0;
220
221
                    /* Clear the overflow flag in the current path string... just in
222
                       case! */
223
4
                    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
57
                path_ptr -> fx_path_directory =  dir_entry;
228
229
                /* Copy the name into the path name buffer.  */
230
784
                for (i = 0; dir_entry.fx_dir_entry_name[i]; i++)
231
                {
232
727
                    path_ptr -> fx_path_name_buffer[i] =  dir_entry.fx_dir_entry_name[i];
233
                }
234
235
                /* Reassign the pointer.  */
236
57
                path_ptr -> fx_path_directory.fx_dir_entry_name =  path_ptr -> fx_path_name_buffer;
237
238
                /* Release media protection.  */
239
57
                FX_UNPROTECT
240
241
                /* Default directory set is complete, return status.  */
242
57
                return(FX_SUCCESS);
243
            }
244
245
            /* Move the current path starting pointer to the end of the current
246
               path string.  */
247

11640
            while ((path_string_capacity) && (*path_string_ptr != FX_NULL))
248
            {
249
11524
                path_string_ptr++;
250
11524
                path_string_capacity--;
251
            }
252
253
            /* If room, place the \ character in the path string.  */
254
116
            if (path_string_capacity)
255
            {
256
257
                /* There is room, place the directory marker in the string.  */
258
115
                *path_string_ptr++ =  '\\';
259
115
                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
24
            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
1
                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
1
                path_ptr =  (FX_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr;
280
281
                /* Copy the local path to the default path.  */
282
1
                media_ptr -> fx_media_default_path =  *path_ptr;
283
284
                /* Restore the name pointer of the default path.  */
285
1
                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
1
                path_ptr =  &media_ptr -> fx_media_default_path;
289
            }
290
            else
291
            {
292
293
                /* Setup the default path to the global media path.  */
294
23
                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
24
            if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
305
            {
306
2
                path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
307
            }
308
        }
309
310
        /* Copy what we can into the current path.  */
311
3143
        while (*new_path_name)
312
        {
313
314
            /* Determine if there is a ".." character sequence that specifies the
315
               previous path.  */
316

3012
            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
4
                path_string_capacity =  path_string_capacity + 2;
324
4
                path_string_ptr =       path_string_ptr - 2;
325
326
75
                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

73
                    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
71
                    path_string_capacity++;
341
71
                    path_string_ptr--;
342
                }
343
344
                /* Adjust the new directory pointer past the .. characters  */
345
4
                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
3008
                if (path_string_capacity)
353
                {
354
355
                    /* Copy character from the new path into the current path string.  */
356
2999
                    *path_string_ptr++ =  *new_path_name++;
357
358
2999
                    path_string_capacity--;
359
                }
360
                else
361
                {
362
363
                    /* No more room in the current path string!  */
364
9
                    break;
365
                }
366
            }
367
        }
368
369
        /* Determine if there is still room in the current path string.  */
370
140
        if (path_string_capacity)
371
        {
372
373
            /* Yes, there is still room, place a NULL character at the
374
               end of the path.  */
375
129
            *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
11
            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
9
                path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] =  '*';
390
            }
391
        }
392
393
        /* Determine if we are at the root directory.  */
394
140
        if (!dir_entry.fx_dir_entry_cluster)
395
        {
396
397
            /* Set the current directory back to the root directory.  */
398
2
            dir_entry.fx_dir_entry_name[0] =      (CHAR)0;
399
2
            path_ptr -> fx_path_name_buffer[0] =  (CHAR)0;
400
        }
401
402
        /* Copy the new directory entry into the media control block.  */
403
140
        path_ptr -> fx_path_directory =  dir_entry;
404
405
        /* Copy the name.  */
406
2923
        for (i = 0; dir_entry.fx_dir_entry_name[i]; i++)
407
        {
408
2783
            path_ptr -> fx_path_name_buffer[i] =  dir_entry.fx_dir_entry_name[i];
409
        }
410
411
        /* Reassign the pointer.  */
412
140
        path_ptr -> fx_path_directory.fx_dir_entry_name =  path_ptr -> fx_path_name_buffer;
413
    }
414
415
    /* Release media protection.  */
416
151
    FX_UNPROTECT
417
418
    /* Default directory set is complete, return status.  */
419
151
    return(FX_SUCCESS);
420
}
421