GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_directory_local_path_set.c Lines: 88 88 100.0 %
Date: 2024-03-11 05:15:45 Branches: 70 70 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
/*  FUNCTION                                               RELEASE        */
40
/*                                                                        */
41
/*    _fx_directory_local_path_set                        PORTABLE C      */
42
/*                                                           6.1.5        */
43
/*  AUTHOR                                                                */
44
/*                                                                        */
45
/*    William E. Lamie, Microsoft Corporation                             */
46
/*                                                                        */
47
/*  DESCRIPTION                                                           */
48
/*                                                                        */
49
/*    This function sets the local default directory of the media to the  */
50
/*    path specified by the caller.  If this path is not found, an error  */
51
/*    code is returned.                                                   */
52
/*                                                                        */
53
/*  INPUT                                                                 */
54
/*                                                                        */
55
/*    media_ptr                             Media control block pointer   */
56
/*    local_path                            Local path control block ptr  */
57
/*    new_path_name                         New path to set current local */
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
/*                                                                        */
69
/*  CALLED BY                                                             */
70
/*                                                                        */
71
/*    Application Code                                                    */
72
/*                                                                        */
73
/*  RELEASE HISTORY                                                       */
74
/*                                                                        */
75
/*    DATE              NAME                      DESCRIPTION             */
76
/*                                                                        */
77
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
78
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
79
/*                                            resulting in version 6.1    */
80
/*  03-02-2021     William E. Lamie         Modified comment(s),          */
81
/*                                            resulting in version 6.1.5  */
82
/*                                                                        */
83
/**************************************************************************/
84
197
UINT  _fx_directory_local_path_set(FX_MEDIA *media_ptr, FX_LOCAL_PATH *local_path_ptr, CHAR *new_path_name)
85
{
86
87
#ifndef FX_NO_LOCAL_PATH
88
UINT         status;
89
CHAR        *path_string_ptr;
90
UINT         path_string_capacity;
91
FX_PATH     *path_ptr;
92
UINT         i, j;
93
#endif
94
FX_DIR_ENTRY dir_entry;
95
96
97
#ifndef FX_MEDIA_STATISTICS_DISABLE
98
99
    /* Increment the number of times this service has been called.  */
100
197
    media_ptr -> fx_media_directory_local_path_sets++;
101
#endif
102
103
    /* Setup pointer to a name buffer.  */
104
197
    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
105
106
    /* Setup the local path name buffer pointer.  */
107
197
    local_path_ptr -> fx_path_directory.fx_dir_entry_name =  local_path_ptr -> fx_path_name_buffer;
108
109
    /* Clear the short name string.  */
110
197
    dir_entry.fx_dir_entry_short_name[0] =  (CHAR)0;
111
112
    /* Clear the long name string.  */
113
197
    dir_entry.fx_dir_entry_name[0] =  (CHAR)0;
114
115
    /* Check the media to make sure it is open.  */
116
197
    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
117
    {
118
119
        /* Return the media not opened error.  */
120
1
        return(FX_MEDIA_NOT_OPEN);
121
    }
122
123
#ifdef FX_NO_LOCAL_PATH
124
125
    FX_PARAMETER_NOT_USED(new_path_name);
126
127
    /* Error, return to caller.  */
128
    return(FX_NOT_IMPLEMENTED);
129
#else
130
131
    /* If trace is enabled, insert this event into the trace buffer.  */
132
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_DIRECTORY_LOCAL_PATH_SET, media_ptr, local_path_ptr, new_path_name, 0, FX_TRACE_DIRECTORY_EVENTS, 0, 0)
133
134
    /* Protect against other threads accessing the media.  */
135
196
    FX_PROTECT
136
137
    /* Look for a root directory selection.  */
138


196
    if ((!new_path_name) || (((new_path_name[0] == '\\') || (new_path_name[0] == '/')) && (new_path_name[1] == (CHAR)0)))
139
    {
140
141
        /* Set the default local directory to the root.  */
142
5
        local_path_ptr -> fx_path_directory.fx_dir_entry_name[0] =  (CHAR)0;
143
5
        local_path_ptr -> fx_path_string[0] =                       (CHAR)0;
144
5
        local_path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] =       (CHAR)0;
145
146
        /* Setup thread control block to use this local path pointer.  */
147
5
        _tx_thread_current_ptr -> tx_thread_filex_ptr =  (VOID *)local_path_ptr;
148
    }
149
    else
