GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: fx_file_open.c Lines: 137 137 100.0 %
Date: 2024-01-10 21:53:23 Branches: 64 64 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
34
35
/**************************************************************************/
36
/*                                                                        */
37
/*  FUNCTION                                               RELEASE        */
38
/*                                                                        */
39
/*    _fx_file_open                                       PORTABLE C      */
40
/*                                                           6.1          */
41
/*  AUTHOR                                                                */
42
/*                                                                        */
43
/*    William E. Lamie, Microsoft Corporation                             */
44
/*                                                                        */
45
/*  DESCRIPTION                                                           */
46
/*                                                                        */
47
/*    This function first attempts to find the specified file.  If found, */
48
/*    the open request is validated and the file is opened.  During the   */
49
/*    opening process, all of the FAT entries for this file are examined  */
50
/*    for their integrity.                                                */
51
/*                                                                        */
52
/*  INPUT                                                                 */
53
/*                                                                        */
54
/*    media_ptr                             Media control block pointer   */
55
/*    file_ptr                              File control block pointer    */
56
/*    file_name                             Name pointer                  */
57
/*    open_type                             Type of open requested        */
58
/*                                                                        */
59
/*  OUTPUT                                                                */
60
/*                                                                        */
61
/*    return status                                                       */
62
/*                                                                        */
63
/*  CALLS                                                                 */
64
/*                                                                        */
65
/*    _fx_directory_search                  Search for the file name in   */
66
/*                                          the directory structure       */
67
/*    _fx_utility_FAT_entry_read            Read a FAT entry              */
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), and      */
79
/*                                            added conditional to        */
80
/*                                            disable fast open and       */
81
/*                                            consecutive detect,         */
82
/*                                            resulting in version 6.1    */
83
/*                                                                        */
84
/**************************************************************************/
85
18457
UINT  _fx_file_open(FX_MEDIA *media_ptr, FX_FILE *file_ptr, CHAR *file_name, UINT open_type)
86
{
87
88
UINT     status;
89
#ifndef FX_DISABLE_CONSECUTIVE_DETECT
90
UINT     leading_consecutive;
91
#endif /* FX_DISABLE_CONSECUTIVE_DETECT */
92
ULONG    cluster;
93
18457
ULONG    contents = 0;
94
ULONG    open_count;
95
FX_FILE *tail_ptr;
96
FX_FILE *search_ptr;
97
ULONG    bytes_per_cluster;
98
UINT     last_cluster;
99
ULONG    cluster_count;
100
ULONG64  bytes_available;
101
ULONG64  bytes_remaining;
102
ULONG    fat_last;
103
#ifndef FX_DISABLE_FAST_OPEN
104
UINT     fast_open;
105
#endif /* FX_DISABLE_FAST_OPEN */
106
UCHAR    not_a_file_attr;
107
108
109
    /* Check the media to make sure it is open.  */
110
18457
    if (media_ptr -> fx_media_id != FX_MEDIA_ID)
111
    {
112
113
        /* Return the media not opened error.  */
114
136
        return(FX_MEDIA_NOT_OPEN);
115
    }
116
117
#ifndef FX_MEDIA_STATISTICS_DISABLE
118
119
    /* Increment the number of times this service has been called.  */
120
18321
    media_ptr -> fx_media_file_opens++;
121
#endif
122
123
    /* Clear the notify function. */
124
18321
    file_ptr -> fx_file_write_notify = FX_NULL;
125
126
    /* Determine the type of FAT and setup variables accordingly.  */
127
#ifdef FX_ENABLE_EXFAT
128
    if (media_ptr -> fx_media_FAT_type == FX_exFAT)
129
    {
130
        fat_last        = FX_LAST_CLUSTER_exFAT;
131
        not_a_file_attr = FX_DIRECTORY;
132
    }
133
    else if (media_ptr -> fx_media_FAT_type == FX_FAT32)
134
#else
135
18321
    if (media_ptr -> fx_media_32_bit_FAT)
136
#endif /* FX_ENABLE_EXFAT */
137
    {
138
3032
        fat_last        = FX_LAST_CLUSTER_1_32;
139
3032
        not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
140
    }
141
    else
142
    {
143
15289
        fat_last        = FX_LAST_CLUSTER_1;
144
15289
        not_a_file_attr = FX_DIRECTORY | FX_VOLUME;
145
    }
146
147
#ifndef FX_DISABLE_FAST_OPEN
148
    /* Determine if a fast open is selected.  */
149
18321
    if (open_type == FX_OPEN_FOR_READ_FAST)
150
    {
151
152
        /* Yes, convert the open type to a standard read.  */
153
2
        open_type =  FX_OPEN_FOR_READ;
154
155
        /* Set the open fast flag.  */
156
2
        fast_open =  FX_TRUE;
157
    }
158
    else
159
    {
160
161
        /* A fast open is not selected, set the flag to false.  */
162
18319
        fast_open =  FX_FALSE;
163
    }
164
#endif /* FX_DISABLE_FAST_OPEN */
165
166
    /* If trace is enabled, register this object.  */
167
    FX_TRACE_OBJECT_REGISTER(FX_TRACE_OBJECT_TYPE_FILE, file_ptr, file_name, 0, 0)
168
169
    /* If trace is enabled, insert this event into the trace buffer.  */
170
    FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_OPEN, media_ptr, file_ptr, file_name, open_type, FX_TRACE_FILE_EVENTS, 0, 0)
