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 /**   Media                                                               */
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_media.h"
29 #include "fx_utility.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _fx_media_check_FAT_chain_check                     PORTABLE C      */
37 /*                                                           6.1          */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    William E. Lamie, Microsoft Corporation                             */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function walks the supplied FAT chain looking for cross links  */
45 /*    (FAT entries already used in another FAT chain) and abnormal FAT    */
46 /*    entries and invalid chain termination.                              */
47 /*                                                                        */
48 /*  INPUT                                                                 */
49 /*                                                                        */
50 /*    media_ptr                             Pointer to a previously       */
51 /*                                            opened media                */
52 /*    starting_cluster                      Starting cluster of FAT chain */
53 /*    last_valid_cluster                    Last valid cluster of chain   */
54 /*    total_valid_clusters                  Total number of valid clusters*/
55 /*    logical_fat                           Pointer to the logical FAT    */
56 /*                                            bit map                     */
57 /*                                                                        */
58 /*  OUTPUT                                                                */
59 /*                                                                        */
60 /*    error                                 Error code                    */
61 /*                                                                        */
62 /*  CALLS                                                                 */
63 /*                                                                        */
64 /*    _fx_utility_FAT_entry_read            Read a FAT entry              */
65 /*                                                                        */
66 /*  CALLED BY                                                             */
67 /*                                                                        */
68 /*    _fx_check_media                       Check media function          */
69 /*                                                                        */
70 /*  RELEASE HISTORY                                                       */
71 /*                                                                        */
72 /*    DATE              NAME                      DESCRIPTION             */
73 /*                                                                        */
74 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
75 /*  09-30-2020     William E. Lamie         Modified comment(s),          */
76 /*                                            resulting in version 6.1    */
77 /*                                                                        */
78 /**************************************************************************/
_fx_media_check_FAT_chain_check(FX_MEDIA * media_ptr,ULONG starting_cluster,ULONG * last_valid_cluster,ULONG * total_valid_clusters,UCHAR * logical_fat)79 ULONG  _fx_media_check_FAT_chain_check(FX_MEDIA *media_ptr, ULONG starting_cluster, ULONG *last_valid_cluster, ULONG *total_valid_clusters, UCHAR *logical_fat)
80 {
81 
82 ULONG prev_cluster, cluster, next_clust = 0;
83 ULONG cluster_number;
84 ULONG count, error;
85 UINT  status;
86 
87 
88     /* Initialize the error code.  */
89     error =  0;
90 
91     /* Setup at the first cluster.  */
92     cluster =  starting_cluster;
93 
94     /* Initialize the previous cluster.  */
95     prev_cluster =  0;
96 
97     /* Initialize the count to 0. */
98     count =  0;
99 
100     /* Loop to walk through the FAT chain.  */
101     while ((cluster >= (ULONG)FX_FAT_ENTRY_START) &&
102            (cluster < (FX_FAT_ENTRY_START + media_ptr -> fx_media_total_clusters)))
103     {
104 
105         cluster_number = cluster;
106 
107 
108         /* Determine if this cluster is already in the logical FAT bit map.  */
109         if (logical_fat[cluster_number >> 3] & (1 << (cluster_number & 7)))
110         {
111 
112             /* Yes, the cluster is already being used by another file or
113                sub-directory.  */
114             error =  FX_FAT_CHAIN_ERROR;
115             break;
116         }
117 
118         /* Now read the contents of the cluster.  */
119         status =  _fx_utility_FAT_entry_read(media_ptr, cluster, &next_clust);
120 
121         /* Check the return status.  */
122         if (status != FX_SUCCESS)
123         {
124 
125             /* Yes, the cluster is already being used by another file or
126                sub-directory.  */
127             error =  FX_IO_ERROR;
128             break;
129         }
130 
131         /* Determine if the link is circular or the count is greater than the
132            total clusters.  */
133         if ((cluster == next_clust) ||
134             (next_clust < (ULONG)FX_FAT_ENTRY_START) ||
135             ((next_clust >= (FX_FAT_ENTRY_START + media_ptr -> fx_media_total_clusters)) &&
136              (next_clust != media_ptr -> fx_media_fat_last)))
137         {
138 
139             error =  FX_FAT_CHAIN_ERROR;
140             break;
141         }
142 
143         /* Everything is good with the chain at this point.  Mark it as valid.  */
144         logical_fat[cluster_number >> 3] = (UCHAR)(logical_fat[cluster_number >> 3] | (1 << (cluster_number & 7)));
145 
146         /* Move the cluster variable forward.  */
147         prev_cluster =  cluster;
148         cluster =       next_clust;
149 
150         /* Increment the number of valid clusters.  */
151         count++;
152     }
153 
154     /* Return the last valid cluster and the total valid cluster count.  */
155     *last_valid_cluster =   prev_cluster;
156     *total_valid_clusters = count;
157 
158     /* Return error code.  */
159     return(error);
160 }
161 
162