150
    {
151
152
        /* Search the system for the supplied path and directory name.  */
153
191
        status =  _fx_directory_search(media_ptr, new_path_name, &dir_entry, FX_NULL, FX_NULL);
154
155
        /* Determine if the search failed or if the entry found is not a
156
           directory.  */
157

191
        if ((status != FX_SUCCESS) || (!(dir_entry.fx_dir_entry_attributes & FX_DIRECTORY)))
158
        {
159
160
            /* Release media protection.  */
161
7
            FX_UNPROTECT
162
163
            /* Invalid Path - Return the error code.  */
164
7
            return(FX_INVALID_PATH);
165
        }
166
167
        /* Now update the current path string.  */
168
169
        /* Setup the path string pointer to the start of the current path.  */
170
184
        path_string_ptr =  &(local_path_ptr -> fx_path_string[0]);
171
172
        /* Setup the path string's capacity.  */
173
184
        path_string_capacity =  FX_MAXIMUM_PATH - 1;
174
175
        /* Determine if the new path is relative from the current path.  */
176

184
        if ((new_path_name[0] != '\\') && (new_path_name[0] != '/'))
177
        {
178
179
            /* Yes, a relative path was found.  */
180
181
            /* Setup the default path pointer to the local path.  */
182
180
            path_ptr =  local_path_ptr;
183
184
            /* Determine if the local path is different than the current local path.  */
185
180
            if (local_path_ptr !=  (FX_LOCAL_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr)
186
            {
187
188
                /* Yes, there is a difference.  */
189
190
                /* Should we copy from the default media path or from the previous default
191
                   path.  */
192
81
                if (_tx_thread_current_ptr -> tx_thread_filex_ptr)
193
                {
194
195
                    /* There is a local path so copy the relative path info from it.  */
196
70
                    i =  0;
197
                    do
198
                    {
199
200
                        /* Copy from previous local to new local path.  */
201
1573
                        local_path_ptr -> fx_path_string[i] =
202
1573
                            ((FX_LOCAL_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string[i];
203
204
                        /* Determine if we are done.  */
205
1573
                        if (local_path_ptr -> fx_path_string[i] == 0)
206
                        {
207
208
                            /* Are we not at the end of the string?  */
209
70
                            if (i < (FX_MAXIMUM_PATH - 1))
210
                            {
211
212
                                /* Yes, break the loop.  */
213
69
                                break;
214
                            }
215
                        }
216
217
                        /* Move to the next character.  */
218
1504
                        i++;
219
220
1504
                    } while (i < FX_MAXIMUM_PATH);
221
                }
222
                else
223
                {
224
225
                    /* No local path, so copy the relative path information from the media
226
                       default.  */
227
11
                    i =  0;
228
                    do
229
                    {
230
231
                        /* Copy from the media default to new local path.  */
232
266
                        local_path_ptr -> fx_path_string[i] =
233
266
                            media_ptr -> fx_media_default_path.fx_path_string[i];
234
235
                        /* Determine if we are done.  */
236
266
                        if (local_path_ptr -> fx_path_string[i] == 0)
237
                        {
238
239
                            /* Are we not at the end of the string?  */
240
11
                            if (i < (FX_MAXIMUM_PATH - 1))
241
                            {
242
243
                                /* Yes, break the loop.  */
244
10
                                break;
245
                            }
246
                        }
247
248
                        /* Move to the next character.  */
249
256
                        i++;
250
251
256
                    } while (i < FX_MAXIMUM_PATH);
252
                }
253
            }
254
255
            /* First, check the current path for string overflow.  If this is set,
256
               don't attempt to update the current path with relative information.
257
               The path won't be valid again until a complete path is given.  */
258
180
            if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
259
            {
260
261
                /* Yes, don't update the string, just finish the path set processing.  */
262
263
                /* Determine if we are at the root directory.  */
264
47
                if (!dir_entry.fx_dir_entry_cluster)
265
                {
266
                    /* Set the current directory back to the root directory.  */
267
4
                    dir_entry.fx_dir_entry_name[0] =  (CHAR)0;
268
269
                    /* Clear the current path string.  */
270
4
                    path_ptr -> fx_path_string[0] =  (CHAR)0;
271
272
                    /* Clear the overflow flag in the current path string... just in
273
                       case! */
274
4
                    path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] =  (CHAR)0;
275
                }
276
277
                /* Copy the new directory entry into the media control block.  */
278
47
                path_ptr -> fx_path_directory =  dir_entry;
279
280
                /* Reset the local path name buffer pointer, since it was clobbered earlier.  */
281
47
                local_path_ptr -> fx_path_directory.fx_dir_entry_name =  local_path_ptr -> fx_path_name_buffer;
282
283
                /* Copy the directory name entry to the local path name area.  */
284
12079
                for (j = 0; j < FX_MAX_LONG_NAME_LEN; j++)
285
                {
286
287
                    /* Copy the name buffer.  */
288
12032
                    local_path_ptr -> fx_path_directory.fx_dir_entry_name[j] =  dir_entry.fx_dir_entry_name[j];
289
                }
290
291
                /* Setup thread control block to use this local path pointer.  */
292
47
                _tx_thread_current_ptr -> tx_thread_filex_ptr =  (VOID *)local_path_ptr;
293
294
                /* Release media protection.  */
295
47
                FX_UNPROTECT
296
297
                /* Default directory set is complete, return status.  */
298
47
                return(FX_SUCCESS);
299
            }
300
301
            /* Move the current path starting pointer to the end of the current
302
               path string.  */
303

7325
            while ((path_string_capacity) && (*path_string_ptr != FX_NULL))
304
            {
305
7192
                path_string_ptr++;
306
7192
                path_string_capacity--;
307
            }
308
309
            /* If room, place the \ character in the path string.  */
310
133
            if (path_string_capacity)
311
            {
312
313
                /* There is room, place the directory marker in the string.  */
314
132
                *path_string_ptr++ =  '\\';
315
132
                path_string_capacity--;
316
            }
317
        }
318
        else
319
        {
320
321
            /* Setup the default path pointer.  */
322
323
            /* Setup the default path pointer to the local path.  */
324
4
            path_ptr =  local_path_ptr;
325
326
            /* Complete path name given.  Check to see if we need to clear an
327
               overflow character from a previous current path string update.  */
328
4
            if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
329
            {
330
1
                path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
331
            }
332
        }
333
334
        /* Copy what we can into the current path.  */
335
3091
        while (*new_path_name)
336
        {
337
338
            /* Determine if there is a ".." character sequence that specifies the
339
               previous path.  */
340

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

107
                    if ((*path_string_ptr == '\\') || (*path_string_ptr == '/'))
357
                    {
358
359
                        /* Yes, we have successfully backed up one directory.  */
360
                        break;
361
                    }
362
363
                    /* Backup another character.  */
364
103
                    path_string_capacity++;
365
103
                    path_string_ptr--;
366
                }
367
368
                /* Adjust the new directory pointer past the .. characters  */
369
6
                new_path_name =  new_path_name + 2;
370
            }
371
            else
372
            {
373
374
                /* Normal characters that need to be copied into the current path.  */
375
376
2953
                if (path_string_capacity)
377
                {
378
379
                    /* Copy character from the new path into the current path string.  */
380
2948
                    *path_string_ptr++ =  *new_path_name++;
381
382
2948
                    path_string_capacity--;
383
                }
384
                else
385
                {
386
387
                    /* No more room in the current path string!  */
388
5
                    break;
389
                }
390
            }
391
        }
392
393
        /* Determine if there is still room in the current path string.  */
394
137
        if (path_string_capacity)
395
        {
396
397
            /* Yes, there is still room, place a NULL character at the
398
               end of the path.  */
399
130
            *path_string_ptr =  (CHAR)FX_NULL;
400
        }
401
        else
402
        {
403
404
            /* No more room.  Determine if the entire path was successfully
405
               copied into the current path.  */
406
7
            if (*new_path_name)
407
            {
408
409
                /* No, we couldn't fit the entire path.  Place a "*" character
410
                   at the end to indicate that we had overflow.  Note that
411
                   the path is kept just the the directory default get call, so
412
                   the new default path is valid.  */
413
5
                path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] =  '*';
414
            }
415
        }