171
172
    /* Protect against other threads accessing the media.  */
173
18321
    FX_PROTECT
174
175
    /* Setup file name pointer.  */
176
18321
    file_ptr -> fx_file_dir_entry.fx_dir_entry_name =  file_ptr -> fx_file_name_buffer;
177
18321
    file_ptr -> fx_file_dir_entry.fx_dir_entry_short_name[0] =  0;
178
179
    /* Search the system for the supplied file name.  */
180
18321
    status =  _fx_directory_search(media_ptr, file_name, &(file_ptr -> fx_file_dir_entry), FX_NULL, FX_NULL);
181
182
    /* Determine if the search was successful.  */
183
18321
    if (status != FX_SUCCESS)
184
    {
185
186
        /* Release media protection.  */
187
5
        FX_UNPROTECT
188
189
        /* Return the error code.  */
190
5
        return(status);
191
    }
192
193
    /* Check to make sure the found entry is a file.  */
194
18316
    if (file_ptr -> fx_file_dir_entry.fx_dir_entry_attributes & not_a_file_attr)
195
    {
196
197
        /* Release media protection.  */
198
1
        FX_UNPROTECT
199
200
        /* Return the not a file error code.  */
201
1
        return(FX_NOT_A_FILE);
202
    }
203
204
#ifdef FX_SINGLE_OPEN_LEGACY
205
    /* Check to make sure the access is okay.  */
206
    if (open_type == FX_OPEN_FOR_READ)
207
    {
208
209
        /* Check the list of open files for others open for writing.  */
210
        open_count =  media_ptr -> fx_media_opened_file_count;
211
        search_ptr =  media_ptr -> fx_media_opened_file_list;
212
        while (open_count)
213
        {
214
215
            /* Look at each opened file to see if the same file is opened
216
               for writing.  */
217
            if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
218
                 file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
219
                (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
220
                 file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset) &&
221
                (search_ptr -> fx_file_open_mode))
222
            {
223
224
                /* Release media protection.  */
225
                FX_UNPROTECT
226
227
                /* The file has been opened for writing by a previous call.  */
228
                return(FX_ACCESS_ERROR);
229
            }
230
231
            /* Adjust the pointer and decrement the search count.  */
232
            search_ptr =  search_ptr -> fx_file_opened_next;
233
            open_count--;
234
        }
235
    }
236
    else
237
#else
238
18315
    if (open_type == FX_OPEN_FOR_WRITE)
239
#endif
240
    {
241
242
        /* A open for write request is present, check the file attributes
243
           and the list of open files for any other open instance of
244
           this file.  */
245
17242
        if (media_ptr -> fx_media_driver_write_protect)
246
        {
247
248
            /* Release media protection.  */
249
1
            FX_UNPROTECT
250
251
            /* Return write protect error.  */
252
1
            return(FX_WRITE_PROTECT);
253
        }
254
255
17241
        if (file_ptr -> fx_file_dir_entry.fx_dir_entry_attributes & (UCHAR)(FX_READ_ONLY))
256
        {
257
258
            /* Release media protection.  */
259
1
            FX_UNPROTECT
260
261
            /* Return the not a file error code.  */
262
1
            return(FX_ACCESS_ERROR);
263
        }
264
265
        /* Also search the opened files to see if this file is currently
266
           opened.  */
267
17240
        open_count =  media_ptr -> fx_media_opened_file_count;
268
17240
        search_ptr =  media_ptr -> fx_media_opened_file_list;
269
84298
        while (open_count)
270
        {
271
272
            /* Look at each opened file to see if the same file is already opened.  */
273
#ifdef FX_SINGLE_OPEN_LEGACY
274
            if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
275
                 file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
276
                (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
277
                 file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset))
278
#else
279
            /* Look at each opened file to see if the same file is already opened
280
               for writing.  */
281
67059
            if ((search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
282
67059
                 file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
283
66062
                (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
284
66062
                 file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset) &&
285
7
                (search_ptr -> fx_file_open_mode == FX_OPEN_FOR_WRITE))
286
#endif
287
            {
288
289
                /* Release media protection.  */
290
1
                FX_UNPROTECT
291
292
                /* The file is currently open.  */
293
1
                return(FX_ACCESS_ERROR);
294
            }
295
296
            /* Adjust the pointer and decrement the search count.  */
297
67058
            search_ptr =  search_ptr -> fx_file_opened_next;
298
67058
            open_count--;
299
        }
300
    }
