• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *   Copyright (C) 2021 LG Electronics.
4  *
5  *   Author(s): Hyunchul Lee <hyc.lee@gmail.com>
6  */
7 
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <errno.h>
12 
13 #include "exfat_ondisk.h"
14 #include "libexfat.h"
15 
16 #include "exfat_fs.h"
17 #include "exfat_dir.h"
18 
exfat_alloc_inode(__u16 attr)19 struct exfat_inode *exfat_alloc_inode(__u16 attr)
20 {
21 	struct exfat_inode *node;
22 	int size;
23 
24 	size = offsetof(struct exfat_inode, name) + NAME_BUFFER_SIZE;
25 	node = (struct exfat_inode *)calloc(1, size);
26 	if (!node) {
27 		exfat_err("failed to allocate exfat_node\n");
28 		return NULL;
29 	}
30 
31 	node->parent = NULL;
32 	INIT_LIST_HEAD(&node->children);
33 	INIT_LIST_HEAD(&node->sibling);
34 	INIT_LIST_HEAD(&node->list);
35 
36 	node->attr = attr;
37 	return node;
38 }
39 
exfat_free_inode(struct exfat_inode * node)40 void exfat_free_inode(struct exfat_inode *node)
41 {
42 	if (node) {
43 		if (node->dentry_set)
44 			free(node->dentry_set);
45 		free(node);
46 	}
47 }
48 
exfat_free_children(struct exfat_inode * dir,bool file_only)49 void exfat_free_children(struct exfat_inode *dir, bool file_only)
50 {
51 	struct exfat_inode *node, *i;
52 
53 	list_for_each_entry_safe(node, i, &dir->children, sibling) {
54 		if (file_only) {
55 			if (!(node->attr & ATTR_SUBDIR)) {
56 				list_del(&node->sibling);
57 				exfat_free_inode(node);
58 			}
59 		} else {
60 			list_del(&node->sibling);
61 			list_del(&node->list);
62 			exfat_free_inode(node);
63 		}
64 	}
65 }
66 
exfat_free_file_children(struct exfat_inode * dir)67 void exfat_free_file_children(struct exfat_inode *dir)
68 {
69 	exfat_free_children(dir, true);
70 }
71 
72 /* delete @child and all ancestors that does not have
73  * children
74  */
exfat_free_ancestors(struct exfat_inode * child)75 void exfat_free_ancestors(struct exfat_inode *child)
76 {
77 	struct exfat_inode *parent;
78 
79 	while (child && list_empty(&child->children)) {
80 		if (!child->parent || !(child->attr & ATTR_SUBDIR))
81 			return;
82 
83 		parent = child->parent;
84 		list_del(&child->sibling);
85 		exfat_free_inode(child);
86 
87 		child = parent;
88 	}
89 	return;
90 }
91 
exfat_free_dir_list(struct exfat * exfat)92 void exfat_free_dir_list(struct exfat *exfat)
93 {
94 	struct exfat_inode *dir, *i;
95 
96 	list_for_each_entry_safe(dir, i, &exfat->dir_list, list) {
97 		if (!dir->parent)
98 			continue;
99 		exfat_free_file_children(dir);
100 		list_del(&dir->list);
101 		exfat_free_inode(dir);
102 	}
103 }
104 
exfat_free_exfat(struct exfat * exfat)105 void exfat_free_exfat(struct exfat *exfat)
106 {
107 	if (exfat) {
108 		if (exfat->bs)
109 			free(exfat->bs);
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);
118 		if (exfat->root)
119 			exfat_free_inode(exfat->root);
120 		if (exfat->zero_cluster)
121 			free(exfat->zero_cluster);
122 		free(exfat);
123 	}
124 }
125 
exfat_alloc_exfat(struct exfat_blk_dev * blk_dev,struct pbr * bs)126 struct exfat *exfat_alloc_exfat(struct exfat_blk_dev *blk_dev, struct pbr *bs)
127 {
128 	struct exfat *exfat;
129 
130 	exfat = (struct exfat *)calloc(1, sizeof(*exfat));
131 	if (!exfat)
132 		return NULL;
133 
134 	INIT_LIST_HEAD(&exfat->dir_list);
135 	exfat->blk_dev = blk_dev;
136 	exfat->bs = bs;
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);
140 
141 	/* TODO: bitmap could be very large. */
142 	exfat->alloc_bitmap = (char *)calloc(1,
143 			EXFAT_BITMAP_SIZE(exfat->clus_count));
144 	if (!exfat->alloc_bitmap) {
145 		exfat_err("failed to allocate bitmap\n");
146 		goto err;
147 	}
148 
149 	exfat->ohead_bitmap =
150 		calloc(1, EXFAT_BITMAP_SIZE(exfat->clus_count));
151 	if (!exfat->ohead_bitmap) {
152 		exfat_err("failed to allocate bitmap\n");
153 		goto err;
154 	}
155 
156 	exfat->disk_bitmap =
157 		calloc(1, EXFAT_BITMAP_SIZE(exfat->clus_count));
158 	if (!exfat->disk_bitmap) {
159 		exfat_err("failed to allocate bitmap\n");
160 		goto err;
161 	}
162 
163 	exfat->zero_cluster = calloc(1, exfat->clus_size);
164 	if (!exfat->zero_cluster) {
165 		exfat_err("failed to allocate a zero-filled cluster buffer\n");
166 		goto err;
167 	}
168 
169 	exfat->start_clu = EXFAT_FIRST_CLUSTER;
170 	return exfat;
171 err:
172 	exfat_free_exfat(exfat);
173 	return NULL;
174 }
175 
exfat_alloc_buffer(int count,unsigned int clu_size,unsigned int sect_size)176 struct buffer_desc *exfat_alloc_buffer(int count,
177 				       unsigned int clu_size, unsigned int sect_size)
178 {
179 	struct buffer_desc *bd;
180 	int i;
181 
182 	bd = (struct buffer_desc *)calloc(sizeof(*bd), count);
183 	if (!bd)
184 		return NULL;
185 
186 	for (i = 0; i < count; i++) {
187 		bd[i].buffer = (char *)malloc(clu_size);
188 		if (!bd[i].buffer)
189 			goto err;
190 		bd[i].dirty = (char *)calloc(clu_size / sect_size, 1);
191 		if (!bd[i].dirty)
192 			goto err;
193 	}
194 	return bd;
195 err:
196 	exfat_free_buffer(bd, count);
197 	return NULL;
198 }
199 
exfat_free_buffer(struct buffer_desc * bd,int count)200 void exfat_free_buffer(struct buffer_desc *bd, int count)
201 {
202 	int i;
203 
204 	for (i = 0; i < count; i++) {
205 		if (bd[i].buffer)
206 			free(bd[i].buffer);
207 		if (bd[i].dirty)
208 			free(bd[i].dirty);
209 	}
210 	free(bd);
211 }
212 
213 /*
214  * get references of ancestors that include @child until the count of
215  * ancesters is not larger than @count and the count of characters of
216  * their names is not larger than @max_char_len.
217  * return true if root is reached.
218  */
get_ancestors(struct exfat_inode * child,struct exfat_inode ** ancestors,int count,int max_char_len,int * ancestor_count)219 static bool get_ancestors(struct exfat_inode *child,
220 			  struct exfat_inode **ancestors, int count,
221 			  int max_char_len,
222 			  int *ancestor_count)
223 {
224 	struct exfat_inode *dir;
225 	int name_len, char_len;
226 	int root_depth, depth, i;
227 
228 	root_depth = 0;
229 	char_len = 0;
230 	max_char_len += 1;
231 
232 	dir = child;
233 	while (dir) {
234 		name_len = exfat_utf16_len(dir->name, NAME_BUFFER_SIZE);
235 		if (char_len + name_len > max_char_len)
236 			break;
237 
238 		/* include '/' */
239 		char_len += name_len + 1;
240 		root_depth++;
241 
242 		dir = dir->parent;
243 	}
244 
245 	depth = MIN(root_depth, count);
246 
247 	for (dir = child, i = depth - 1; i >= 0; dir = dir->parent, i--)
248 		ancestors[i] = dir;
249 
250 	*ancestor_count = depth;
251 	return !dir;
252 }
253 
exfat_resolve_path(struct path_resolve_ctx * ctx,struct exfat_inode * child)254 int exfat_resolve_path(struct path_resolve_ctx *ctx, struct exfat_inode *child)
255 {
256 	int depth, i;
257 	int name_len;
258 	__le16 *utf16_path;
259 	static const __le16 utf16_slash = cpu_to_le16(0x002F);
260 	static const __le16 utf16_null = cpu_to_le16(0x0000);
261 	size_t in_size;
262 
263 	ctx->local_path[0] = '\0';
264 
265 	get_ancestors(child,
266 		      ctx->ancestors,
267 		      sizeof(ctx->ancestors) / sizeof(ctx->ancestors[0]),
268 		      PATH_MAX,
269 		      &depth);
270 
271 	utf16_path = ctx->utf16_path;
272 	for (i = 0; i < depth; i++) {
273 		name_len = exfat_utf16_len(ctx->ancestors[i]->name,
274 					   NAME_BUFFER_SIZE);
275 		memcpy((char *)utf16_path, (char *)ctx->ancestors[i]->name,
276 		       name_len * 2);
277 		utf16_path += name_len;
278 		memcpy((char *)utf16_path, &utf16_slash, sizeof(utf16_slash));
279 		utf16_path++;
280 	}
281 
282 	if (depth > 1)
283 		utf16_path--;
284 	memcpy((char *)utf16_path, &utf16_null, sizeof(utf16_null));
285 	utf16_path++;
286 
287 	in_size = (utf16_path - ctx->utf16_path) * sizeof(__le16);
288 	return exfat_utf16_dec(ctx->utf16_path, in_size,
289 				ctx->local_path, sizeof(ctx->local_path));
290 }
291 
exfat_resolve_path_parent(struct path_resolve_ctx * ctx,struct exfat_inode * parent,struct exfat_inode * child)292 int exfat_resolve_path_parent(struct path_resolve_ctx *ctx,
293 			      struct exfat_inode *parent, struct exfat_inode *child)
294 {
295 	int ret;
296 	struct exfat_inode *old;
297 
298 	old = child->parent;
299 	child->parent = parent;
300 
301 	ret = exfat_resolve_path(ctx, child);
302 	child->parent = old;
303 	return ret;
304 }
305