GCC Code Coverage Report


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

fx_file_read.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_file.h"
31 #include "fx_utility.h"
32
33
34 /**************************************************************************/
35 /* */
36 /* FUNCTION RELEASE */
37 /* */
38 /* _fx_file_read PORTABLE C */
39 /* 6.1 */
40 /* AUTHOR */
41 /* */
42 /* William E. Lamie, Microsoft Corporation */
43 /* */
44 /* DESCRIPTION */
45 /* */
46 /* This function reads the specified number of bytes (or as many as */
47 /* possible into the buffer supplied by the caller. The actual number */
48 /* of bytes and the status of the read operation is returned to the */
49 /* caller. In addition, various internal file pointers in the file */
50 /* control block are also updated. */
51 /* */
52 /* INPUT */
53 /* */
54 /* file_ptr File control block pointer */
55 /* buffer_ptr Buffer pointer */
56 /* request_size Number of bytes requested */
57 /* actual_size Pointer to variable for the */
58 /* number of bytes read */
59 /* */
60 /* OUTPUT */
61 /* */
62 /* return status */
63 /* */
64 /* CALLS */
65 /* */
66 /* _fx_utility_FAT_entry_read Read a FAT entry */
67 /* _fx_utility_logical_sector_read Read a logical sector */
68 /* _fx_utility_memory_copy Fast memory copy routine */
69 /* */
70 /* CALLED BY */
71 /* */
72 /* Application Code */
73 /* */
74 /**************************************************************************/
75 158524537 UINT _fx_file_read(FX_FILE *file_ptr, VOID *buffer_ptr, ULONG request_size, ULONG *actual_size)
76 {
77
78 UINT status;
79 ULONG bytes_remaining, i;
80 ULONG copy_bytes;
81 UCHAR *destination_ptr;
82 ULONG cluster, next_cluster;
83 UINT sectors;
84 FX_MEDIA *media_ptr;
85
86 #ifdef TX_ENABLE_EVENT_TRACE
87 TX_TRACE_BUFFER_ENTRY *trace_event;
88 ULONG trace_timestamp;
89 #endif
90
91
92 /* First, determine if the file is still open. */
93
2/2
✓ Branch 2 → 3 taken 17 times.
✓ Branch 2 → 4 taken 158524520 times.
158524537 if (file_ptr -> fx_file_id != FX_FILE_ID)
94 {
95
96 /* Return the file not open error status. */
97 17 return(FX_NOT_OPEN);
98 }
99
100 #ifndef FX_MEDIA_STATISTICS_DISABLE
101 /* Setup pointer to media structure. */
102 158524520 media_ptr = file_ptr -> fx_file_media_ptr;
103
104 /* Increment the number of times this service has been called. */
105 158524520 media_ptr -> fx_media_file_reads++;
106 #endif
107
108 /* Setup pointer to associated media control block. */
109 158524520 media_ptr = file_ptr -> fx_file_media_ptr;
110
111 /* If trace is enabled, insert this event into the trace buffer. */
112 FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_READ, file_ptr, buffer_ptr, request_size, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
113
114 /* Protect against other threads accessing the media. */
115 81052094 FX_PROTECT
116
117 /* Next, determine if there is any more bytes to read in the file. */
118 158524518 if (file_ptr -> fx_file_current_file_offset >=
119
4/4
✓ Branch 4 → 5 taken 81 times.
✓ Branch 4 → 6 taken 77472345 times.
✓ Branch 5 → 6 taken 127 times.
✓ Branch 5 → 8 taken 81051965 times.
158524518 file_ptr -> fx_file_current_file_size)
120 {
121
122 /* Release media protection. */
123 127 FX_UNPROTECT
124
125 /* The file is at the end, return the proper status and set the
126 actual size to 0. */
127 208 *actual_size = 0;
128 208 return(FX_END_OF_FILE);
129 }
130
131 /* At this point there is something to read. */
132
133 /* Setup local buffer pointer. */
134 158524310 destination_ptr = (UCHAR *)buffer_ptr;
135
136 /* Determine if there are less bytes left in the file than that specified
137 by the request. If so, adjust the requested size. */
138 158524310 if ((ULONG64)request_size >
139
4/4
✓ Branch 6 → 7 taken 8102 times.
✓ Branch 6 → 8 taken 77464243 times.
✓ Branch 8 → 9 taken 8116 times.
✓ Branch 8 → 10 taken 81043849 times.
158524310 (file_ptr -> fx_file_current_file_size - file_ptr -> fx_file_current_file_offset))
140 {
141
142 /* Adjust the bytes remaining to what's available. */
143 16218 request_size = (ULONG)(file_ptr -> fx_file_current_file_size - file_ptr -> fx_file_current_file_offset);
144 }
145
146 /* Setup the remaining number of bytes to read. */
147 158524310 bytes_remaining = request_size;
148
149 /* Loop to read all of the bytes. */
150
4/4
✓ Branch 57 → 9 taken 79238133 times.
✓ Branch 57 → 58 taken 76261492 times.
✓ Branch 64 → 11 taken 84041777 times.
✓ Branch 64 → 65 taken 77970294 times.
317511696 while (bytes_remaining)
151 {
152
153 /* Determine if a beginning or ending partial read is required. */
154
4/4
✓ Branch 9 → 10 taken 3801263 times.
✓ Branch 9 → 11 taken 75436870 times.
✓ Branch 11 → 12 taken 8438541 times.
✓ Branch 11 → 13 taken 75603236 times.
163279910 if ((file_ptr -> fx_file_current_logical_offset) ||
155
4/4
✓ Branch 10 → 11 taken 1206951 times.
✓ Branch 10 → 18 taken 2594312 times.
✓ Branch 12 → 13 taken 2812359 times.
✓ Branch 12 → 21 taken 5626182 times.
12239804 (bytes_remaining < media_ptr -> fx_media_bytes_per_sector))
156 {
157
158 /* A partial sector read is required. */
159
160 /* Read the current logical sector. */
161 155059416 status = _fx_utility_logical_sector_read(media_ptr,
162 file_ptr -> fx_file_current_logical_sector,
163 155059416 media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
164
165 /* Check for good completion status. */
166
4/4
✓ Branch 12 → 13 taken 147612 times.
✓ Branch 12 → 14 taken 76496209 times.
✓ Branch 14 → 15 taken 170823 times.
✓ Branch 14 → 17 taken 78244772 times.
155059416 if (status != FX_SUCCESS)
167 {
168
169 /* Release media protection. */
170 170823 FX_UNPROTECT
171
172 /* Return the error status. */
173 318435 return(status);
174 }
175
176 /* Copy the appropriate number of bytes into the destination buffer. */
177 154740981 copy_bytes = media_ptr -> fx_media_bytes_per_sector -
178 154740981 file_ptr -> fx_file_current_logical_offset;
179
180 /* Check to see if only a portion of the read sector needs to be
181 copied. */
182
4/4
✓ Branch 14 → 15 taken 75036684 times.
✓ Branch 14 → 16 taken 1459525 times.
✓ Branch 17 → 18 taken 76734566 times.
✓ Branch 17 → 19 taken 1510206 times.
154740981 if (copy_bytes > bytes_remaining)
183 {
184
185 /* Adjust the number of bytes to copy. */
186 151771250 copy_bytes = bytes_remaining;
187 }
188
189 /* Actually perform the memory copy. */
190 154740981 _fx_utility_memory_copy(((UCHAR *)media_ptr -> fx_media_memory_buffer) + /* Use case of memcpy is verified. */
191 154740981 file_ptr -> fx_file_current_logical_offset,
192 destination_ptr, copy_bytes);
193
194 /* Increment the logical sector byte offset. */
195 154740981 file_ptr -> fx_file_current_logical_offset =
196 154740981 file_ptr -> fx_file_current_logical_offset + copy_bytes;
197
198 /* Adjust the remaining bytes to read. */
199 154740981 bytes_remaining = bytes_remaining - copy_bytes;
200
201 /* Adjust the pointer to the destination buffer. */
202 154740981 destination_ptr = destination_ptr + copy_bytes;
203 }
204 else
205 {
206
207 /* Attempt to read multiple sectors directly into the destination
208 buffer. */
209
210 /* Calculate the number of whole sectors to read directly into
211 the destination buffer. */
212 8220494 sectors = (UINT)(bytes_remaining / media_ptr -> fx_media_bytes_per_sector);
213
214
215 8220494 next_cluster = cluster = file_ptr -> fx_file_current_physical_cluster;
216 8220494 for (i = (media_ptr -> fx_media_sectors_per_cluster -
217
4/4
✓ Branch 29 → 19 taken 6911228 times.
✓ Branch 29 → 30 taken 923788 times.
✓ Branch 33 → 22 taken 31719647 times.
✓ Branch 33 → 34 taken 3954323 times.
43508986 file_ptr -> fx_file_current_relative_sector); i < sectors; i += media_ptr -> fx_media_sectors_per_cluster)
218 {
219 38630875 status = _fx_utility_FAT_entry_read(media_ptr, cluster, &next_cluster);
220
221 /* Determine if an error is present. */
222
8/8
✓ Branch 20 → 21 taken 6911224 times.
✓ Branch 20 → 23 taken 4 times.
✓ Branch 21 → 22 taken 6911220 times.
✓ Branch 21 → 23 taken 4 times.
✓ Branch 23 → 24 taken 31719642 times.
✓ Branch 23 → 26 taken 5 times.
✓ Branch 24 → 25 taken 31719637 times.
✓ Branch 24 → 26 taken 5 times.
38630875 if ((status != FX_SUCCESS) || (next_cluster < FX_FAT_ENTRY_START) ||
223
4/4
✓ Branch 22 → 23 taken 4 times.
✓ Branch 22 → 26 taken 6911216 times.
✓ Branch 25 → 26 taken 5 times.
✓ Branch 25 → 30 taken 31719632 times.
38630857 (next_cluster > media_ptr -> fx_media_fat_reserved))
224 {
225
226 /* Release media protection. */
227 15 FX_UNPROTECT
228
229 /* Send error message back to caller. */
230
4/4
✓ Branch 23 → 24 taken 4 times.
✓ Branch 23 → 25 taken 8 times.
✓ Branch 27 → 28 taken 5 times.
✓ Branch 27 → 29 taken 10 times.
27 if (status != FX_SUCCESS)
231 {
232 9 return(status);
233 }
234 else
235 {
236 18 return(FX_FILE_CORRUPT);
237 }
238 }
239
240
4/4
✓ Branch 26 → 27 taken 1670512 times.
✓ Branch 26 → 28 taken 5240704 times.
✓ Branch 30 → 31 taken 1671844 times.
✓ Branch 30 → 32 taken 30047788 times.
38630848 if (next_cluster != cluster + 1)
241 {
242 3342356 break;
243 }
244 else
245 {
246 35288492 cluster = next_cluster;
247 }
248 }
249
250
4/4
✓ Branch 30 → 31 taken 1670512 times.
✓ Branch 30 → 32 taken 923788 times.
✓ Branch 34 → 35 taken 1671844 times.
✓ Branch 34 → 36 taken 3954323 times.
8220467 if (i < sectors)
251 {
252 3342356 sectors = i;
253 }
254
255 /* Determine if this is a single sector read request. If so, read the sector so it will
256 come from the internal cache. */
257
4/4
✓ Branch 32 → 33 taken 467235 times.
✓ Branch 32 → 37 taken 2127065 times.
✓ Branch 36 → 37 taken 695998 times.
✓ Branch 36 → 42 taken 4930169 times.
8220467 if (sectors == 1)
258 {
259
260 /* Read the current logical sector. */
261 1163233 status = _fx_utility_logical_sector_read(media_ptr,
262 file_ptr -> fx_file_current_logical_sector,
263 1163233 media_ptr -> fx_media_memory_buffer, ((ULONG) 1), FX_DATA_SECTOR);
264
265 /* Check for good completion status. */
266
4/4
✓ Branch 34 → 35 taken 1874 times.
✓ Branch 34 → 36 taken 465361 times.
✓ Branch 38 → 39 taken 2928 times.
✓ Branch 38 → 41 taken 693070 times.
1163233 if (status != FX_SUCCESS)
267 {
268
269 /* Release media protection. */
270 2928 FX_UNPROTECT
271
272 /* Return the error status. */
273 4802 return(status);
274 }
275
276 /* Actually perform the memory copy. */
277 1158431 _fx_utility_memory_copy((UCHAR *)media_ptr -> fx_media_memory_buffer, destination_ptr, media_ptr -> fx_media_bytes_per_sector); /* Use case of memcpy is verified. */
278 }
279 else
280 {
281
282 /* Multiple sector read request. Read all the sectors at once. */
283
284 /* Perform the data read directly into the user's buffer of
285 the appropriate number of sectors. */
286 7057234 media_ptr -> fx_media_disable_burst_cache = file_ptr -> fx_file_disable_burst_cache;
287 7057234 status = _fx_utility_logical_sector_read(media_ptr, file_ptr -> fx_file_current_logical_sector,
288 destination_ptr, (ULONG) sectors, FX_DATA_SECTOR);
289 7057234 media_ptr -> fx_media_disable_burst_cache = FX_FALSE;
290
291 /* Check for good completion status. */
292
4/4
✓ Branch 38 → 39 taken 4 times.
✓ Branch 38 → 40 taken 2127061 times.
✓ Branch 43 → 44 taken 5 times.
✓ Branch 43 → 46 taken 4930164 times.
7057234 if (status != FX_SUCCESS)
293 {
294
295 /* Release media protection. */
296 5 FX_UNPROTECT
297
298 /* Return the error status. */
299 9 return(status);
300 }
301 }
302
303 /* Now adjust the various file pointers. */
304
305 /* Increment the current logical sector. Subtract one from
306 the sector count because we are going to use the logical
307 offset to do additional sector/cluster arithmetic below. */
308 8215656 file_ptr -> fx_file_current_logical_sector =
309 8215656 file_ptr -> fx_file_current_logical_sector +
310 8215656 (sectors - 1);
311
312 /* Move the relative sector and cluster as well. */
313 8215656 file_ptr -> fx_file_current_relative_cluster = file_ptr -> fx_file_current_relative_cluster +
314 8215656 (file_ptr -> fx_file_current_relative_sector + (sectors - 1)) /
315 8215656 media_ptr -> fx_media_sectors_per_cluster;
316
317 8215656 file_ptr -> fx_file_current_relative_sector =
318 8215656 (file_ptr -> fx_file_current_relative_sector +
319 8215656 (sectors - 1)) % media_ptr -> fx_media_sectors_per_cluster;
320
321 /* Increment the logical sector byte offset. */
322 8215656 file_ptr -> fx_file_current_logical_offset =
323 8215656 media_ptr -> fx_media_bytes_per_sector;
324
325 8215656 file_ptr -> fx_file_current_physical_cluster = cluster;
326
327 /* Adjust the remaining bytes. */
328 8215656 bytes_remaining = bytes_remaining -
329 8215656 (((ULONG)media_ptr -> fx_media_bytes_per_sector) * sectors);
330
331 /* Adjust the pointer to the destination buffer. */
332 8215656 destination_ptr = destination_ptr +
333 8215656 (((ULONG)media_ptr -> fx_media_bytes_per_sector) * sectors);
334 }
335
336 /* At this point, we have either read a partial sector or have successfully
337 read one or more whole sectors. Determine if we are at the end of
338 the current logical sector. */
339 162956637 if (file_ptr -> fx_file_current_logical_offset >=
340
4/4
✓ Branch 41 → 42 taken 4051947 times.
✓ Branch 41 → 56 taken 75036684 times.
✓ Branch 47 → 48 taken 7133440 times.
✓ Branch 47 → 63 taken 76734566 times.
162956637 media_ptr -> fx_media_bytes_per_sector)
341 {
342
343 /* Determine if we are at the exact physical end of the file at the end of reading. */
344
4/4
✓ Branch 42 → 43 taken 2117469 times.
✓ Branch 42 → 45 taken 1934478 times.
✓ Branch 48 → 49 taken 3950368 times.
✓ Branch 48 → 51 taken 3183072 times.
11185387 if ((bytes_remaining == 0) && ((file_ptr -> fx_file_current_file_offset + (ULONG64)request_size) >=
345
4/4
✓ Branch 43 → 44 taken 874867 times.
✓ Branch 43 → 45 taken 1242602 times.
✓ Branch 49 → 50 taken 2693178 times.
✓ Branch 49 → 51 taken 1257190 times.
6067837 file_ptr -> fx_file_current_available_size))
346 {
347
348 /* Skip the following file parameter adjustments. The next write will
349 detect the logical offset out of the range of the sector and reset
350 all of the pertinent information. */
351 3568045 break;
352 }
353
354 /* We need to move to the next logical sector, but first
355 determine if the next logical sector is within the same
356 cluster. */
357
358 /* Increment the current relative sector in the cluster. */
359 7617342 file_ptr -> fx_file_current_relative_sector++;
360
361 /* Determine if this is in a new cluster. */
362 7617342 if (file_ptr -> fx_file_current_relative_sector >=
363
4/4
✓ Branch 45 → 46 taken 2110958 times.
✓ Branch 45 → 54 taken 1066122 times.
✓ Branch 51 → 52 taken 3367596 times.
✓ Branch 51 → 61 taken 1072666 times.
7617342 media_ptr -> fx_media_sectors_per_cluster)
364 {
365
366 /* Read the FAT entry of the current cluster to find
367 the next cluster. */
368 5478554 status = _fx_utility_FAT_entry_read(media_ptr,
369 file_ptr -> fx_file_current_physical_cluster, &next_cluster);
370
371 /* Determine if an error is present. */
372
8/8
✓ Branch 47 → 48 taken 2086439 times.
✓ Branch 47 → 50 taken 24519 times.
✓ Branch 48 → 49 taken 2086435 times.
✓ Branch 48 → 50 taken 4 times.
✓ Branch 53 → 54 taken 3339113 times.
✓ Branch 53 → 56 taken 28483 times.
✓ Branch 54 → 55 taken 3339108 times.
✓ Branch 54 → 56 taken 5 times.
5478554 if ((status != FX_SUCCESS) || (next_cluster < FX_FAT_ENTRY_START) ||
373
4/4
✓ Branch 49 → 50 taken 161961 times.
✓ Branch 49 → 53 taken 1924474 times.
✓ Branch 55 → 56 taken 186234 times.
✓ Branch 55 → 60 taken 3152874 times.
5425543 (next_cluster > media_ptr -> fx_media_fat_reserved))
374 {
375
376 /* Release media protection. */
377 214722 FX_UNPROTECT
378
379 /* Send error message back to caller. */
380
4/4
✓ Branch 50 → 51 taken 24519 times.
✓ Branch 50 → 52 taken 161965 times.
✓ Branch 57 → 58 taken 28483 times.
✓ Branch 57 → 59 taken 186239 times.
401206 if (status != FX_SUCCESS)
381 {
382 53002 return(status);
383 }
384 else
385 {
386 348204 return(FX_FILE_CORRUPT);
387 }
388 }
389
390 /* Otherwise, we have a new cluster. Save it in the file
391 control block and calculate a new logical sector value. */
392 5077348 file_ptr -> fx_file_current_physical_cluster = next_cluster;
393 5077348 file_ptr -> fx_file_current_relative_cluster++;
394 5077348 file_ptr -> fx_file_current_logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
395 5077348 ((((ULONG64)next_cluster) - FX_FAT_ENTRY_START) *
396 5077348 ((ULONG)media_ptr -> fx_media_sectors_per_cluster));
397 5077348 file_ptr -> fx_file_current_relative_sector = 0;
398 }
399 else
400 {
401
402 /* Still within the same cluster so just increment the
403 logical sector. */
404 2138788 file_ptr -> fx_file_current_logical_sector++;
405 }
406
407 /* In either case, we are now positioned at a new sector so
408 clear the logical sector offset. */
409 7216136 file_ptr -> fx_file_current_logical_offset = 0;
410 }
411 }
412
413 /* Adjust the current file offset accordingly. */
414 157799831 file_ptr -> fx_file_current_file_offset =
415 157799831 file_ptr -> fx_file_current_file_offset + (ULONG64)request_size;
416
417 /* Store the number of bytes actually read. */
418 157799831 *actual_size = request_size;
419
420 /* Update the trace event with the bytes read. */
421 FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_READ, 0, 0, 0, request_size)
422
423 /* Update the last accessed date. */
424 157799831 file_ptr -> fx_file_dir_entry.fx_dir_entry_last_accessed_date = _fx_system_date;
425
426 /* Release media protection. */
427 80663472 FX_UNPROTECT
428
429 /* Return a successful status to the caller. */
430 157799830 return(FX_SUCCESS);
431 }
432
433