]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - LinuxGUI/Ventoy2Disk/Lib/exfat/src/libexfat/cluster.c
3 exFAT file system implementation library.
5 Free exFAT implementation.
6 Copyright (C) 2010-2018 Andrew Nayenko
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 * Sector to absolute offset.
31 static off_t
s2o(const struct exfat
* ef
, off_t sector
)
33 return sector
<< ef
->sb
->sector_bits
;
39 static off_t
c2s(const struct exfat
* ef
, cluster_t cluster
)
41 if (cluster
< EXFAT_FIRST_DATA_CLUSTER
)
42 exfat_bug("invalid cluster number %u", cluster
);
43 return le32_to_cpu(ef
->sb
->cluster_sector_start
) +
44 ((off_t
) (cluster
- EXFAT_FIRST_DATA_CLUSTER
) << ef
->sb
->spc_bits
);
48 * Cluster to absolute offset.
50 off_t
exfat_c2o(const struct exfat
* ef
, cluster_t cluster
)
52 return s2o(ef
, c2s(ef
, cluster
));
58 static cluster_t
s2c(const struct exfat
* ef
, off_t sector
)
60 return ((sector
- le32_to_cpu(ef
->sb
->cluster_sector_start
)) >>
61 ef
->sb
->spc_bits
) + EXFAT_FIRST_DATA_CLUSTER
;
65 * Size in bytes to size in clusters (rounded upwards).
67 static uint32_t bytes2clusters(const struct exfat
* ef
, uint64_t bytes
)
69 uint64_t cluster_size
= CLUSTER_SIZE(*ef
->sb
);
70 return DIV_ROUND_UP(bytes
, cluster_size
);
73 cluster_t
exfat_next_cluster(const struct exfat
* ef
,
74 const struct exfat_node
* node
, cluster_t cluster
)
79 if (cluster
< EXFAT_FIRST_DATA_CLUSTER
)
80 exfat_bug("bad cluster 0x%x", cluster
);
82 if (node
->is_contiguous
)
84 fat_offset
= s2o(ef
, le32_to_cpu(ef
->sb
->fat_sector_start
))
85 + cluster
* sizeof(cluster_t
);
86 if (exfat_pread(ef
->dev
, &next
, sizeof(next
), fat_offset
) < 0)
87 return EXFAT_CLUSTER_BAD
; /* the caller should handle this and print
88 appropriate error message */
89 return le32_to_cpu(next
);
92 cluster_t
exfat_advance_cluster(const struct exfat
* ef
,
93 struct exfat_node
* node
, uint32_t count
)
97 if (node
->fptr_index
> count
)
100 node
->fptr_cluster
= node
->start_cluster
;
103 for (i
= node
->fptr_index
; i
< count
; i
++)
105 node
->fptr_cluster
= exfat_next_cluster(ef
, node
, node
->fptr_cluster
);
106 if (CLUSTER_INVALID(*ef
->sb
, node
->fptr_cluster
))
107 break; /* the caller should handle this and print appropriate
110 node
->fptr_index
= count
;
111 return node
->fptr_cluster
;
114 static cluster_t
find_bit_and_set(bitmap_t
* bitmap
, size_t start
, size_t end
)
116 const size_t start_index
= start
/ sizeof(bitmap_t
) / 8;
117 const size_t end_index
= DIV_ROUND_UP(end
, sizeof(bitmap_t
) * 8);
119 size_t start_bitindex
;
123 for (i
= start_index
; i
< end_index
; i
++)
125 if (bitmap
[i
] == ~((bitmap_t
) 0))
127 start_bitindex
= MAX(i
* sizeof(bitmap_t
) * 8, start
);
128 end_bitindex
= MIN((i
+ 1) * sizeof(bitmap_t
) * 8, end
);
129 for (c
= start_bitindex
; c
< end_bitindex
; c
++)
130 if (BMAP_GET(bitmap
, c
) == 0)
133 return c
+ EXFAT_FIRST_DATA_CLUSTER
;
136 return EXFAT_CLUSTER_END
;
139 static int flush_nodes(struct exfat
* ef
, struct exfat_node
* node
)
141 struct exfat_node
* p
;
143 for (p
= node
->child
; p
!= NULL
; p
= p
->next
)
145 int rc
= flush_nodes(ef
, p
);
149 return exfat_flush_node(ef
, node
);
152 int exfat_flush_nodes(struct exfat
* ef
)
154 return flush_nodes(ef
, ef
->root
);
157 int exfat_flush(struct exfat
* ef
)
161 if (exfat_pwrite(ef
->dev
, ef
->cmap
.chunk
,
162 BMAP_SIZE(ef
->cmap
.chunk_size
),
163 exfat_c2o(ef
, ef
->cmap
.start_cluster
)) < 0)
165 exfat_error("failed to write clusters bitmap");
168 ef
->cmap
.dirty
= false;
174 static bool set_next_cluster(const struct exfat
* ef
, bool contiguous
,
175 cluster_t current
, cluster_t next
)
182 fat_offset
= s2o(ef
, le32_to_cpu(ef
->sb
->fat_sector_start
))
183 + current
* sizeof(cluster_t
);
184 next_le32
= cpu_to_le32(next
);
185 if (exfat_pwrite(ef
->dev
, &next_le32
, sizeof(next_le32
), fat_offset
) < 0)
187 exfat_error("failed to write the next cluster %#x after %#x", next
,
194 static cluster_t
allocate_cluster(struct exfat
* ef
, cluster_t hint
)
198 hint
-= EXFAT_FIRST_DATA_CLUSTER
;
199 if (hint
>= ef
->cmap
.chunk_size
)
202 cluster
= find_bit_and_set(ef
->cmap
.chunk
, hint
, ef
->cmap
.chunk_size
);
203 if (cluster
== EXFAT_CLUSTER_END
)
204 cluster
= find_bit_and_set(ef
->cmap
.chunk
, 0, hint
);
205 if (cluster
== EXFAT_CLUSTER_END
)
207 exfat_error("no free space left");
208 return EXFAT_CLUSTER_END
;
211 ef
->cmap
.dirty
= true;
215 static void free_cluster(struct exfat
* ef
, cluster_t cluster
)
217 if (cluster
- EXFAT_FIRST_DATA_CLUSTER
>= ef
->cmap
.size
)
218 exfat_bug("caller must check cluster validity (%#x, %#x)", cluster
,
221 BMAP_CLR(ef
->cmap
.chunk
, cluster
- EXFAT_FIRST_DATA_CLUSTER
);
222 ef
->cmap
.dirty
= true;
225 static bool make_noncontiguous(const struct exfat
* ef
, cluster_t first
,
230 for (c
= first
; c
< last
; c
++)
231 if (!set_next_cluster(ef
, false, c
, c
+ 1))
236 static int shrink_file(struct exfat
* ef
, struct exfat_node
* node
,
237 uint32_t current
, uint32_t difference
);
239 static int grow_file(struct exfat
* ef
, struct exfat_node
* node
,
240 uint32_t current
, uint32_t difference
)
244 uint32_t allocated
= 0;
247 exfat_bug("zero clusters count passed");
249 if (node
->start_cluster
!= EXFAT_CLUSTER_FREE
)
251 /* get the last cluster of the file */
252 previous
= exfat_advance_cluster(ef
, node
, current
- 1);
253 if (CLUSTER_INVALID(*ef
->sb
, previous
))
255 exfat_error("invalid cluster 0x%x while growing", previous
);
261 if (node
->fptr_index
!= 0)
262 exfat_bug("non-zero pointer index (%u)", node
->fptr_index
);
263 /* file does not have clusters (i.e. is empty), allocate
264 the first one for it */
265 previous
= allocate_cluster(ef
, 0);
266 if (CLUSTER_INVALID(*ef
->sb
, previous
))
268 node
->fptr_cluster
= node
->start_cluster
= previous
;
270 /* file consists of only one cluster, so it's contiguous */
271 node
->is_contiguous
= true;
274 while (allocated
< difference
)
276 next
= allocate_cluster(ef
, previous
+ 1);
277 if (CLUSTER_INVALID(*ef
->sb
, next
))
280 shrink_file(ef
, node
, current
+ allocated
, allocated
);
283 if (next
!= previous
- 1 && node
->is_contiguous
)
285 /* it's a pity, but we are not able to keep the file contiguous
287 if (!make_noncontiguous(ef
, node
->start_cluster
, previous
))
289 node
->is_contiguous
= false;
290 node
->is_dirty
= true;
292 if (!set_next_cluster(ef
, node
->is_contiguous
, previous
, next
))
298 if (!set_next_cluster(ef
, node
->is_contiguous
, previous
,
304 static int shrink_file(struct exfat
* ef
, struct exfat_node
* node
,
305 uint32_t current
, uint32_t difference
)
311 exfat_bug("zero difference passed");
312 if (node
->start_cluster
== EXFAT_CLUSTER_FREE
)
313 exfat_bug("unable to shrink empty file (%u clusters)", current
);
314 if (current
< difference
)
315 exfat_bug("file underflow (%u < %u)", current
, difference
);
318 if (current
> difference
)
320 cluster_t last
= exfat_advance_cluster(ef
, node
,
321 current
- difference
- 1);
322 if (CLUSTER_INVALID(*ef
->sb
, last
))
324 exfat_error("invalid cluster 0x%x while shrinking", last
);
327 previous
= exfat_next_cluster(ef
, node
, last
);
328 if (!set_next_cluster(ef
, node
->is_contiguous
, last
,
334 previous
= node
->start_cluster
;
335 node
->start_cluster
= EXFAT_CLUSTER_FREE
;
336 node
->is_dirty
= true;
338 node
->fptr_index
= 0;
339 node
->fptr_cluster
= node
->start_cluster
;
341 /* free remaining clusters */
344 if (CLUSTER_INVALID(*ef
->sb
, previous
))
346 exfat_error("invalid cluster 0x%x while freeing after shrink",
351 next
= exfat_next_cluster(ef
, node
, previous
);
352 if (!set_next_cluster(ef
, node
->is_contiguous
, previous
,
355 free_cluster(ef
, previous
);
361 static bool erase_raw(struct exfat
* ef
, size_t size
, off_t offset
)
363 if (exfat_pwrite(ef
->dev
, ef
->zero_cluster
, size
, offset
) < 0)
365 exfat_error("failed to erase %zu bytes at %"PRId64
, size
, offset
);
371 static int erase_range(struct exfat
* ef
, struct exfat_node
* node
,
372 uint64_t begin
, uint64_t end
)
374 uint64_t cluster_boundary
;
380 cluster_boundary
= (begin
| (CLUSTER_SIZE(*ef
->sb
) - 1)) + 1;
381 cluster
= exfat_advance_cluster(ef
, node
,
382 begin
/ CLUSTER_SIZE(*ef
->sb
));
383 if (CLUSTER_INVALID(*ef
->sb
, cluster
))
385 exfat_error("invalid cluster 0x%x while erasing", cluster
);
388 /* erase from the beginning to the closest cluster boundary */
389 if (!erase_raw(ef
, MIN(cluster_boundary
, end
) - begin
,
390 exfat_c2o(ef
, cluster
) + begin
% CLUSTER_SIZE(*ef
->sb
)))
392 /* erase whole clusters */
393 while (cluster_boundary
< end
)
395 cluster
= exfat_next_cluster(ef
, node
, cluster
);
396 /* the cluster cannot be invalid because we have just allocated it */
397 if (CLUSTER_INVALID(*ef
->sb
, cluster
))
398 exfat_bug("invalid cluster 0x%x after allocation", cluster
);
399 if (!erase_raw(ef
, CLUSTER_SIZE(*ef
->sb
), exfat_c2o(ef
, cluster
)))
401 cluster_boundary
+= CLUSTER_SIZE(*ef
->sb
);
406 int exfat_truncate(struct exfat
* ef
, struct exfat_node
* node
, uint64_t size
,
409 uint32_t c1
= bytes2clusters(ef
, node
->size
);
410 uint32_t c2
= bytes2clusters(ef
, size
);
413 if (node
->references
== 0 && node
->parent
)
414 exfat_bug("no references, node changes can be lost");
416 if (node
->size
== size
)
420 rc
= grow_file(ef
, node
, c1
, c2
- c1
);
422 rc
= shrink_file(ef
, node
, c1
, c1
- c2
);
429 rc
= erase_range(ef
, node
, node
->size
, size
);
434 exfat_update_mtime(node
);
436 node
->is_dirty
= true;
440 uint32_t exfat_count_free_clusters(const struct exfat
* ef
)
442 uint32_t free_clusters
= 0;
445 for (i
= 0; i
< ef
->cmap
.size
; i
++)
446 if (BMAP_GET(ef
->cmap
.chunk
, i
) == 0)
448 return free_clusters
;
451 static int find_used_clusters(const struct exfat
* ef
,
452 cluster_t
* a
, cluster_t
* b
)
454 const cluster_t end
= le32_to_cpu(ef
->sb
->cluster_count
);
456 /* find first used cluster */
457 for (*a
= *b
+ 1; *a
< end
; (*a
)++)
458 if (BMAP_GET(ef
->cmap
.chunk
, *a
- EXFAT_FIRST_DATA_CLUSTER
))
463 /* find last contiguous used cluster */
464 for (*b
= *a
; *b
< end
; (*b
)++)
465 if (BMAP_GET(ef
->cmap
.chunk
, *b
- EXFAT_FIRST_DATA_CLUSTER
) == 0)
474 int exfat_find_used_sectors(const struct exfat
* ef
, off_t
* a
, off_t
* b
)
478 if (*a
== 0 && *b
== 0)
479 ca
= cb
= EXFAT_FIRST_DATA_CLUSTER
- 1;
485 if (find_used_clusters(ef
, &ca
, &cb
) != 0)
487 if (*a
!= 0 || *b
!= 0)
489 *b
= c2s(ef
, cb
) + (CLUSTER_SIZE(*ef
->sb
) - 1) / SECTOR_SIZE(*ef
->sb
);