GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_file_create.c Lines: 46 46 100.0 %
Date: 2024-01-10 21:53:23 Branches: 26 26 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
/**   File                                                                */
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_directory.h"
31
#include "fx_file.h"
32
#include "fx_utility.h"
33
#ifdef FX_ENABLE_FAULT_TOLERANT
34
#include "fx_fault_tolerant.h"
35
#endif /* FX_ENABLE_FAULT_TOLERANT */
36
37
38
/**************************************************************************/
39
/*                                                                        */
40
/*  FUNCTION                                               RELEASE        */
41
/*                                                                        */
42
/*    _fx_file_create                                     PORTABLE C      */
43
/*                                                           6.1          */
44
/*  AUTHOR                                                                */
45
/*                                                                        */
46
/*    William E. Lamie, Microsoft Corporation                             */
47
/*                                                                        */
48
/*  DESCRIPTION                                                           */
49
/*                                                                        */
50
/*    This function first attempts to find the specified file.  If found, */
51
/*    the create request is invalid and an error is returned to the       */
52
/*    caller.  After the file name verification is made, a search for a   */
53
/*    free directory entry will be made.  If nothing is available, an     */
54
/*    error will be returned to the caller.  Otherwise, if all is okay, a */
55
/*    file of 0 bytes will be created.                                    */
56
/*                                                                        */
57
/*  INPUT                                                                 */
58
/*                                                                        */
59
/*    media_ptr                             Media control block pointer   */
60
/*    file_name                             File name                     */
61
/*                                                                        */
62
/*  OUTPUT                                                                */
63
/*                                                                        */
64
/*    return status                                                       */
65
/*                                                                        */
66
/*  CALLS                                                                 */
67
/*                                                                        */
68
/*    _fx_directory_entry_write             Write the new directory entry */
69
/*    _fx_directory_name_extract            Extract directory name        */
70
/*    _fx_directory_search                  Search for the file name in   */
71
/*                                          the directory structure       */
72
/*    _fx_directory_free_search             Search for a free directory   */
73
/*                                            entry                       */
74
/*    _fx_fault_tolerant_transaction_start  Start fault tolerant          */
75
/*                                            transaction                 */
76
/*    _fx_fault_tolerant_transaction_end    End fault tolerant transaction*/
77
/*    _fx_fault_tolerant_recover            Recover FAT chain             */
78
/*    _fx_fault_tolerant_reset_log_file     Reset the log file            */
79
/*                                                                        */
80
/*  CALLED BY                                                             */
81
/*                                                                        */
82
/*    Application Code                                                    */
83
/*                                                                        */
84
/*  RELEASE HISTORY                                                       */
85
/*                                                                        */
86
/*    DATE              NAME                      DESCRIPTION             */
87
/*                                                                        */
88
/*  05-19-2020     William E. Lamie         Initial Version 6.0           */
89
/*  09-30-2020     William E. Lamie         Modified comment(s),          */
90
/*                                            resulting in version 6.1    */
91
/*                                                                        */
92
/**************************************************************************/
93
55363
UINT  _fx_file_create(FX_MEDIA *media_ptr, CHAR *file_name)
94
{
95
96
FX_INT_SAVE_AREA
97
98
UINT         status;
99
CHAR        *name_ptr;
100
UINT         i;
101
CHAR        *work_ptr;
102
FX_DIR_ENTRY dir_entry;
103
FX_DIR_ENTRY search_directory;
104
#ifdef FX_ENABLE_EXFAT
105
ULONG64      dir_size;
106
#endif /* FX_ENABLE_EXFAT */
107
108
109
#ifndef FX_MEDIA_STATISTICS_DISABLE
110
111
    /* Increment the number of times this service has been called.  */
112
55363
    media_ptr -> fx_media_file_creates++;
113
#endif
114
115
    /* Determine if the supplied name is less than the maximum supported name size. The
116
       maximum name (FX_MAX_LONG_NAME_LEN) is defined in fx_api.h.  */
117
55363
    i =  0;
118
55363
    work_ptr =  (CHAR *)file_name;
119
737491
    while (*work_ptr)
120
    {
121
122
        /* Determine if the character designates a new path.  */
123

682128
        if ((*work_ptr == '\\') || (*work_ptr == '/'))
124
        {
125
            /* Yes, reset the name size.  */
126
28434
            i =  0;
127
        }
128
        /* Check for leading spaces.  */
129

653694
        else if ((*work_ptr != ' ') || (i != 0))
130
        {
131
132
            /* No leading spaces, increment the name size.  */
133
653670
            i++;
134
        }
135
136
        /* Move to the next character.  */
137
682128
        work_ptr++;
138
    }
139
140
    /* Determine if the supplied name is valid.  */
141

55363
    if ((i == 0) || (i >= FX_MAX_LONG_NAME_LEN))
142
    {
143
144
        /* Return an invalid name value.  */
145
2
        return(FX_INVALID_NAME);
146
    }
147
148
    /* Setup pointer to media name buffer.  */
149
55361
    dir_entry.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN;
150
151
    /* Setup another pointer to another media name buffer.  */
152
55361
    search_directory.fx_dir_entry_name =  media_ptr -> fx_media_name_buffer + FX_MAX_LONG_NAME_LEN * 2;
153
154
    /* Clear the short name strings.  */
155
55361
    dir_entry.fx_dir_entry_short_name[0] =        0;
156
55361
    search_directory.fx_dir_entry_short_name[0] = 0;
157
158
    /* Check the media to make sure it is open.  */
159
55361
    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
160
    {
161
162
        /* Return the media not opened error.  */
163
1
        return(FX_MEDIA_NOT_OPEN);
164
    }
165
166
    /* If trace is enabled, insert this event into the trace buffer.  */
167
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_CREATE, media_ptr, file_name, 0, 0, FX_TRACE_FILE_EVENTS, 0, 0)
168
169
    /* Protect against other threads accessing the media.  */