301
302
    /* At this point, we are ready to walk list of clusters to setup the
303
       initial condition of this file as well as to verify its integrity.  */
304
18312
    cluster =           file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster;
305
18312
    bytes_remaining =   file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size;
306
18312
    bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
307
18312
        ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
308
18312
    file_ptr -> fx_file_current_physical_cluster =  0;
309
310
    /* Check for invalid value.  */
311
18312
    if (bytes_per_cluster == 0)
312
    {
313
314
        /* Release media protection.  */
315
1
        FX_UNPROTECT
316
317
        /* Invalid media, return error.  */
318
1
        return(FX_MEDIA_INVALID);
319
    }
320
321
18311
    last_cluster =      0;
322
18311
    cluster_count =     0;
323
324
#ifndef FX_DISABLE_CONSECUTIVE_DETECT
325
18311
    leading_consecutive = 1;
326
#endif /* FX_DISABLE_CONSECUTIVE_DETECT */
327
18311
    file_ptr -> fx_file_consecutive_cluster = 1;
328
#ifndef FX_DISABLE_FAST_OPEN
329
330
    /* Determine if the file is being open for reading with the fast option.  */
331
18311
    if (fast_open)
332
    {
333
334
        /* Calculate the bytes available.  */
335
2
        bytes_available =  ((bytes_remaining + bytes_per_cluster - 1) / bytes_per_cluster) * bytes_per_cluster;
336
337
#ifdef FX_ENABLE_EXFAT
338
        if (bytes_remaining && (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1))
339
        {
340
            cluster_count =
341
                (ULONG)((file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size + bytes_per_cluster - 1) /
342
                        bytes_per_cluster);
343
            file_ptr -> fx_file_consecutive_cluster = cluster_count;
344
        }
345
#endif /* FX_ENABLE_EXFAT */
346
    }
347
    else
