1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2021 LG Electronics.
5 * Author(s): Hyunchul Lee <hyc.lee@gmail.com>
13 #include "exfat_ondisk.h"
17 #include "exfat_dir.h"
19 struct exfat_inode *exfat_alloc_inode(__u16 attr)
21 struct exfat_inode *node;
24 size = offsetof(struct exfat_inode, name) + NAME_BUFFER_SIZE;
25 node = calloc(1, size);
27 exfat_err("failed to allocate exfat_node\n");
32 INIT_LIST_HEAD(&node->children);
33 INIT_LIST_HEAD(&node->sibling);
34 INIT_LIST_HEAD(&node->list);
40 void exfat_free_inode(struct exfat_inode *node)
44 free(node->dentry_set);
49 void exfat_free_children(struct exfat_inode *dir, bool file_only)
51 struct exfat_inode *node, *i;
53 list_for_each_entry_safe(node, i, &dir->children, sibling) {
55 if (!(node->attr & ATTR_SUBDIR)) {
56 list_del(&node->sibling);
57 exfat_free_inode(node);
60 list_del(&node->sibling);
61 list_del(&node->list);
62 exfat_free_inode(node);
67 void exfat_free_file_children(struct exfat_inode *dir)
69 exfat_free_children(dir, true);
72 /* delete @child and all ancestors that does not have
75 void exfat_free_ancestors(struct exfat_inode *child)
77 struct exfat_inode *parent;
79 while (child && list_empty(&child->children)) {
80 if (!child->parent || !(child->attr & ATTR_SUBDIR))
83 parent = child->parent;
84 list_del(&child->sibling);
85 exfat_free_inode(child);
92 void exfat_free_dir_list(struct exfat *exfat)
94 struct exfat_inode *dir, *i;
96 list_for_each_entry_safe(dir, i, &exfat->dir_list, list) {
99 exfat_free_file_children(dir);
100 list_del(&dir->list);
101 exfat_free_inode(dir);
105 void exfat_free_exfat(struct exfat *exfat)
110 if (exfat->alloc_bitmap)
111 free(exfat->alloc_bitmap);
112 if (exfat->disk_bitmap)
113 free(exfat->disk_bitmap);
114 if (exfat->ohead_bitmap)
115 free(exfat->ohead_bitmap);
116 if (exfat->upcase_table)
117 free(exfat->upcase_table);
119 exfat_free_inode(exfat->root);
120 if (exfat->lookup_buffer)
121 free(exfat->lookup_buffer);
126 struct exfat *exfat_alloc_exfat(struct exfat_blk_dev *blk_dev, struct pbr *bs)
130 exfat = calloc(1, sizeof(*exfat));
134 INIT_LIST_HEAD(&exfat->dir_list);
135 exfat->blk_dev = blk_dev;
137 exfat->clus_count = le32_to_cpu(bs->bsx.clu_count);
138 exfat->clus_size = EXFAT_CLUSTER_SIZE(bs);
139 exfat->sect_size = EXFAT_SECTOR_SIZE(bs);
141 /* TODO: bitmap could be very large. */
142 exfat->alloc_bitmap = calloc(1, EXFAT_BITMAP_SIZE(exfat->clus_count));
143 if (!exfat->alloc_bitmap) {
144 exfat_err("failed to allocate bitmap\n");
148 exfat->ohead_bitmap = calloc(1, EXFAT_BITMAP_SIZE(exfat->clus_count));
149 if (!exfat->ohead_bitmap) {
150 exfat_err("failed to allocate bitmap\n");
154 exfat->disk_bitmap = calloc(1, EXFAT_BITMAP_SIZE(exfat->clus_count));
155 if (!exfat->disk_bitmap) {
156 exfat_err("failed to allocate bitmap\n");
160 exfat->buffer_count = ((MAX_EXT_DENTRIES + 1) * DENTRY_SIZE) /
161 exfat_get_read_size(exfat) + 1;
163 exfat->start_clu = EXFAT_FIRST_CLUSTER;
166 exfat_free_exfat(exfat);
170 struct buffer_desc *exfat_alloc_buffer(struct exfat *exfat)
172 struct buffer_desc *bd;
174 unsigned int read_size = exfat_get_read_size(exfat);
176 bd = calloc(exfat->buffer_count, sizeof(*bd));
180 for (i = 0; i < exfat->buffer_count; i++) {
181 bd[i].buffer = malloc(read_size);
185 memset(&bd[i].dirty, 0, sizeof(bd[i].dirty));
189 exfat_free_buffer(exfat, bd);
193 void exfat_free_buffer(const struct exfat *exfat, struct buffer_desc *bd)
197 for (i = 0; i < exfat->buffer_count; i++) {
205 * get references of ancestors that include @child until the count of
206 * ancesters is not larger than @count and the count of characters of
207 * their names is not larger than @max_char_len.
208 * return true if root is reached.
210 static bool get_ancestors(struct exfat_inode *child,
211 struct exfat_inode **ancestors, int count,
215 struct exfat_inode *dir;
216 int name_len, char_len;
217 int root_depth, depth, i;
225 name_len = exfat_utf16_len(dir->name, NAME_BUFFER_SIZE);
226 if (char_len + name_len > max_char_len)
230 char_len += name_len + 1;
236 depth = MIN(root_depth, count);
238 for (dir = child, i = depth - 1; i >= 0; dir = dir->parent, i--)
241 *ancestor_count = depth;
245 int exfat_resolve_path(struct path_resolve_ctx *ctx, struct exfat_inode *child)
250 static const __le16 utf16_slash = cpu_to_le16(0x002F);
251 static const __le16 utf16_null = cpu_to_le16(0x0000);
254 ctx->local_path[0] = '\0';
258 sizeof(ctx->ancestors) / sizeof(ctx->ancestors[0]),
262 utf16_path = ctx->utf16_path;
263 for (i = 0; i < depth; i++) {
264 name_len = exfat_utf16_len(ctx->ancestors[i]->name,
266 memcpy((char *)utf16_path, (char *)ctx->ancestors[i]->name,
268 utf16_path += name_len;
269 memcpy((char *)utf16_path, &utf16_slash, sizeof(utf16_slash));
275 memcpy((char *)utf16_path, &utf16_null, sizeof(utf16_null));
278 in_size = (utf16_path - ctx->utf16_path) * sizeof(__le16);
279 return exfat_utf16_dec(ctx->utf16_path, in_size,
280 ctx->local_path, sizeof(ctx->local_path));
283 int exfat_resolve_path_parent(struct path_resolve_ctx *ctx,
284 struct exfat_inode *parent, struct exfat_inode *child)
287 struct exfat_inode *old;
290 child->parent = parent;
292 ret = exfat_resolve_path(ctx, child);