170
55360
    FX_PROTECT
171
172
#ifdef FX_ENABLE_FAULT_TOLERANT
173
    /* Start transaction. */
174
    _fx_fault_tolerant_transaction_start(media_ptr);
175
#endif /* FX_ENABLE_FAULT_TOLERANT */
176
177
    /* Check for write protect at the media level (set by driver).  */
178
55360
    if (media_ptr -> fx_media_driver_write_protect)
179
    {
180
181
#ifdef FX_ENABLE_FAULT_TOLERANT
182
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
183
#endif /* FX_ENABLE_FAULT_TOLERANT */
184
185
        /* Release media protection.  */
186
2
        FX_UNPROTECT
187
188
        /* Return write protect error.  */
189
2
        return(FX_WRITE_PROTECT);
190
    }
191
192
    /* Search the system for the supplied file name.  */
193
55358
    status =  _fx_directory_search(media_ptr, file_name, &dir_entry, &search_directory, &name_ptr);
194
195
    /* Determine if the search was successful.  */
196
55358
    if (status == FX_SUCCESS)
197
    {
198
199
#ifdef FX_ENABLE_FAULT_TOLERANT
200
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
201
#endif /* FX_ENABLE_FAULT_TOLERANT */
202
203
        /* Release media protection.  */
204
437
        FX_UNPROTECT
205
206
        /* File found - Return the error code.  */
207
437
        return(FX_ALREADY_CREATED);
208
    }
209
210
    /* Determine if there is anything left after the name.  */
211
54921
    if (_fx_directory_name_extract(name_ptr, &dir_entry.fx_dir_entry_name[0]))
212
    {
213
214
#ifdef FX_ENABLE_FAULT_TOLERANT
215
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
216
#endif /* FX_ENABLE_FAULT_TOLERANT */
217
218
        /* Release media protection.  */
219
2
        FX_UNPROTECT
220
221
        /* Extra information after the file name, return an invalid path
222
           error.  */
223
2
        return(FX_INVALID_PATH);
224
    }
225
226
#ifdef FX_ENABLE_EXFAT
227
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
228
    {
229
        if (((dir_entry.fx_dir_entry_name[0] == '.') && (dir_entry.fx_dir_entry_name[1] == 0)) ||
230
            ((dir_entry.fx_dir_entry_name[0] == '.') && (dir_entry.fx_dir_entry_name[1] == '.') && (dir_entry.fx_dir_entry_name[2] == 0)))
231
        {
232
#ifdef FX_ENABLE_FAULT_TOLERANT
233
            FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
234
#endif /* FX_ENABLE_FAULT_TOLERANT */
235
236
            /* Release media protection.  */
237
            FX_UNPROTECT
238
239
            /* We don't need '.' or '..' for exFAT */
240
            return(FX_ALREADY_CREATED);
241
        }
242
    }
243
244
    /* Save the directory entry size.  */
245
    dir_size = search_directory.fx_dir_entry_file_size;
246
#endif /* FX_ENABLE_EXFAT */
247
248
    /* Find a free slot for the new file.  */
249
54919
    status =  _fx_directory_free_search(media_ptr, &search_directory, &dir_entry);
250
251
    /* Determine if the search was successful.  */
252
54919
    if (status != FX_SUCCESS)
253
    {
254
255
#ifdef FX_ENABLE_FAULT_TOLERANT
256
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
257
#endif /* FX_ENABLE_FAULT_TOLERANT */
258
259
        /* Release media protection.  */
260
21
        FX_UNPROTECT
261
262
        /* Return the error code.  */
263
21
        return(status);
264
    }