348
#endif /* FX_DISABLE_FAST_OPEN */
349
    {
350
#ifdef FX_ENABLE_EXFAT
351
352
        /* File is open for writing... walk the FAT chain to position to the end.  */
353
354
        if (bytes_remaining && (file_ptr -> fx_file_dir_entry.fx_dir_entry_dont_use_fat & 1))
355
        {
356
            cluster_count =
357
                (ULONG)((file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size + bytes_per_cluster - 1) /
358
                        bytes_per_cluster);
359
360
            last_cluster = cluster + cluster_count - 1;
361
362
            file_ptr -> fx_file_consecutive_cluster = cluster_count;
363
364
            file_ptr -> fx_file_current_physical_cluster = last_cluster;
365
366
            file_ptr -> fx_file_current_relative_cluster = cluster_count - 1;
367
368
            bytes_remaining %= bytes_per_cluster;
369
370
            if (!bytes_remaining)
371
            {
372
                if (file_ptr -> fx_file_dir_entry.fx_dir_entry_available_file_size >
373
                    file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size)
374
                {
375
                    file_ptr -> fx_file_current_physical_cluster = last_cluster + 1;
376
                    file_ptr -> fx_file_current_relative_cluster++;
377
                }
378
                else
379
                {
380
                    bytes_remaining = bytes_per_cluster;
381
                }
382
            }
383
384
            bytes_available =
385
                (ULONG)((file_ptr -> fx_file_dir_entry.fx_dir_entry_available_file_size + bytes_per_cluster - 1) /
386
                        bytes_per_cluster);
387
            bytes_available *= bytes_per_cluster;
388
        }
389
        else
390
        {
391
#endif /* FX_ENABLE_EXFAT */
392
393
            /* Follow the link of FAT entries.  */
394

36798
            while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
395
            {
396
397
                /* Increment the number of clusters.  */
398
18492
                cluster_count++;
399
400
                /* Read the current cluster entry from the FAT.  */
401
18492
                status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
402
403
                /* Check the return value.  */
404
18492
                if (status != FX_SUCCESS)
405
                {
406
407
                    /* Release media protection.  */
408
1
                    FX_UNPROTECT
409
410
                    /* Return the error status.  */
411
1
                    return(status);
412
                }
413
414
                /* Determine if the cluster is invalid (points to itself) or the count exceeds the total number of clusters.  */
415

18491
                if ((cluster == contents) || (cluster_count > media_ptr -> fx_media_total_clusters))
416
                {
417
418
                    /* Release media protection.  */
419
2
                    FX_UNPROTECT
420
421
                    /* Return the bad status.  */
422
2
                    return(FX_FAT_READ_ERROR);
423
                }
424
425
#ifndef FX_DISABLE_CONSECUTIVE_DETECT
426
427
                /* Check if present and next clusters are consecutive */
428
18489
                if (cluster + 1 == contents)
429
                {
430
431
                    /* Determine if clusters are consecutive so far.  */
432
1115
                    if (leading_consecutive)
433
                    {
434
435
                        /* Yes, increment the number of leading consecutive clusters.  */
436
1101
                        file_ptr -> fx_file_consecutive_cluster++;
437
                    }
438
                }
439
                else
440
                {
441
442
                    /* The clusters are no longer consecutive, clear the consecutive flag.  */
443
17374
                    leading_consecutive = 0;
444
                }
445
#endif /* FX_DISABLE_CONSECUTIVE_DETECT */
446
447
                /* Save the last valid cluster.  */
448
18489
                last_cluster =  cluster;
449
450
                /* Setup for the next cluster.  */
451
18489
                cluster =  contents;
452
453
                /* Determine if this is the last written cluster.  We need to remember this
454
                   for open for writing.  */
455
18489
                if (bytes_remaining > bytes_per_cluster)
456
                {
457
458
                    /* Still more written clusters, just decrement the counter.  */
459
6476
                    bytes_remaining =  bytes_remaining - bytes_per_cluster;
460
                }
461
12013
                else if (!file_ptr -> fx_file_current_physical_cluster)
462
                {
463
464
                    /* Remember this cluster number.  */
465
12011
                    file_ptr -> fx_file_current_physical_cluster =  last_cluster;
466
467
                    /* Remember the relative cluster.  */
468
12011
                    file_ptr -> fx_file_current_relative_cluster =  cluster_count - 1;
469
470
                    /* If the remaining bytes exactly fits the cluster size, check for
471
                       a possible adjustment to the next cluster.  */
472

12011
                    if ((bytes_remaining == bytes_per_cluster) &&
473
1020
                        (cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
474
                    {
475
476
                        /* We need to position to next allocated cluster.  */
477
1
                        file_ptr -> fx_file_current_physical_cluster =  cluster;
478
1
                        file_ptr -> fx_file_current_relative_cluster++;
479
480
                        /* Clear the remaining bytes.  */
481
1
                        bytes_remaining =  0;
482
                    }
483
                }
484
            }
485
486
            /* Determine if the number of clusters is large enough to support the
487
               specified file size.  */
488
18306
            bytes_available =  ((ULONG64)media_ptr -> fx_media_bytes_per_sector) *
489
18306
                ((ULONG64)media_ptr -> fx_media_sectors_per_cluster) *
490
18306
                ((ULONG64)cluster_count);
491
492
            /* Check the bytes available in the cluster chain against the directory entry file size.  */
493

18306
            if ((bytes_available < file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size) ||
494
12011
                ((cluster_count) && (contents < fat_last)))
495
            {
496
                /* File is corrupt, release media protection.  */
497
4
                FX_UNPROTECT
498
499
                /* Return a corrupt file error status.  */
500
4
                return(FX_FILE_CORRUPT);
501
            }
502
#ifdef FX_ENABLE_EXFAT
503
        }
504
#endif /* FX_ENABLE_EXFAT */
505
    }
506
507
    /* The file is okay, populate the file control block and complete the
508
       file open process.  */
509
18304
    file_ptr -> fx_file_id =                        FX_FILE_ID;
510
18304
    file_ptr -> fx_file_name =                      file_ptr -> fx_file_name_buffer;
511
18304
    file_ptr -> fx_file_media_ptr =                 media_ptr;
512
18304
    file_ptr -> fx_file_open_mode =                 open_type;
513
18304
    file_ptr -> fx_file_modified =                  FX_FALSE;
514
18304
    file_ptr -> fx_file_total_clusters =            cluster_count;
515
18304
    file_ptr -> fx_file_first_physical_cluster =    file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster;
516
18304
    file_ptr -> fx_file_last_physical_cluster =     last_cluster;
517
18304
    file_ptr -> fx_file_current_file_size =         file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size;
518
18304
    file_ptr -> fx_file_current_available_size =    bytes_available;
519
18304
    file_ptr -> fx_file_disable_burst_cache =       FX_FALSE;
520
521
    /* Set the current settings based on how the file was opened.  */
522
18304
    if (open_type == FX_OPEN_FOR_READ)
523
    {
524
525
        /* Position the pointers to the beginning of the file.  */
526
1073
        file_ptr -> fx_file_current_physical_cluster =  file_ptr -> fx_file_first_physical_cluster;
527
1073
        file_ptr -> fx_file_current_relative_cluster =  0;
528
1073
        file_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
529
1073
            (((ULONG64)(file_ptr -> fx_file_first_physical_cluster - FX_FAT_ENTRY_START)) *
530
1073
             ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
531
1073
        file_ptr -> fx_file_current_relative_sector =   0;
532
1073
        file_ptr -> fx_file_current_logical_offset =    0;
533
1073
        file_ptr -> fx_file_current_file_offset =       0;
534
    }
535
    else
536
    {
537
538
        /* Open for writing - position the pointers to the end of the file.  */
539
540
        /* Determine if the remaining bytes fit exactly into the cluster size.  */
541
17231
        if (bytes_remaining == bytes_per_cluster)
542
        {
543
544
            /* Position to the end of the cluster.  */
545
17
            file_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
546
17
                (((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
547
17
                 ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
548
17
                ((ULONG)(((bytes_remaining - 1) / (ULONG)media_ptr -> fx_media_bytes_per_sector)));
549
17
            file_ptr -> fx_file_current_relative_sector =   (ULONG)(((bytes_remaining - 1) / (ULONG)media_ptr -> fx_media_bytes_per_sector));
550
17
            file_ptr -> fx_file_current_file_offset =       file_ptr -> fx_file_current_file_size;
551
17
            file_ptr -> fx_file_current_logical_offset =    media_ptr -> fx_media_bytes_per_sector;
552
        }
553
        else
554
        {
555
556
            /* Position file parameters at end of last cluster allocation.  */
557
17214
            file_ptr -> fx_file_current_logical_sector =    ((ULONG)media_ptr -> fx_media_data_sector_start) +
558
17214
                (((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
559
17214
                 ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
560
17214
                ((ULONG)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector)));
561
17214
            file_ptr -> fx_file_current_relative_sector =   (ULONG)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
562
17214
            file_ptr -> fx_file_current_file_offset =       file_ptr -> fx_file_current_file_size;
563
17214
            file_ptr -> fx_file_current_logical_offset =    (ULONG)bytes_remaining % ((ULONG)media_ptr -> fx_media_bytes_per_sector);
564
        }
565
    }
566
567
#ifdef FX_ENABLE_FAULT_TOLERANT
568
    /* By default, the whole file is used. */
569
    file_ptr -> fx_file_maximum_size_used = file_ptr -> fx_file_current_file_size;
570
#endif /* FX_ENABLE_FAULT_TOLERANT */
571
572
    /* Place newly opened file on the list of open files for
573
       this media.  First, check for an empty list.  */
574
18304
    if (media_ptr -> fx_media_opened_file_list)
575
    {
576
577
        /* Pickup tail pointer.  */
578
11093
        tail_ptr =  (media_ptr -> fx_media_opened_file_list) -> fx_file_opened_previous;
579
580
        /* Place the new file in the list.  */
581
11093
        (media_ptr -> fx_media_opened_file_list) -> fx_file_opened_previous =  file_ptr;
582
11093
        tail_ptr -> fx_file_opened_next =  file_ptr;
583
584
        /* Setup this file's opened links.  */
585
11093
        file_ptr -> fx_file_opened_previous =  tail_ptr;
586
11093
        file_ptr -> fx_file_opened_next =      media_ptr -> fx_media_opened_file_list;
587
    }
588
    else
589
    {
590
591
        /* The opened media list is empty.  Add the media to empty list.  */
592
7211
        media_ptr -> fx_media_opened_file_list =   file_ptr;
593
7211
        file_ptr ->  fx_file_opened_next =         file_ptr;
594
7211
        file_ptr ->  fx_file_opened_previous =     file_ptr;
595
    }
596
597
    /* Increment the opened file counter.  */
598
18304
    media_ptr -> fx_media_opened_file_count++;
599
600
    /* Release media protection.  */
601
18304
    FX_UNPROTECT
602
603
    /* Open is complete, return successful status.  */
604
18304
    return(FX_SUCCESS);
605
}
606