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 /**************************************************************************/
_fx_directory_local_path_set(FX_MEDIA * media_ptr,FX_LOCAL_PATH * local_path_ptr,CHAR * new_path_name)84 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 media_ptr -> fx_media_directory_local_path_sets++;
101 #endif
102
103 /* Setup pointer to a name buffer. */
104 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 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 dir_entry.fx_dir_entry_short_name[0] = (CHAR)0;
111
112 /* Clear the long name string. */
113 dir_entry.fx_dir_entry_name[0] = (CHAR)0;
114
115 /* Check the media to make sure it is open. */
116 if (media_ptr -> fx_media_id != FX_MEDIA_ID)
117 {
118
119 /* Return the media not opened error. */
120 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 FX_PROTECT
136
137 /* Look for a root directory selection. */
138 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 local_path_ptr -> fx_path_directory.fx_dir_entry_name[0] = (CHAR)0;
143 local_path_ptr -> fx_path_string[0] = (CHAR)0;
144 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 _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 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 if ((status != FX_SUCCESS) || (!(dir_entry.fx_dir_entry_attributes & FX_DIRECTORY)))
158 {
159
160 /* Release media protection. */
161 FX_UNPROTECT
162
163 /* Invalid Path - Return the error code. */
164 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 path_string_ptr = &(local_path_ptr -> fx_path_string[0]);
171
172 /* Setup the path string's capacity. */
173 path_string_capacity = FX_MAXIMUM_PATH - 1;
174
175 /* Determine if the new path is relative from the current path. */
176 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 path_ptr = local_path_ptr;
183
184 /* Determine if the local path is different than the current local path. */
185 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 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 i = 0;
197 do
198 {
199
200 /* Copy from previous local to new local path. */
201 local_path_ptr -> fx_path_string[i] =
202 ((FX_LOCAL_PATH *)_tx_thread_current_ptr -> tx_thread_filex_ptr) -> fx_path_string[i];
203
204 /* Determine if we are done. */
205 if (local_path_ptr -> fx_path_string[i] == 0)
206 {
207
208 /* Are we not at the end of the string? */
209 if (i < (FX_MAXIMUM_PATH - 1))
210 {
211
212 /* Yes, break the loop. */
213 break;
214 }
215 }
216
217 /* Move to the next character. */
218 i++;
219
220 } 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 i = 0;
228 do
229 {
230
231 /* Copy from the media default to new local path. */
232 local_path_ptr -> fx_path_string[i] =
233 media_ptr -> fx_media_default_path.fx_path_string[i];
234
235 /* Determine if we are done. */
236 if (local_path_ptr -> fx_path_string[i] == 0)
237 {
238
239 /* Are we not at the end of the string? */
240 if (i < (FX_MAXIMUM_PATH - 1))
241 {
242
243 /* Yes, break the loop. */
244 break;
245 }
246 }
247
248 /* Move to the next character. */
249 i++;
250
251 } 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 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 if (!dir_entry.fx_dir_entry_cluster)
265 {
266 /* Set the current directory back to the root directory. */
267 dir_entry.fx_dir_entry_name[0] = (CHAR)0;
268
269 /* Clear the current path string. */
270 path_ptr -> fx_path_string[0] = (CHAR)0;
271
272 /* Clear the overflow flag in the current path string... just in
273 case! */
274 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 path_ptr -> fx_path_directory = dir_entry;
279
280 /* Reset the local path name buffer pointer, since it was clobbered earlier. */
281 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 for (j = 0; j < FX_MAX_LONG_NAME_LEN; j++)
285 {
286
287 /* Copy the name buffer. */
288 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 _tx_thread_current_ptr -> tx_thread_filex_ptr = (VOID *)local_path_ptr;
293
294 /* Release media protection. */
295 FX_UNPROTECT
296
297 /* Default directory set is complete, return status. */
298 return(FX_SUCCESS);
299 }
300
301 /* Move the current path starting pointer to the end of the current
302 path string. */
303 while ((path_string_capacity) && (*path_string_ptr != FX_NULL))
304 {
305 path_string_ptr++;
306 path_string_capacity--;
307 }
308
309 /* If room, place the \ character in the path string. */
310 if (path_string_capacity)
311 {
312
313 /* There is room, place the directory marker in the string. */
314 *path_string_ptr++ = '\\';
315 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 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 if (path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] == '*')
329 {
330 path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = (CHAR)0;
331 }
332 }
333
334 /* Copy what we can into the current path. */
335 while (*new_path_name)
336 {
337
338 /* Determine if there is a ".." character sequence that specifies the
339 previous path. */
340 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 path_string_capacity = path_string_capacity + 2;
348 path_string_ptr = path_string_ptr - 2;
349
350 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 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 path_string_capacity++;
365 path_string_ptr--;
366 }
367
368 /* Adjust the new directory pointer past the .. characters */
369 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 if (path_string_capacity)
377 {
378
379 /* Copy character from the new path into the current path string. */
380 *path_string_ptr++ = *new_path_name++;
381
382 path_string_capacity--;
383 }
384 else
385 {
386
387 /* No more room in the current path string! */
388 break;
389 }
390 }
391 }
392
393 /* Determine if there is still room in the current path string. */
394 if (path_string_capacity)
395 {
396
397 /* Yes, there is still room, place a NULL character at the
398 end of the path. */
399 *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 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 path_ptr -> fx_path_string[FX_MAXIMUM_PATH - 2] = '*';
414 }
415 }
416
417 /* Determine if we are at the root directory. */
418 if (!dir_entry.fx_dir_entry_cluster)
419 {
420 /* Set the current directory back to the root directory. */
421 dir_entry.fx_dir_entry_name[0] = (CHAR)0;
422 local_path_ptr -> fx_path_name_buffer[0] = (CHAR)0;
423 }
424
425 /* Copy the new directory entry into the media control block. */
426 path_ptr -> fx_path_directory = dir_entry;
427
428 /* Reset the local path name buffer pointer, since it was clobbered earlier. */
429 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 for (j = 0; j < FX_MAX_LONG_NAME_LEN; j++)
433 {
434
435 /* Copy the name buffer. */
436 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 _tx_thread_current_ptr -> tx_thread_filex_ptr = (VOID *)local_path_ptr;
441 }
442
443 /* Release media protection. */
444 FX_UNPROTECT
445
446 /* Default directory set is complete, return status. */
447 return(FX_SUCCESS);
448 #endif
449 }
450
451