GCC Code Coverage Report


Directory: common/src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 100.0% 71 / 0 / 71
Functions: 100.0% 1 / 0 / 1
Branches: 100.0% 58 / 0 / 58

fx_file_extended_seek.c
Line Branch Exec Source
1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 * Copyright (c) 2026-present Eclipse ThreadX contributors
4 *
5 * This program and the accompanying materials are made available under the
6 * terms of the MIT License which is available at
7 * https://opensource.org/licenses/MIT.
8 *
9 * SPDX-License-Identifier: MIT
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_extended_seek PORTABLE C */
40 /* 6.1.7 */
41 /* AUTHOR */
42 /* */
43 /* William E. Lamie, Microsoft Corporation */
44 /* */
45 /* DESCRIPTION */
46 /* */
47 /* This function positions the internal file pointers to the specified */
48 /* byte offset such that the next read or write operation will be */
49 /* performed there. If the byte offset is greater than the size, the */
50 /* file pointers will be positioned to the end of the file. */
51 /* */
52 /* INPUT */
53 /* */
54 /* file_ptr File control block pointer */
55 /* byte_offset Byte offset into the file */
56 /* */
57 /* OUTPUT */
58 /* */
59 /* return status */
60 /* */
61 /* CALLS */
62 /* */
63 /* _fx_utility_FAT_entry_read Read a FAT entry */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* Application Code */
68 /* */
69 /**************************************************************************/
70 6631622 UINT _fx_file_extended_seek(FX_FILE *file_ptr, ULONG64 byte_offset)
71 {
72
73 UINT status;
74 ULONG cluster;
75 6631622 ULONG contents = 0;
76 ULONG bytes_per_cluster;
77 ULONG last_cluster;
78 ULONG cluster_count;
79 ULONG64 bytes_remaining;
80 FX_MEDIA *media_ptr;
81
82
83 /* First, determine if the file is still open. */
84
2/2
✓ Branch 2 → 3 taken 13 times.
✓ Branch 2 → 4 taken 6631609 times.
6631622 if (file_ptr -> fx_file_id != FX_FILE_ID)
85 {
86
87 /* Return the file not open error status. */
88 13 return(FX_NOT_OPEN);
89 }
90
91 #ifndef FX_MEDIA_STATISTICS_DISABLE
92 /* Setup pointer to media structure. */
93 6631609 media_ptr = file_ptr -> fx_file_media_ptr;
94
95 /* Increment the number of times this service has been called. */
96 6631609 media_ptr -> fx_media_file_seeks++;
97 #endif
98
99 /* Setup pointer to associated media control block. */
100 6631609 media_ptr = file_ptr -> fx_file_media_ptr;
101
102 /* If trace is enabled, insert this event into the trace buffer. */
103 FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_SEEK, file_ptr, byte_offset, file_ptr -> fx_file_current_file_offset, 0, FX_TRACE_FILE_EVENTS, 0, 0)
104
105 /* Protect against other threads accessing the media. */
106 5016124 FX_PROTECT
107
108 /* Check if we actually have to do anything. */
109
4/4
✓ Branch 4 → 5 taken 349 times.
✓ Branch 4 → 6 taken 1615136 times.
✓ Branch 5 → 6 taken 3400847 times.
✓ Branch 5 → 8 taken 1615277 times.
6631609 if (byte_offset == file_ptr -> fx_file_current_file_offset)
110 {
111
112 /* Release media protection. */
113 3400847 FX_UNPROTECT
114
115 /* Seek is complete, return successful status. */
116 3401196 return(FX_SUCCESS);
117 }
118
119 /* Calculate the number of bytes per cluster. */
120 3230413 bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
121 3230413 ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
122
123 /* Check for invalid value. */
124
4/4
✓ Branch 6 → 7 taken 4 times.
✓ Branch 6 → 8 taken 1615132 times.
✓ Branch 8 → 9 taken 5 times.
✓ Branch 8 → 11 taken 1615272 times.
3230413 if (bytes_per_cluster == 0)
125 {
126
127 /* Release media protection. */
128 5 FX_UNPROTECT
129
130 /* Invalid media, return error. */
131 9 return(FX_MEDIA_INVALID);
132 }
133
134 /* See if we need to adjust the byte offset. */
135
4/4
✓ Branch 8 → 9 taken 222 times.
✓ Branch 8 → 10 taken 1614910 times.
✓ Branch 11 → 12 taken 252 times.
✓ Branch 11 → 13 taken 1615020 times.
3230404 if (byte_offset > file_ptr -> fx_file_current_file_size)
136 {
137
138 /* Adjust the byte offset down to the file size. */
139 474 byte_offset = file_ptr -> fx_file_current_file_size;
140 }
141
142 /* Check if the desired position within the leading consecutive clusters. */
143
4/4
✓ Branch 10 → 11 taken 626162 times.
✓ Branch 10 → 29 taken 988970 times.
✓ Branch 13 → 14 taken 625830 times.
✓ Branch 13 → 34 taken 989442 times.
3230404 if (byte_offset >= (ULONG64)file_ptr -> fx_file_consecutive_cluster * (ULONG64)bytes_per_cluster)
144 {
145
146 /* At this point, we are ready to walk list of clusters to setup the
147 seek position of this file. */
148
149 /* check if byte_offset is greater than where we were left off earlier */
150
4/4
✓ Branch 11 → 12 taken 176834 times.
✓ Branch 11 → 13 taken 449328 times.
✓ Branch 14 → 15 taken 175193 times.
✓ Branch 14 → 16 taken 450637 times.
1251992 if ((ULONG64)file_ptr -> fx_file_current_relative_cluster * (ULONG64)bytes_per_cluster < byte_offset)
151 {
152
153 352027 cluster = file_ptr -> fx_file_current_physical_cluster;
154
155 352027 bytes_remaining = byte_offset -
156 352027 file_ptr -> fx_file_current_relative_cluster * bytes_per_cluster;
157
158 352027 cluster_count = file_ptr -> fx_file_current_relative_cluster;
159 }
160 else
161 {
162
163 899965 cluster = file_ptr -> fx_file_first_physical_cluster +
164 899965 (file_ptr -> fx_file_consecutive_cluster - 1);
165 899965 bytes_remaining = byte_offset -
166 899965 (file_ptr -> fx_file_consecutive_cluster - 1) * bytes_per_cluster;
167 899965 cluster_count = (file_ptr -> fx_file_consecutive_cluster - 1);
168 }
169
170
171 /* Follow the link of FAT entries. */
172
8/8
✓ Branch 25 → 26 taken 1615927 times.
✓ Branch 25 → 27 taken 4 times.
✓ Branch 26 → 15 taken 1615923 times.
✓ Branch 26 → 27 taken 4 times.
✓ Branch 29 → 30 taken 1621321 times.
✓ Branch 29 → 31 taken 5 times.
✓ Branch 30 → 18 taken 1621316 times.
✓ Branch 30 → 31 taken 5 times.
3237257 while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
173 {
174
175 /* Increment the number of clusters. */
176 3237239 cluster_count++;
177
178 /* Read the current cluster entry from the FAT. */
179 3237239 status = _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
180
181 /* Check the return value. */
182
4/4
✓ Branch 16 → 17 taken 4 times.
✓ Branch 16 → 18 taken 1615919 times.
✓ Branch 19 → 20 taken 5 times.
✓ Branch 19 → 22 taken 1621311 times.
3237239 if (status != FX_SUCCESS)
183 {
184
185 /* Release media protection. */
186 5 FX_UNPROTECT
187
188 /* Return the error status. */
189 9 return(status);
190 }
191
192 /* Save the last valid cluster. */
193 3237230 last_cluster = cluster;
194
195 /* Setup for the next cluster. */
196 3237230 cluster = contents;
197
198 /* Determine if this is the last written cluster. */
199
4/4
✓ Branch 18 → 19 taken 989769 times.
✓ Branch 18 → 20 taken 626150 times.
✓ Branch 22 → 23 taken 995496 times.
✓ Branch 22 → 24 taken 625815 times.
3237230 if (bytes_remaining > bytes_per_cluster)
200 {
201
202 /* Still more seeking, just decrement the working byte offset. */
203 1985265 bytes_remaining = bytes_remaining - bytes_per_cluster;
204 }
205 else
206 {
207
208 /* Remember this cluster number. */
209 1251965 file_ptr -> fx_file_current_physical_cluster = last_cluster;
210
211 /* Remember the relative cluster. */
212 1251965 file_ptr -> fx_file_current_relative_cluster = cluster_count - 1;
213
214 /* If the remaining bytes exactly fits the cluster size, check for
215 a possible adjustment to the next cluster. */
216
8/8
✓ Branch 20 → 21 taken 219 times.
✓ Branch 20 → 24 taken 625931 times.
✓ Branch 21 → 22 taken 215 times.
✓ Branch 21 → 24 taken 4 times.
✓ Branch 24 → 25 taken 225 times.
✓ Branch 24 → 28 taken 625590 times.
✓ Branch 25 → 26 taken 220 times.
✓ Branch 25 → 28 taken 5 times.
1251965 if ((bytes_remaining == bytes_per_cluster) &&
217
4/4
✓ Branch 22 → 23 taken 197 times.
✓ Branch 22 → 24 taken 18 times.
✓ Branch 26 → 27 taken 198 times.
✓ Branch 26 → 28 taken 22 times.
435 (cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
218 {
219
220 /* We need to position to next allocated cluster. */
221 395 file_ptr -> fx_file_current_physical_cluster = cluster;
222 395 file_ptr -> fx_file_current_relative_cluster++;
223
224 /* Clear the remaining bytes. */
225 395 bytes_remaining = 0;
226 }
227
228 /* This is the cluster that contains the seek position. */
229 1251965 break;
230 }
231 }
232
233 /* Check for errors in traversal of the FAT chain. */
234
4/4
✓ Branch 27 → 28 taken 8 times.
✓ Branch 27 → 30 taken 626150 times.
✓ Branch 31 → 32 taken 10 times.
✓ Branch 31 → 35 taken 625815 times.
1251983 if (byte_offset > (((ULONG64) bytes_per_cluster) * ((ULONG64) cluster_count)))
235 {
236
237 /* Release media protection. */
238 10 FX_UNPROTECT
239
240 /* This is an error that suggests a corrupt file. */
241 18 return(FX_FILE_CORRUPT);
242 }
243 }
244 else
245 {
246
247 /* we should directly access the desired cluster */
248 1978412 file_ptr -> fx_file_current_relative_cluster = (ULONG)(byte_offset / bytes_per_cluster);
249
250 1978412 file_ptr -> fx_file_current_physical_cluster =
251 1978412 file_ptr -> fx_file_first_physical_cluster + file_ptr -> fx_file_current_relative_cluster;
252
253 1978412 bytes_remaining = byte_offset % bytes_per_cluster;
254 }
255
256
257 /* Determine if the remaining bytes fit exactly into the cluster size. */
258
4/4
✓ Branch 30 → 31 taken 22 times.
✓ Branch 30 → 32 taken 1615098 times.
✓ Branch 35 → 36 taken 27 times.
✓ Branch 35 → 37 taken 1615230 times.
3230377 if (bytes_remaining == bytes_per_cluster)
259 {
260
261 /* Position to the end of the cluster. */
262 49 file_ptr -> fx_file_current_logical_sector = (ULONG)(((ULONG)media_ptr -> fx_media_data_sector_start) +
263 49 (((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
264 49 ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
265 49 ((bytes_remaining - 1) / (ULONG)media_ptr -> fx_media_bytes_per_sector));
266 49 file_ptr -> fx_file_current_relative_sector = (UINT)(((bytes_remaining - 1) / (ULONG)media_ptr -> fx_media_bytes_per_sector));
267 49 file_ptr -> fx_file_current_file_offset = byte_offset;
268 49 file_ptr -> fx_file_current_logical_offset = media_ptr -> fx_media_bytes_per_sector;
269 }
270 else
271 {
272
273 /* Position the pointers to the new offset. */
274 3230328 file_ptr -> fx_file_current_logical_sector = (ULONG)(((ULONG)media_ptr -> fx_media_data_sector_start) +
275 3230328 (((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
276 3230328 ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
277 3230328 (bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
278 3230328 file_ptr -> fx_file_current_relative_sector = (UINT)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
279 3230328 file_ptr -> fx_file_current_file_offset = byte_offset;
280 3230328 file_ptr -> fx_file_current_logical_offset = (ULONG)(bytes_remaining % ((ULONG)media_ptr -> fx_media_bytes_per_sector));
281 }
282
283 /* Release media protection. */
284 1615257 FX_UNPROTECT
285
286 /* Seek is complete, return successful status. */
287 3230377 return(FX_SUCCESS);
288 }
289
290