265
266
    /* Populate the directory entry.  */
267
268
    /* Isolate the file name.  */
269
54898
    _fx_directory_name_extract(name_ptr, &dir_entry.fx_dir_entry_name[0]);
270
271
    /* Disable interrupts for time/date access.  */
272
54898
    FX_DISABLE_INTS
273
274
    /* Set time and date stamps.  */
275
54898
    dir_entry.fx_dir_entry_time =  _fx_system_time;
276
54898
    dir_entry.fx_dir_entry_date =  _fx_system_date;
277
278
    /* Restore interrupts.  */
279
54898
    FX_RESTORE_INTS
280
281
    /* Set the attributes for the file.  */
282
54898
    dir_entry.fx_dir_entry_attributes =  FX_ARCHIVE;
283
284
    /* Set file size to 0. */
285
54898
    dir_entry.fx_dir_entry_file_size =  0;
286
287
#ifdef FX_ENABLE_EXFAT
288
    /* Set available file size to 0. */
289
    dir_entry.fx_dir_entry_available_file_size = 0;
290
#endif /* FX_ENABLE_EXFAT */
291
292
    /* Set the cluster to NULL.  */
293
54898
    dir_entry.fx_dir_entry_cluster =    FX_NULL;
294
295
    /* Is there a leading dot?  */
296
54898
    if (dir_entry.fx_dir_entry_name[0] == '.')
297
    {
298
299
        /* Yes, toggle the hidden attribute bit.  */
300
2
        dir_entry.fx_dir_entry_attributes |=  FX_HIDDEN;
301
    }
302
303
#ifdef FX_ENABLE_EXFAT
304
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
305
    {
306
307
        /* Don't use FAT by default.  */
308
        dir_entry.fx_dir_entry_dont_use_fat = (CHAR)(((search_directory.fx_dir_entry_dont_use_fat & 1) << 1) | 1);
309
310
        if (search_directory.fx_dir_entry_name[0])
311
        {
312
313
            /* Not root directory.  */
314
            /* Copy the date and time from the actual sub-directory.  */
315
            search_directory.fx_dir_entry_time = dir_entry.fx_dir_entry_time;
316
            search_directory.fx_dir_entry_date = dir_entry.fx_dir_entry_date;
317
318
            /* Check if the directory size has changed.  */
319
            if (search_directory.fx_dir_entry_file_size == dir_size)
320
            {
321
322
                /* Not changed, we need only update time stamps.  */
323
                status = _fx_directory_exFAT_entry_write(media_ptr, &search_directory, UPDATE_FILE);
324
            }
325
            else
326
            {
327
328
                /* Directory size changed, update time stamps and the stream size.  */
329
                status = _fx_directory_exFAT_entry_write(media_ptr, &search_directory, UPDATE_STREAM);
330
            }
331
332
            /* Check for a bad status.  */
333
            if (status != FX_SUCCESS)
334
            {
335
336
#ifdef FX_ENABLE_FAULT_TOLERANT
337
                FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
338
#endif /* FX_ENABLE_FAULT_TOLERANT */
339
340
                /* Release media protection.  */
341
                FX_UNPROTECT
342
343
                /* Return the bad status.  */
344
                return(status);
345
            }
346
        }
347
    }
348
    else
349
    {
350
        dir_entry.fx_dir_entry_dont_use_fat = 0;
351
    }
352
#endif /* FX_ENABLE_EXFAT */
353
354
    /* Now write out the directory entry.  */
355
#ifdef FX_ENABLE_EXFAT
356
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
357
    {
358
        status = _fx_directory_exFAT_entry_write(media_ptr, &dir_entry, UPDATE_FULL);
359
    }
360
    else
361
    {
362
#endif /* FX_ENABLE_EXFAT */
363
54898
        status = _fx_directory_entry_write(media_ptr, &dir_entry);
364
#ifdef FX_ENABLE_EXFAT
365
    }
366
#endif /* FX_ENABLE_EXFAT */
367
368
#ifdef FX_ENABLE_FAULT_TOLERANT
369
    /* Check for a bad status.  */
370
    if (status != FX_SUCCESS)
371
    {
372
373
        FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
374
375
        /* Release media protection.  */
376
        FX_UNPROTECT
377
378
        /* Return the bad status.  */
379
        return(status);
380
    }
381
382
    /* End transaction. */
383
    status = _fx_fault_tolerant_transaction_end(media_ptr);
384
#endif /* FX_ENABLE_FAULT_TOLERANT */
385
386
    /* Release media protection.  */
387
54898
    FX_UNPROTECT
388
389
    /* File create is complete, return status.  */
390
54898
    return(status);
391
}
392