GCC Code Coverage Report


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

fx_file_extended_truncate_release.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 #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_extended_truncate_release PORTABLE C */
43 /* 6.1.3 */
44 /* AUTHOR */
45 /* */
46 /* William E. Lamie, Microsoft Corporation */
47 /* */
48 /* DESCRIPTION */
49 /* */
50 /* This function sets the file to the specified size, if smaller than */
51 /* the current file size. If the new file size is less than the */
52 /* current file read/write position, the internal file pointers will */
53 /* also be modified. Any unused clusters are released back to the */
54 /* media. */
55 /* */
56 /* INPUT */
57 /* */
58 /* file_ptr File control block pointer */
59 /* size New size of the file in bytes */
60 /* */
61 /* OUTPUT */
62 /* */
63 /* return status */
64 /* */
65 /* CALLS */
66 /* */
67 /* _fx_directory_entry_write Write directory entry */
68 /* _fx_utility_FAT_entry_read Read a FAT entry */
69 /* _fx_utility_FAT_entry_write Write a FAT entry */
70 /* _fx_utility_FAT_flush Flush written FAT entries */
71 /* _fx_fault_tolerant_transaction_start Start fault tolerant */
72 /* transaction */
73 /* _fx_fault_tolerant_transaction_end End fault tolerant transaction*/
74 /* _fx_fault_tolerant_recover Recover FAT chain */
75 /* _fx_fault_tolerant_reset_log_file Reset the log file */
76 /* _fx_fault_tolerant_set_FAT_chain Set data of FAT chain */
77 /* */
78 /* CALLED BY */
79 /* */
80 /* Application Code */
81 /* */
82 /**************************************************************************/
83 3400910 UINT _fx_file_extended_truncate_release(FX_FILE *file_ptr, ULONG64 size)
84 {
85
86 UINT status;
87 ULONG cluster;
88 ULONG contents;
89 ULONG bytes_per_cluster;
90 ULONG last_cluster;
91 ULONG cluster_count;
92 ULONG64 bytes_remaining;
93 FX_MEDIA *media_ptr;
94
95
96 #ifndef FX_DONT_UPDATE_OPEN_FILES
97 ULONG open_count;
98 FX_FILE *search_ptr;
99 #endif
100
101 #ifdef TX_ENABLE_EVENT_TRACE
102 TX_TRACE_BUFFER_ENTRY *trace_event;
103 ULONG trace_timestamp;
104 #endif
105
106
107 /* First, determine if the file is still open. */
108
2/2
✓ Branch 2 → 3 taken 9 times.
✓ Branch 2 → 4 taken 3400901 times.
3400910 if (file_ptr -> fx_file_id != FX_FILE_ID)
109 {
110
111 /* Return the file not open error status. */
112 9 return(FX_NOT_OPEN);
113 }
114
115 #ifndef FX_MEDIA_STATISTICS_DISABLE
116 /* Setup pointer to media structure. */
117 3400901 media_ptr = file_ptr -> fx_file_media_ptr;
118
119 /* Increment the number of times this service has been called. */
120 3400901 media_ptr -> fx_media_file_truncate_releases++;
121 #endif
122
123 /* Setup pointer to associated media control block. */
124 3400901 media_ptr = file_ptr -> fx_file_media_ptr;
125
126 /* If trace is enabled, insert this event into the trace buffer. */
127 FX_TRACE_IN_LINE_INSERT(FX_TRACE_FILE_TRUNCATE_RELEASE, file_ptr, size, file_ptr -> fx_file_current_file_size, 0, FX_TRACE_FILE_EVENTS, &trace_event, &trace_timestamp)
128
129 /* Protect against other threads accessing the media. */
130 3400693 FX_PROTECT
131
132 #ifdef FX_ENABLE_FAULT_TOLERANT
133 /* Start transaction. */
134 3400750 _fx_fault_tolerant_transaction_start(media_ptr);
135 #endif /* FX_ENABLE_FAULT_TOLERANT */
136
137 /* Make sure this file is open for writing. */
138
6/6
✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 6 taken 58 times.
✓ Branch 5 → 6 taken 7 times.
✓ Branch 5 → 8 taken 231 times.
✓ Branch 6 → 7 taken 4 times.
✓ Branch 6 → 10 taken 3400598 times.
3400900 if (file_ptr -> fx_file_open_mode != FX_OPEN_FOR_WRITE)
139 {
140
141 #ifdef FX_ENABLE_FAULT_TOLERANT
142 8 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
143 #endif /* FX_ENABLE_FAULT_TOLERANT */
144
145 /* Release media protection. */
146 7 FX_UNPROTECT
147
148 /* Return the access error exception - a write was attempted from
149 a file opened for reading! */
150 13 return(FX_ACCESS_ERROR);
151 }
152
153 /* Check for write protect at the media level (set by driver). */
154
6/6
✓ Branch 6 → 7 taken 2 times.
✓ Branch 6 → 8 taken 56 times.
✓ Branch 8 → 9 taken 7 times.
✓ Branch 8 → 11 taken 224 times.
✓ Branch 10 → 11 taken 4 times.
✓ Branch 10 → 14 taken 3400594 times.
3400887 if (media_ptr -> fx_media_driver_write_protect)
155 {
156
157 #ifdef FX_ENABLE_FAULT_TOLERANT
158 8 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
159 #endif /* FX_ENABLE_FAULT_TOLERANT */
160
161 /* Release media protection. */
162 7 FX_UNPROTECT
163
164 /* Return write protect error. */
165 13 return(FX_WRITE_PROTECT);
166 }
167
168 /* Calculate the number of bytes per cluster. */
169 3400874 bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
170 3400874 ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
171
172 /* Check for invalid value. */
173
6/6
✓ Branch 8 → 9 taken 2 times.
✓ Branch 8 → 10 taken 54 times.
✓ Branch 11 → 12 taken 5 times.
✓ Branch 11 → 14 taken 219 times.
✓ Branch 14 → 15 taken 2 times.
✓ Branch 14 → 18 taken 3400592 times.
3400874 if (bytes_per_cluster == 0)
174 {
175
176 #ifdef FX_ENABLE_FAULT_TOLERANT
177 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
178 #endif /* FX_ENABLE_FAULT_TOLERANT */
179
180 /* Release media protection. */
181 5 FX_UNPROTECT
182
183 /* Invalid media, return error. */
184 9 return(FX_MEDIA_INVALID);
185 }
186
187 /* Setup the new file available size - if less than the current available size. */
188
6/6
✓ Branch 10 → 11 taken 52 times.
✓ Branch 10 → 17 taken 2 times.
✓ Branch 14 → 15 taken 210 times.
✓ Branch 14 → 22 taken 9 times.
✓ Branch 18 → 19 taken 3400553 times.
✓ Branch 18 → 27 taken 39 times.
3400865 if (size < file_ptr -> fx_file_current_available_size)
189 {
190
191 /* Yes, the file needs to be truncated. */
192
193 /* Update the available file size. */
194 3400815 file_ptr -> fx_file_current_available_size = ((size + bytes_per_cluster - 1) / bytes_per_cluster) * bytes_per_cluster;
195
196 /* Is the new available size less than the actual file size? */
197
6/6
✓ Branch 11 → 12 taken 48 times.
✓ Branch 11 → 18 taken 4 times.
✓ Branch 15 → 16 taken 202 times.
✓ Branch 15 → 24 taken 8 times.
✓ Branch 19 → 20 taken 3400551 times.
✓ Branch 19 → 30 taken 2 times.
3400815 if (size < file_ptr -> fx_file_current_file_size)
198 {
199
200 /* Setup the new file size. */
201 3400801 file_ptr -> fx_file_current_file_size = size;
202
203 /* Set the modified flag. */
204 3400801 file_ptr -> fx_file_modified = FX_TRUE;
205
206 /* Copy the new file size into the directory entry. */
207 3400801 file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = size;
208
209 /* Set the first cluster to NULL. */
210
6/6
✓ Branch 12 → 13 taken 20 times.
✓ Branch 12 → 14 taken 28 times.
✓ Branch 16 → 17 taken 66 times.
✓ Branch 16 → 18 taken 136 times.
✓ Branch 20 → 21 taken 3400457 times.
✓ Branch 20 → 22 taken 94 times.
3400801 if (size == 0)
211 {
212
213 /* Yes, the first cluster needs to be cleared since the entire
214 file is going to be truncated. */
215 3400543 file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster = FX_NULL;
216 }
217
218 /* Write the directory entry to the media. */
219 3400801 status = _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
220
221 /* Check for a good status. */
222
6/6
✓ Branch 15 → 16 taken 2 times.
✓ Branch 15 → 18 taken 46 times.
✓ Branch 19 → 20 taken 8 times.
✓ Branch 19 → 24 taken 194 times.
✓ Branch 23 → 24 taken 5 times.
✓ Branch 23 → 30 taken 3400546 times.
3400801 if (status != FX_SUCCESS)
223 {
224
225 #ifdef FX_ENABLE_FAULT_TOLERANT
226 10 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
227 #endif /* FX_ENABLE_FAULT_TOLERANT */
228
229 /* Release media protection. */
230 8 FX_UNPROTECT
231
232 /* Error writing the directory. */
233 15 return(status);
234 }
235 }
236
237 /* Update the trace event with the truncated size. */
238 FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_TRUNCATE_RELEASE, 0, 0, 0, file_ptr -> fx_file_current_file_size)
239 }
240 else
241 {
242
243 /* Update the trace event with the truncated size. */
244 FX_TRACE_EVENT_UPDATE(trace_event, trace_timestamp, FX_TRACE_FILE_TRUNCATE_RELEASE, 0, 0, 0, file_ptr -> fx_file_current_file_size)
245
246 #ifdef FX_ENABLE_FAULT_TOLERANT
247 45 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
248 #endif /* FX_ENABLE_FAULT_TOLERANT */
249
250 /* Release media protection. */
251 42 FX_UNPROTECT
252
253 /* Just return, the truncate size is larger than the available size. */
254 50 return(FX_SUCCESS);
255 }
256
257 /* Calculate the number of bytes per cluster. */
258 3400800 bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
259 3400800 ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
260
261 /* Now check to see if the read/write internal file pointers need
262 to be adjusted. */
263
6/6
✓ Branch 18 → 19 taken 46 times.
✓ Branch 18 → 31 taken 4 times.
✓ Branch 24 → 25 taken 167 times.
✓ Branch 24 → 39 taken 35 times.
✓ Branch 30 → 31 taken 3400519 times.
✓ Branch 30 → 47 taken 29 times.
3400800 if (file_ptr -> fx_file_current_file_offset > file_ptr -> fx_file_current_file_size)
264 {
265
266
267 /* At this point, we are ready to walk list of clusters to setup the
268 seek position of this file. */
269 3400732 cluster = file_ptr -> fx_file_first_physical_cluster;
270 3400732 bytes_remaining = size;
271 3400732 last_cluster = 0;
272 3400732 cluster_count = 0;
273
274 /* Follow the link of FAT entries. */
275
12/12
✓ Branch 26 → 27 taken 674 times.
✓ Branch 26 → 28 taken 2 times.
✓ Branch 27 → 20 taken 672 times.
✓ Branch 27 → 28 taken 2 times.
✓ Branch 33 → 34 taken 1737 times.
✓ Branch 33 → 35 taken 5 times.
✓ Branch 34 → 26 taken 1732 times.
✓ Branch 34 → 35 taken 5 times.
✓ Branch 40 → 41 taken 3401147 times.
✓ Branch 40 → 42 taken 2 times.
✓ Branch 41 → 32 taken 3401145 times.
✓ Branch 41 → 42 taken 2 times.
3403567 while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
276 {
277
278 /* Increment the number of clusters. */
279 3403549 cluster_count++;
280
281
282 /* Read the current cluster entry from the FAT. */
283 3403549 status = _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
284
285 /* Check the return value. */
286
6/6
✓ Branch 21 → 22 taken 2 times.
✓ Branch 21 → 23 taken 670 times.
✓ Branch 27 → 28 taken 7 times.
✓ Branch 27 → 30 taken 1725 times.
✓ Branch 33 → 34 taken 4 times.
✓ Branch 33 → 37 taken 3401141 times.
3403549 if (status != FX_SUCCESS)
287 {
288
289 #ifdef FX_ENABLE_FAULT_TOLERANT
290 8 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
291 #endif /* FX_ENABLE_FAULT_TOLERANT */
292
293 /* Release media protection. */
294 7 FX_UNPROTECT
295
296 /* Return the error status. */
297 13 return(status);
298 }
299
300 /* Save the last valid cluster. */
301 3403536 last_cluster = cluster;
302
303 /* Setup for the next cluster. */
304 3403536 cluster = contents;
305
306 /* Determine if this is the last written cluster. */
307
6/6
✓ Branch 23 → 24 taken 630 times.
✓ Branch 23 → 25 taken 40 times.
✓ Branch 30 → 31 taken 1575 times.
✓ Branch 30 → 32 taken 150 times.
✓ Branch 37 → 38 taken 630 times.
✓ Branch 37 → 39 taken 3400511 times.
3403536 if (bytes_remaining >= bytes_per_cluster)
308 {
309
310 /* Still more seeking, just decrement the working byte offset. */
311 2835 bytes_remaining = bytes_remaining - bytes_per_cluster;
312 }
313 else
314 {
315
316 /* This is the cluster that contains the seek position. */
317 3400701 break;
318 }
319 }
320
321 /* Check for errors in traversal of the FAT chain. */
322
6/6
✓ Branch 28 → 29 taken 4 times.
✓ Branch 28 → 30 taken 40 times.
✓ Branch 35 → 36 taken 10 times.
✓ Branch 35 → 38 taken 150 times.
✓ Branch 42 → 43 taken 4 times.
✓ Branch 42 → 46 taken 3400511 times.
3400719 if (size > (((ULONG64) bytes_per_cluster) * ((ULONG64) cluster_count)))
323 {
324
325 #ifdef FX_ENABLE_FAULT_TOLERANT
326 8 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
327 #endif /* FX_ENABLE_FAULT_TOLERANT */
328
329 /* Release media protection. */
330 10 FX_UNPROTECT
331
332 /* This is an error that suggests a corrupt file. */
333 18 return(FX_FILE_CORRUPT);
334 }
335
336 /* Position the pointers to the new offset. */
337 3400701 file_ptr -> fx_file_current_physical_cluster = last_cluster;
338 3400701 file_ptr -> fx_file_current_relative_cluster = cluster_count - 1;
339 3400701 file_ptr -> fx_file_current_logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
340 3400701 (((ULONG64)file_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
341 3400701 ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
342 3400701 (bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector);
343 3400701 file_ptr -> fx_file_current_relative_sector = (UINT)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
344 3400701 file_ptr -> fx_file_current_file_offset = size;
345 3400701 file_ptr -> fx_file_current_logical_offset = (ULONG)bytes_remaining % ((ULONG)media_ptr -> fx_media_bytes_per_sector);
346 }
347
348 /* Determine how many clusters are actually in-use now. */
349 3400769 cluster_count = (ULONG) (file_ptr -> fx_file_current_available_size + (((ULONG64) bytes_per_cluster) - ((ULONG64) 1)))/bytes_per_cluster;
350
351 /* Save the number of clusters in-use. */
352 3400769 file_ptr -> fx_file_total_clusters = cluster_count;
353
354 /* At this point, we are ready to walk list of clusters to find the clusters
355 that can be released. */
356 3400769 cluster = file_ptr -> fx_file_first_physical_cluster;
357
358 #ifdef FX_ENABLE_FAULT_TOLERANT
359 /* Is this the last used cluster? */
360
8/8
✓ Branch 39 → 40 taken 36 times.
✓ Branch 39 → 46 taken 83 times.
✓ Branch 40 → 41 taken 16 times.
✓ Branch 40 → 46 taken 20 times.
✓ Branch 47 → 48 taken 3400457 times.
✓ Branch 47 → 55 taken 83 times.
✓ Branch 48 → 49 taken 3400437 times.
✓ Branch 48 → 55 taken 20 times.
3400659 if ((cluster_count == 0) && (media_ptr -> fx_media_fault_tolerant_enabled))
361 {
362
363 /* Set undo log. */
364 3400453 status = _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_FALSE, FX_FREE_CLUSTER,
365 media_ptr -> fx_media_fat_last, cluster, media_ptr -> fx_media_fat_last);
366
367 /* Determine if the write was successful. */
368
4/4
✓ Branch 42 → 43 taken 2 times.
✓ Branch 42 → 45 taken 14 times.
✓ Branch 50 → 51 taken 2 times.
✓ Branch 50 → 54 taken 3400427 times.
3400445 if (status != FX_SUCCESS)
369 {
370
371 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
372
373 /* Release media protection. */
374 2 FX_UNPROTECT
375
376 /* Return the error code. */
377 4 return(status);
378 }
379
380 3400441 file_ptr -> fx_file_last_physical_cluster = cluster;
381 }
382 #endif /* FX_ENABLE_FAULT_TOLERANT */
383
384 /* Follow the link of FAT entries. */
385
16/16
✓ Branch 46 → 47 taken 29292 times.
✓ Branch 46 → 48 taken 2 times.
✓ Branch 47 → 32 taken 29256 times.
✓ Branch 47 → 48 taken 36 times.
✓ Branch 57 → 58 taken 43938 times.
✓ Branch 57 → 59 taken 3 times.
✓ Branch 58 → 40 taken 43884 times.
✓ Branch 58 → 59 taken 54 times.
✓ Branch 79 → 80 taken 29487 times.
✓ Branch 79 → 81 taken 2 times.
✓ Branch 80 → 47 taken 29397 times.
✓ Branch 80 → 81 taken 90 times.
✓ Branch 94 → 95 taken 32833235 times.
✓ Branch 94 → 96 taken 2 times.
✓ Branch 95 → 56 taken 29432732 times.
✓ Branch 95 → 96 taken 3400503 times.
32935961 while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
386 {
387
388 /* Read the current cluster entry from the FAT. */
389 29535269 status = _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
390
391 /* Check the return value. */
392
8/8
✓ Branch 33 → 34 taken 2 times.
✓ Branch 33 → 35 taken 29254 times.
✓ Branch 41 → 42 taken 3 times.
✓ Branch 41 → 44 taken 43881 times.
✓ Branch 48 → 49 taken 13 times.
✓ Branch 48 → 51 taken 29384 times.
✓ Branch 57 → 58 taken 13 times.
✓ Branch 57 → 61 taken 29432719 times.
29535269 if (status != FX_SUCCESS)
393 {
394
395 #ifdef FX_ENABLE_FAULT_TOLERANT
396 26 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
397 #endif /* FX_ENABLE_FAULT_TOLERANT */
398
399 /* Release media protection. */
400 16 FX_UNPROTECT
401
402 /* Return the error status. */
403 31 return(status);
404 }
405
406 /* Determine if are more clusters to release. */
407
8/8
✓ Branch 35 → 36 taken 644 times.
✓ Branch 35 → 41 taken 28610 times.
✓ Branch 44 → 45 taken 966 times.
✓ Branch 44 → 51 taken 42915 times.
✓ Branch 51 → 52 taken 700 times.
✓ Branch 51 → 72 taken 28684 times.
✓ Branch 61 → 62 taken 700 times.
✓ Branch 61 → 86 taken 29432019 times.
29535238 if (cluster_count > 0)
408 {
409
410 /* Decrement the number of clusters. */
411 3010 cluster_count--;
412
413 /* Is this the last used cluster? */
414
8/8
✓ Branch 36 → 37 taken 20 times.
✓ Branch 36 → 45 taken 624 times.
✓ Branch 45 → 46 taken 30 times.
✓ Branch 45 → 56 taken 936 times.
✓ Branch 52 → 53 taken 76 times.
✓ Branch 52 → 78 taken 624 times.
✓ Branch 62 → 63 taken 76 times.
✓ Branch 62 → 93 taken 624 times.
3010 if (cluster_count == 0)
415 {
416 {
417
418 #ifdef FX_ENABLE_FAULT_TOLERANT
419
4/4
✓ Branch 53 → 54 taken 54 times.
✓ Branch 53 → 62 taken 22 times.
✓ Branch 63 → 64 taken 54 times.
✓ Branch 63 → 74 taken 22 times.
152 if (media_ptr -> fx_media_fault_tolerant_enabled)
420 {
421
422 /* Set undo phase. */
423 108 media_ptr -> fx_media_fault_tolerant_state |= FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN;
424
425 /* Read the current cluster entry from the FAT. */
426 108 status = _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
427
428 /* Check the return value. */
429
4/4
✓ Branch 55 → 56 taken 2 times.
✓ Branch 55 → 58 taken 52 times.
✓ Branch 65 → 66 taken 2 times.
✓ Branch 65 → 69 taken 52 times.
108 if (status != FX_SUCCESS)
430 {
431
432 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
433
434 /* Release media protection. */
435 2 FX_UNPROTECT
436
437 /* Return the error status. */
438 4 return(status);
439 }
440
441 /* Set undo log. */
442 104 status = _fx_fault_tolerant_set_FAT_chain(media_ptr, FX_FALSE, cluster,
443 media_ptr -> fx_media_fat_last, contents, media_ptr -> fx_media_fat_last);
444
445 /* Determine if the write was successful. */
446
4/4
✓ Branch 59 → 60 taken 2 times.
✓ Branch 59 → 62 taken 50 times.
✓ Branch 70 → 71 taken 2 times.
✓ Branch 70 → 74 taken 50 times.
104 if (status != FX_SUCCESS)
447 {
448
449 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
450
451 /* Release media protection. */
452 2 FX_UNPROTECT
453
454 /* Return the error code. */
455 4 return(status);
456 }
457 }
458 #endif /* FX_ENABLE_FAULT_TOLERANT */
459
460 /* Yes, it should be designated as last cluster. */
461 194 status = _fx_utility_FAT_entry_write(media_ptr, cluster, media_ptr -> fx_media_fat_last);
462
463 /* Check the return value. */
464
8/8
✓ Branch 38 → 39 taken 2 times.
✓ Branch 38 → 40 taken 18 times.
✓ Branch 47 → 48 taken 3 times.
✓ Branch 47 → 50 taken 27 times.
✓ Branch 63 → 64 taken 4 times.
✓ Branch 63 → 66 taken 68 times.
✓ Branch 75 → 76 taken 4 times.
✓ Branch 75 → 79 taken 68 times.
194 if (status)
465 {
466
467 #ifdef FX_ENABLE_FAULT_TOLERANT
468 8 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
469 #endif /* FX_ENABLE_FAULT_TOLERANT */
470
471 /* Release media protection. */
472 7 FX_UNPROTECT
473
474 /* Return the error status. */
475 13 return(status);
476 }
477
478 #ifdef FX_ENABLE_FAULT_TOLERANT
479
4/4
✓ Branch 66 → 67 taken 48 times.
✓ Branch 66 → 68 taken 20 times.
✓ Branch 79 → 80 taken 48 times.
✓ Branch 79 → 81 taken 20 times.
136 if (media_ptr -> fx_media_fault_tolerant_enabled)
480 {
481
482 /* Clear undo phase. */
483 96 media_ptr -> fx_media_fault_tolerant_state &= (UCHAR)(~FX_FAULT_TOLERANT_STATE_SET_FAT_CHAIN & 0xff);
484 }
485 #endif /* FX_ENABLE_FAULT_TOLERANT */
486 }
487
488 181 file_ptr -> fx_file_last_physical_cluster = cluster;
489
490 #ifdef FX_FAULT_TOLERANT
491
492 /* Flush the cached individual FAT entries. */
493 136 status = _fx_utility_FAT_flush(media_ptr);
494
495 /* Check the return value. */
496
4/4
✓ Branch 69 → 70 taken 2 times.
✓ Branch 69 → 78 taken 66 times.
✓ Branch 82 → 83 taken 2 times.
✓ Branch 82 → 93 taken 66 times.
136 if (status)
497 {
498
499 #ifdef FX_ENABLE_FAULT_TOLERANT
500 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
501 #endif /* FX_ENABLE_FAULT_TOLERANT */
502
503 /* Release media protection. */
504 2 FX_UNPROTECT
505
506 /* Return the error status. */
507 4 return(status);
508 }
509 #endif
510 }
511 }
512 else
513 {
514
515 /* This is a cluster after the clusters used by the file, release
516 it back to the media. */
517
518 #ifdef FX_ENABLE_FAULT_TOLERANT
519
4/4
✓ Branch 72 → 73 taken 28618 times.
✓ Branch 72 → 78 taken 66 times.
✓ Branch 86 → 87 taken 28618 times.
✓ Branch 86 → 93 taken 29403401 times.
29460703 if (media_ptr -> fx_media_fault_tolerant_enabled == FX_FALSE)
520 {
521 #endif /* FX_ENABLE_FAULT_TOLERANT */
522
523 128761 status = _fx_utility_FAT_entry_write(media_ptr, cluster, FX_FREE_CLUSTER);
524
525 /* Check the return value. */
526
8/8
✓ Branch 42 → 43 taken 2 times.
✓ Branch 42 → 44 taken 28608 times.
✓ Branch 52 → 53 taken 3 times.
✓ Branch 52 → 55 taken 42912 times.
✓ Branch 74 → 75 taken 2 times.
✓ Branch 74 → 77 taken 28616 times.
✓ Branch 88 → 89 taken 2 times.
✓ Branch 88 → 92 taken 28616 times.
128761 if (status)
527 {
528
529 #ifdef FX_ENABLE_FAULT_TOLERANT
530 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
531 #endif /* FX_ENABLE_FAULT_TOLERANT */
532
533 /* Release media protection. */
534 5 FX_UNPROTECT
535
536 /* Return the error status. */
537 9 return(status);
538 }
539
540 /* Increment the number of available clusters. */
541 128752 media_ptr -> fx_media_available_clusters++;
542
543 #ifdef FX_ENABLE_FAULT_TOLERANT
544 }
545 #endif /* FX_ENABLE_FAULT_TOLERANT */
546 }
547
548 /* Setup for the next cluster. */
549 29535204 cluster = contents;
550 }
551
552 /* Determine if we need to adjust the number of leading consecutive clusters. */
553
8/8
✓ Branch 48 → 49 taken 20 times.
✓ Branch 48 → 50 taken 18 times.
✓ Branch 59 → 60 taken 30 times.
✓ Branch 59 → 61 taken 27 times.
✓ Branch 81 → 82 taken 46 times.
✓ Branch 81 → 83 taken 46 times.
✓ Branch 96 → 97 taken 3400459 times.
✓ Branch 96 → 98 taken 46 times.
3400692 if (file_ptr -> fx_file_consecutive_cluster > file_ptr -> fx_file_total_clusters)
554 {
555
556 /* Adjust the leading consecutive cluster count. */
557 3400555 file_ptr -> fx_file_consecutive_cluster = file_ptr -> fx_file_total_clusters;
558 }
559
560 /* Determine if the file available size has been truncated to zero. */
561
8/8
✓ Branch 50 → 51 taken 20 times.
✓ Branch 50 → 52 taken 18 times.
✓ Branch 61 → 62 taken 30 times.
✓ Branch 61 → 63 taken 27 times.
✓ Branch 83 → 84 taken 34 times.
✓ Branch 83 → 85 taken 58 times.
✓ Branch 98 → 99 taken 3400447 times.
✓ Branch 98 → 100 taken 58 times.
3400692 if (file_ptr -> fx_file_current_available_size == 0)
562 {
563
564 /* Yes, the first cluster has already been released. Update the file info
565 to indicate the file has no clusters. */
566 3400531 file_ptr -> fx_file_last_physical_cluster = 0;
567 3400531 file_ptr -> fx_file_first_physical_cluster = 0;
568 3400531 file_ptr -> fx_file_current_physical_cluster = 0;
569 3400531 file_ptr -> fx_file_current_logical_sector = 0;
570 3400531 file_ptr -> fx_file_current_relative_cluster = 0;
571 3400531 file_ptr -> fx_file_current_relative_sector = 0;
572 3400531 file_ptr -> fx_file_current_available_size = 0;
573 3400531 file_ptr -> fx_file_consecutive_cluster = 1;
574 }
575
576 #ifndef FX_DONT_UPDATE_OPEN_FILES
577
578 /* Search the opened files list to see if the same file is opened for reading. */
579 3400692 open_count = media_ptr -> fx_media_opened_file_count;
580 3400692 search_ptr = media_ptr -> fx_media_opened_file_list;
581
8/8
✓ Branch 72 → 53 taken 76 times.
✓ Branch 72 → 73 taken 32 times.
✓ Branch 85 → 64 taken 114 times.
✓ Branch 85 → 86 taken 48 times.
✓ Branch 107 → 86 taken 130 times.
✓ Branch 107 → 108 taken 86 times.
✓ Branch 124 → 101 taken 3400543 times.
✓ Branch 124 → 125 taken 3400499 times.
6801528 while (open_count)
582 {
583
584 /* Is this file the same file opened for reading? */
585
8/8
✓ Branch 53 → 54 taken 38 times.
✓ Branch 53 → 71 taken 38 times.
✓ Branch 64 → 65 taken 57 times.
✓ Branch 64 → 84 taken 57 times.
✓ Branch 86 → 87 taken 38 times.
✓ Branch 86 → 106 taken 92 times.
✓ Branch 101 → 102 taken 38 times.
✓ Branch 101 → 123 taken 3400505 times.
3400863 if ((search_ptr != file_ptr) &&
586 171 (search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector ==
587
8/8
✓ Branch 54 → 55 taken 30 times.
✓ Branch 54 → 71 taken 8 times.
✓ Branch 65 → 66 taken 45 times.
✓ Branch 65 → 84 taken 12 times.
✓ Branch 87 → 88 taken 30 times.
✓ Branch 87 → 106 taken 8 times.
✓ Branch 102 → 103 taken 30 times.
✓ Branch 102 → 123 taken 8 times.
171 file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector) &&
588 135 (search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset ==
589
8/8
✓ Branch 55 → 56 taken 18 times.
✓ Branch 55 → 71 taken 12 times.
✓ Branch 66 → 67 taken 27 times.
✓ Branch 66 → 84 taken 18 times.
✓ Branch 88 → 89 taken 18 times.
✓ Branch 88 → 106 taken 12 times.
✓ Branch 103 → 104 taken 18 times.
✓ Branch 103 → 123 taken 12 times.
135 file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset))
590 {
591
592 /* Yes, the same file is opened for reading. */
593
594 /* Setup the new file size. */
595 81 search_ptr -> fx_file_current_file_size = size;
596
597 /* Setup the new total clusters. */
598 81 search_ptr -> fx_file_total_clusters = file_ptr -> fx_file_total_clusters;
599
600 /* Copy the directory entry. */
601 81 search_ptr -> fx_file_dir_entry.fx_dir_entry_cluster = file_ptr -> fx_file_dir_entry.fx_dir_entry_cluster;
602 81 search_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size;
603 81 search_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector = file_ptr -> fx_file_dir_entry.fx_dir_entry_log_sector;
604 81 search_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset = file_ptr -> fx_file_dir_entry.fx_dir_entry_byte_offset;
605
606 /* Setup the other file parameters. */
607 81 search_ptr -> fx_file_last_physical_cluster = file_ptr -> fx_file_last_physical_cluster;
608 81 search_ptr -> fx_file_first_physical_cluster = file_ptr -> fx_file_first_physical_cluster;
609 81 search_ptr -> fx_file_current_available_size = file_ptr -> fx_file_current_available_size;
610 81 search_ptr -> fx_file_consecutive_cluster = file_ptr -> fx_file_consecutive_cluster;
611
612 /* Determine if the truncated file is smaller than the current file offset. */
613
8/8
✓ Branch 56 → 57 taken 14 times.
✓ Branch 56 → 71 taken 4 times.
✓ Branch 67 → 68 taken 21 times.
✓ Branch 67 → 84 taken 6 times.
✓ Branch 89 → 90 taken 14 times.
✓ Branch 89 → 106 taken 4 times.
✓ Branch 104 → 105 taken 14 times.
✓ Branch 104 → 123 taken 4 times.
81 if (search_ptr -> fx_file_current_file_offset > size)
614 {
615
616 /* Yes, the current file parameters need to be changed since the file was
617 truncated to a position prior to the current file position. */
618
619 /* Calculate the number of bytes per cluster. */
620 63 bytes_per_cluster = ((ULONG)media_ptr -> fx_media_bytes_per_sector) *
621 63 ((ULONG)media_ptr -> fx_media_sectors_per_cluster);
622
623 /* At this point, we are ready to walk list of clusters to setup the
624 seek position of this file. */
625 63 cluster = search_ptr -> fx_file_first_physical_cluster;
626 63 bytes_remaining = size;
627 63 last_cluster = 0;
628 63 cluster_count = 0;
629
630 /* Follow the link of FAT entries. */
631
16/16
✓ Branch 64 → 65 taken 72 times.
✓ Branch 64 → 66 taken 4 times.
✓ Branch 65 → 58 taken 70 times.
✓ Branch 65 → 66 taken 2 times.
✓ Branch 76 → 77 taken 108 times.
✓ Branch 76 → 78 taken 6 times.
✓ Branch 77 → 69 taken 105 times.
✓ Branch 77 → 78 taken 3 times.
✓ Branch 98 → 99 taken 72 times.
✓ Branch 98 → 100 taken 4 times.
✓ Branch 99 → 91 taken 70 times.
✓ Branch 99 → 100 taken 2 times.
✓ Branch 114 → 115 taken 72 times.
✓ Branch 114 → 116 taken 4 times.
✓ Branch 115 → 106 taken 70 times.
✓ Branch 115 → 116 taken 2 times.
342 while ((cluster >= FX_FAT_ENTRY_START) && (cluster < media_ptr -> fx_media_fat_reserved))
632 {
633
634 /* Increment the number of clusters. */
635 315 cluster_count++;
636
637
638 /* Read the current cluster entry from the FAT. */
639 315 status = _fx_utility_FAT_entry_read(media_ptr, cluster, &contents);
640
641 /* Check the return value. */
642
8/8
✓ Branch 59 → 60 taken 2 times.
✓ Branch 59 → 61 taken 68 times.
✓ Branch 70 → 71 taken 3 times.
✓ Branch 70 → 73 taken 102 times.
✓ Branch 92 → 93 taken 2 times.
✓ Branch 92 → 95 taken 68 times.
✓ Branch 107 → 108 taken 2 times.
✓ Branch 107 → 111 taken 68 times.
315 if (status != FX_SUCCESS)
643 {
644
645 #ifdef FX_ENABLE_FAULT_TOLERANT
646 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
647 #endif /* FX_ENABLE_FAULT_TOLERANT */
648
649 /* Release media protection. */
650 5 FX_UNPROTECT
651
652 /* Return the error status. */
653 9 return(status);
654 }
655
656 /* Save the last valid cluster. */
657 306 last_cluster = cluster;
658
659 /* Setup for the next cluster. */
660 306 cluster = contents;
661
662 /* Determine if this is the last written cluster. */
663
8/8
✓ Branch 61 → 62 taken 62 times.
✓ Branch 61 → 63 taken 6 times.
✓ Branch 73 → 74 taken 93 times.
✓ Branch 73 → 75 taken 9 times.
✓ Branch 95 → 96 taken 62 times.
✓ Branch 95 → 97 taken 6 times.
✓ Branch 111 → 112 taken 62 times.
✓ Branch 111 → 113 taken 6 times.
306 if (bytes_remaining >= bytes_per_cluster)
664 {
665
666 /* Still more seeking, just decrement the working byte offset. */
667 279 bytes_remaining = bytes_remaining - bytes_per_cluster;
668 }
669 else
670 {
671
672 /* This is the cluster that contains the seek position. */
673 27 break;
674 }
675 }
676
677 /* Check for errors in traversal of the FAT chain. */
678
8/8
✓ Branch 66 → 67 taken 4 times.
✓ Branch 66 → 68 taken 8 times.
✓ Branch 78 → 79 taken 6 times.
✓ Branch 78 → 81 taken 12 times.
✓ Branch 100 → 101 taken 4 times.
✓ Branch 100 → 103 taken 8 times.
✓ Branch 116 → 117 taken 4 times.
✓ Branch 116 → 120 taken 8 times.
54 if (size > (((ULONG64) bytes_per_cluster) * ((ULONG64) cluster_count)))
679 {
680
681 #ifdef FX_ENABLE_FAULT_TOLERANT
682 8 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
683 #endif /* FX_ENABLE_FAULT_TOLERANT */
684
685 /* Release media protection. */
686 10 FX_UNPROTECT
687
688 /* This is an error that suggests a corrupt file. */
689 18 return(FX_FILE_CORRUPT);
690 }
691
692 /* Position the pointers to the new offset. */
693
694 /* Determine if there is at least one cluster. */
695
8/8
✓ Branch 68 → 69 taken 6 times.
✓ Branch 68 → 70 taken 2 times.
✓ Branch 81 → 82 taken 9 times.
✓ Branch 81 → 83 taken 3 times.
✓ Branch 103 → 104 taken 6 times.
✓ Branch 103 → 105 taken 2 times.
✓ Branch 120 → 121 taken 6 times.
✓ Branch 120 → 122 taken 2 times.
36 if (cluster_count)
696 {
697
698 /* Calculate real file parameters. */
699 27 search_ptr -> fx_file_current_physical_cluster = last_cluster;
700 27 search_ptr -> fx_file_current_relative_cluster = cluster_count - 1;
701 27 search_ptr -> fx_file_current_logical_sector = ((ULONG)media_ptr -> fx_media_data_sector_start) +
702 27 (((ULONG64)search_ptr -> fx_file_current_physical_cluster - FX_FAT_ENTRY_START) *
703 27 ((ULONG)media_ptr -> fx_media_sectors_per_cluster)) +
704 27 (bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector);
705 27 search_ptr -> fx_file_current_relative_sector = (UINT)((bytes_remaining / (ULONG)media_ptr -> fx_media_bytes_per_sector));
706 27 search_ptr -> fx_file_current_file_offset = size;
707 27 search_ptr -> fx_file_current_logical_offset = (ULONG)bytes_remaining % ((ULONG)media_ptr -> fx_media_bytes_per_sector);
708 }
709 else
710 {
711
712 /* Calculate zero-length file parameters. */
713 9 search_ptr -> fx_file_current_physical_cluster = 0;
714 9 search_ptr -> fx_file_current_relative_cluster = 0;
715 9 search_ptr -> fx_file_current_logical_sector = 0;
716 9 search_ptr -> fx_file_current_relative_sector = 0;
717 9 search_ptr -> fx_file_current_file_offset = 0;
718 9 search_ptr -> fx_file_current_logical_offset = 0;
719 }
720 }
721 }
722
723 /* Adjust the pointer and decrement the search count. */
724 3400836 search_ptr = search_ptr -> fx_file_opened_next;
725 3400836 open_count--;
726 }
727 #endif
728
729 #ifdef FX_FAULT_TOLERANT
730
731 /* Flush the cached individual FAT entries */
732 3400585 status = _fx_utility_FAT_flush(media_ptr);
733
734 /* Check the return value. */
735
4/4
✓ Branch 109 → 110 taken 2 times.
✓ Branch 109 → 112 taken 84 times.
✓ Branch 126 → 127 taken 2 times.
✓ Branch 126 → 130 taken 3400497 times.
3400585 if (status)
736 {
737
738 #ifdef FX_ENABLE_FAULT_TOLERANT
739 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
740 #endif /* FX_ENABLE_FAULT_TOLERANT */
741
742 /* Release media protection. */
743 2 FX_UNPROTECT
744
745 /* Return the error status. */
746 4 return(status);
747 }
748
749 #endif
750
751 #ifdef FX_ENABLE_FAULT_TOLERANT
752
4/4
✓ Branch 112 → 113 taken 52 times.
✓ Branch 112 → 115 taken 32 times.
✓ Branch 130 → 131 taken 3400465 times.
✓ Branch 130 → 133 taken 32 times.
3400581 if (media_ptr -> fx_media_fault_tolerant_enabled &&
753
4/4
✓ Branch 113 → 114 taken 50 times.
✓ Branch 113 → 115 taken 2 times.
✓ Branch 131 → 132 taken 3400463 times.
✓ Branch 131 → 133 taken 2 times.
3400517 (media_ptr -> fx_media_fault_tolerant_state & FX_FAULT_TOLERANT_STATE_STARTED))
754 {
755
756 /* Copy the new file size into the directory entry. */
757 3400513 file_ptr -> fx_file_dir_entry.fx_dir_entry_file_size = file_ptr -> fx_file_current_file_size;
758 }
759
760 /* Write the directory entry to the media. */
761 3400581 status = _fx_directory_entry_write(media_ptr, &(file_ptr -> fx_file_dir_entry));
762
763 /* Check for a good status. */
764
4/4
✓ Branch 116 → 117 taken 2 times.
✓ Branch 116 → 119 taken 82 times.
✓ Branch 134 → 135 taken 2 times.
✓ Branch 134 → 138 taken 3400495 times.
3400581 if (status != FX_SUCCESS)
765 {
766
767 4 FX_FAULT_TOLERANT_TRANSACTION_FAIL(media_ptr);
768
769 /* Release media protection. */
770 2 FX_UNPROTECT
771
772 /* Error writing the directory. */
773 4 return(status);
774 }
775
776 /* End transaction. */
777 3400577 status = _fx_fault_tolerant_transaction_end(media_ptr);
778
779 /* Check for a bad status. */
780
4/4
✓ Branch 120 → 121 taken 6 times.
✓ Branch 120 → 122 taken 46 times.
✓ Branch 139 → 140 taken 6 times.
✓ Branch 139 → 142 taken 3400441 times.
3400499 if (status != FX_SUCCESS)
781 {
782
783 /* Release media protection. */
784 6 FX_UNPROTECT
785
786 /* Return the bad status. */
787 12 return(status);
788 }
789
790 /* Update maximum size used if necessary. */
791
4/4
✓ Branch 122 → 123 taken 36 times.
✓ Branch 122 → 124 taken 10 times.
✓ Branch 142 → 143 taken 3400431 times.
✓ Branch 142 → 144 taken 10 times.
3400487 if (size < file_ptr -> fx_file_maximum_size_used)
792 {
793 3400467 file_ptr -> fx_file_maximum_size_used = size;
794 }
795 #endif /* FX_ENABLE_FAULT_TOLERANT */
796
797 /* Release media protection. */
798 3400489 FX_UNPROTECT
799
800 /* Truncate is complete, return successful status. */
801 3400564 return(FX_SUCCESS);
802 }
803
804