416
417
        /* Determine if we are at the root directory.  */
418
137
        if (!dir_entry.fx_dir_entry_cluster)
419
        {
420
            /* Set the current directory back to the root directory.  */
421
3
            dir_entry.fx_dir_entry_name[0] =            (CHAR)0;
422
3
            local_path_ptr -> fx_path_name_buffer[0] =  (CHAR)0;
423
        }
424
425
        /* Copy the new directory entry into the media control block.  */
426
137
        path_ptr -> fx_path_directory =  dir_entry;
427
428
        /* Reset the local path name buffer pointer, since it was clobbered earlier.  */
429
137
        local_path_ptr -> fx_path_directory.fx_dir_entry_name =  local_path_ptr -> fx_path_name_buffer;
430
431
        /* Copy the directory name entry to the local path name area.  */
432
35209
        for (j = 0; j < FX_MAX_LONG_NAME_LEN; j++)
433
        {
434
435
            /* Copy the name buffer.  */
436
35072
            local_path_ptr -> fx_path_directory.fx_dir_entry_name[j] =  dir_entry.fx_dir_entry_name[j];
437
        }
438
439
        /* Setup thread control block to use this local path pointer.  */
440
137
        _tx_thread_current_ptr -> tx_thread_filex_ptr =  (VOID *)local_path_ptr;
441
    }
442
443
    /* Release media protection.  */
444
142
    FX_UNPROTECT
445
446
    /* Default directory set is complete, return status.  */
447
142
    return(FX_SUCCESS);
448
#endif
449
}
450