diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/ntfs/dir.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'fs/ntfs/dir.c')
-rw-r--r-- | fs/ntfs/dir.c | 1569 |
1 files changed, 1569 insertions, 0 deletions
diff --git a/fs/ntfs/dir.c b/fs/ntfs/dir.c new file mode 100644 index 000000000000..93577561cdbe --- /dev/null +++ b/fs/ntfs/dir.c | |||
@@ -0,0 +1,1569 @@ | |||
1 | /** | ||
2 | * dir.c - NTFS kernel directory operations. Part of the Linux-NTFS project. | ||
3 | * | ||
4 | * Copyright (c) 2001-2004 Anton Altaparmakov | ||
5 | * Copyright (c) 2002 Richard Russon | ||
6 | * | ||
7 | * This program/include file is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as published | ||
9 | * by the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program/include file is distributed in the hope that it will be | ||
13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty | ||
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program (in the main directory of the Linux-NTFS | ||
19 | * distribution in the file COPYING); if not, write to the Free Software | ||
20 | * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/smp_lock.h> | ||
24 | #include <linux/buffer_head.h> | ||
25 | |||
26 | #include "dir.h" | ||
27 | #include "aops.h" | ||
28 | #include "attrib.h" | ||
29 | #include "mft.h" | ||
30 | #include "debug.h" | ||
31 | #include "ntfs.h" | ||
32 | |||
33 | /** | ||
34 | * The little endian Unicode string $I30 as a global constant. | ||
35 | */ | ||
36 | ntfschar I30[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('I'), | ||
37 | const_cpu_to_le16('3'), const_cpu_to_le16('0'), 0 }; | ||
38 | |||
39 | /** | ||
40 | * ntfs_lookup_inode_by_name - find an inode in a directory given its name | ||
41 | * @dir_ni: ntfs inode of the directory in which to search for the name | ||
42 | * @uname: Unicode name for which to search in the directory | ||
43 | * @uname_len: length of the name @uname in Unicode characters | ||
44 | * @res: return the found file name if necessary (see below) | ||
45 | * | ||
46 | * Look for an inode with name @uname in the directory with inode @dir_ni. | ||
47 | * ntfs_lookup_inode_by_name() walks the contents of the directory looking for | ||
48 | * the Unicode name. If the name is found in the directory, the corresponding | ||
49 | * inode number (>= 0) is returned as a mft reference in cpu format, i.e. it | ||
50 | * is a 64-bit number containing the sequence number. | ||
51 | * | ||
52 | * On error, a negative value is returned corresponding to the error code. In | ||
53 | * particular if the inode is not found -ENOENT is returned. Note that you | ||
54 | * can't just check the return value for being negative, you have to check the | ||
55 | * inode number for being negative which you can extract using MREC(return | ||
56 | * value). | ||
57 | * | ||
58 | * Note, @uname_len does not include the (optional) terminating NULL character. | ||
59 | * | ||
60 | * Note, we look for a case sensitive match first but we also look for a case | ||
61 | * insensitive match at the same time. If we find a case insensitive match, we | ||
62 | * save that for the case that we don't find an exact match, where we return | ||
63 | * the case insensitive match and setup @res (which we allocate!) with the mft | ||
64 | * reference, the file name type, length and with a copy of the little endian | ||
65 | * Unicode file name itself. If we match a file name which is in the DOS name | ||
66 | * space, we only return the mft reference and file name type in @res. | ||
67 | * ntfs_lookup() then uses this to find the long file name in the inode itself. | ||
68 | * This is to avoid polluting the dcache with short file names. We want them to | ||
69 | * work but we don't care for how quickly one can access them. This also fixes | ||
70 | * the dcache aliasing issues. | ||
71 | * | ||
72 | * Locking: - Caller must hold i_sem on the directory. | ||
73 | * - Each page cache page in the index allocation mapping must be | ||
74 | * locked whilst being accessed otherwise we may find a corrupt | ||
75 | * page due to it being under ->writepage at the moment which | ||
76 | * applies the mst protection fixups before writing out and then | ||
77 | * removes them again after the write is complete after which it | ||
78 | * unlocks the page. | ||
79 | */ | ||
80 | MFT_REF ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const ntfschar *uname, | ||
81 | const int uname_len, ntfs_name **res) | ||
82 | { | ||
83 | ntfs_volume *vol = dir_ni->vol; | ||
84 | struct super_block *sb = vol->sb; | ||
85 | MFT_RECORD *m; | ||
86 | INDEX_ROOT *ir; | ||
87 | INDEX_ENTRY *ie; | ||
88 | INDEX_ALLOCATION *ia; | ||
89 | u8 *index_end; | ||
90 | u64 mref; | ||
91 | ntfs_attr_search_ctx *ctx; | ||
92 | int err, rc; | ||
93 | VCN vcn, old_vcn; | ||
94 | struct address_space *ia_mapping; | ||
95 | struct page *page; | ||
96 | u8 *kaddr; | ||
97 | ntfs_name *name = NULL; | ||
98 | |||
99 | BUG_ON(!S_ISDIR(VFS_I(dir_ni)->i_mode)); | ||
100 | BUG_ON(NInoAttr(dir_ni)); | ||
101 | /* Get hold of the mft record for the directory. */ | ||
102 | m = map_mft_record(dir_ni); | ||
103 | if (IS_ERR(m)) { | ||
104 | ntfs_error(sb, "map_mft_record() failed with error code %ld.", | ||
105 | -PTR_ERR(m)); | ||
106 | return ERR_MREF(PTR_ERR(m)); | ||
107 | } | ||
108 | ctx = ntfs_attr_get_search_ctx(dir_ni, m); | ||
109 | if (unlikely(!ctx)) { | ||
110 | err = -ENOMEM; | ||
111 | goto err_out; | ||
112 | } | ||
113 | /* Find the index root attribute in the mft record. */ | ||
114 | err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, | ||
115 | 0, ctx); | ||
116 | if (unlikely(err)) { | ||
117 | if (err == -ENOENT) { | ||
118 | ntfs_error(sb, "Index root attribute missing in " | ||
119 | "directory inode 0x%lx.", | ||
120 | dir_ni->mft_no); | ||
121 | err = -EIO; | ||
122 | } | ||
123 | goto err_out; | ||
124 | } | ||
125 | /* Get to the index root value (it's been verified in read_inode). */ | ||
126 | ir = (INDEX_ROOT*)((u8*)ctx->attr + | ||
127 | le16_to_cpu(ctx->attr->data.resident.value_offset)); | ||
128 | index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length); | ||
129 | /* The first index entry. */ | ||
130 | ie = (INDEX_ENTRY*)((u8*)&ir->index + | ||
131 | le32_to_cpu(ir->index.entries_offset)); | ||
132 | /* | ||
133 | * Loop until we exceed valid memory (corruption case) or until we | ||
134 | * reach the last entry. | ||
135 | */ | ||
136 | for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { | ||
137 | /* Bounds checks. */ | ||
138 | if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie + | ||
139 | sizeof(INDEX_ENTRY_HEADER) > index_end || | ||
140 | (u8*)ie + le16_to_cpu(ie->key_length) > | ||
141 | index_end) | ||
142 | goto dir_err_out; | ||
143 | /* | ||
144 | * The last entry cannot contain a name. It can however contain | ||
145 | * a pointer to a child node in the B+tree so we just break out. | ||
146 | */ | ||
147 | if (ie->flags & INDEX_ENTRY_END) | ||
148 | break; | ||
149 | /* | ||
150 | * We perform a case sensitive comparison and if that matches | ||
151 | * we are done and return the mft reference of the inode (i.e. | ||
152 | * the inode number together with the sequence number for | ||
153 | * consistency checking). We convert it to cpu format before | ||
154 | * returning. | ||
155 | */ | ||
156 | if (ntfs_are_names_equal(uname, uname_len, | ||
157 | (ntfschar*)&ie->key.file_name.file_name, | ||
158 | ie->key.file_name.file_name_length, | ||
159 | CASE_SENSITIVE, vol->upcase, vol->upcase_len)) { | ||
160 | found_it: | ||
161 | /* | ||
162 | * We have a perfect match, so we don't need to care | ||
163 | * about having matched imperfectly before, so we can | ||
164 | * free name and set *res to NULL. | ||
165 | * However, if the perfect match is a short file name, | ||
166 | * we need to signal this through *res, so that | ||
167 | * ntfs_lookup() can fix dcache aliasing issues. | ||
168 | * As an optimization we just reuse an existing | ||
169 | * allocation of *res. | ||
170 | */ | ||
171 | if (ie->key.file_name.file_name_type == FILE_NAME_DOS) { | ||
172 | if (!name) { | ||
173 | name = kmalloc(sizeof(ntfs_name), | ||
174 | GFP_NOFS); | ||
175 | if (!name) { | ||
176 | err = -ENOMEM; | ||
177 | goto err_out; | ||
178 | } | ||
179 | } | ||
180 | name->mref = le64_to_cpu( | ||
181 | ie->data.dir.indexed_file); | ||
182 | name->type = FILE_NAME_DOS; | ||
183 | name->len = 0; | ||
184 | *res = name; | ||
185 | } else { | ||
186 | if (name) | ||
187 | kfree(name); | ||
188 | *res = NULL; | ||
189 | } | ||
190 | mref = le64_to_cpu(ie->data.dir.indexed_file); | ||
191 | ntfs_attr_put_search_ctx(ctx); | ||
192 | unmap_mft_record(dir_ni); | ||
193 | return mref; | ||
194 | } | ||
195 | /* | ||
196 | * For a case insensitive mount, we also perform a case | ||
197 | * insensitive comparison (provided the file name is not in the | ||
198 | * POSIX namespace). If the comparison matches, and the name is | ||
199 | * in the WIN32 namespace, we cache the filename in *res so | ||
200 | * that the caller, ntfs_lookup(), can work on it. If the | ||
201 | * comparison matches, and the name is in the DOS namespace, we | ||
202 | * only cache the mft reference and the file name type (we set | ||
203 | * the name length to zero for simplicity). | ||
204 | */ | ||
205 | if (!NVolCaseSensitive(vol) && | ||
206 | ie->key.file_name.file_name_type && | ||
207 | ntfs_are_names_equal(uname, uname_len, | ||
208 | (ntfschar*)&ie->key.file_name.file_name, | ||
209 | ie->key.file_name.file_name_length, | ||
210 | IGNORE_CASE, vol->upcase, vol->upcase_len)) { | ||
211 | int name_size = sizeof(ntfs_name); | ||
212 | u8 type = ie->key.file_name.file_name_type; | ||
213 | u8 len = ie->key.file_name.file_name_length; | ||
214 | |||
215 | /* Only one case insensitive matching name allowed. */ | ||
216 | if (name) { | ||
217 | ntfs_error(sb, "Found already allocated name " | ||
218 | "in phase 1. Please run chkdsk " | ||
219 | "and if that doesn't find any " | ||
220 | "errors please report you saw " | ||
221 | "this message to " | ||
222 | "linux-ntfs-dev@lists." | ||
223 | "sourceforge.net."); | ||
224 | goto dir_err_out; | ||
225 | } | ||
226 | |||
227 | if (type != FILE_NAME_DOS) | ||
228 | name_size += len * sizeof(ntfschar); | ||
229 | name = kmalloc(name_size, GFP_NOFS); | ||
230 | if (!name) { | ||
231 | err = -ENOMEM; | ||
232 | goto err_out; | ||
233 | } | ||
234 | name->mref = le64_to_cpu(ie->data.dir.indexed_file); | ||
235 | name->type = type; | ||
236 | if (type != FILE_NAME_DOS) { | ||
237 | name->len = len; | ||
238 | memcpy(name->name, ie->key.file_name.file_name, | ||
239 | len * sizeof(ntfschar)); | ||
240 | } else | ||
241 | name->len = 0; | ||
242 | *res = name; | ||
243 | } | ||
244 | /* | ||
245 | * Not a perfect match, need to do full blown collation so we | ||
246 | * know which way in the B+tree we have to go. | ||
247 | */ | ||
248 | rc = ntfs_collate_names(uname, uname_len, | ||
249 | (ntfschar*)&ie->key.file_name.file_name, | ||
250 | ie->key.file_name.file_name_length, 1, | ||
251 | IGNORE_CASE, vol->upcase, vol->upcase_len); | ||
252 | /* | ||
253 | * If uname collates before the name of the current entry, there | ||
254 | * is definitely no such name in this index but we might need to | ||
255 | * descend into the B+tree so we just break out of the loop. | ||
256 | */ | ||
257 | if (rc == -1) | ||
258 | break; | ||
259 | /* The names are not equal, continue the search. */ | ||
260 | if (rc) | ||
261 | continue; | ||
262 | /* | ||
263 | * Names match with case insensitive comparison, now try the | ||
264 | * case sensitive comparison, which is required for proper | ||
265 | * collation. | ||
266 | */ | ||
267 | rc = ntfs_collate_names(uname, uname_len, | ||
268 | (ntfschar*)&ie->key.file_name.file_name, | ||
269 | ie->key.file_name.file_name_length, 1, | ||
270 | CASE_SENSITIVE, vol->upcase, vol->upcase_len); | ||
271 | if (rc == -1) | ||
272 | break; | ||
273 | if (rc) | ||
274 | continue; | ||
275 | /* | ||
276 | * Perfect match, this will never happen as the | ||
277 | * ntfs_are_names_equal() call will have gotten a match but we | ||
278 | * still treat it correctly. | ||
279 | */ | ||
280 | goto found_it; | ||
281 | } | ||
282 | /* | ||
283 | * We have finished with this index without success. Check for the | ||
284 | * presence of a child node and if not present return -ENOENT, unless | ||
285 | * we have got a matching name cached in name in which case return the | ||
286 | * mft reference associated with it. | ||
287 | */ | ||
288 | if (!(ie->flags & INDEX_ENTRY_NODE)) { | ||
289 | if (name) { | ||
290 | ntfs_attr_put_search_ctx(ctx); | ||
291 | unmap_mft_record(dir_ni); | ||
292 | return name->mref; | ||
293 | } | ||
294 | ntfs_debug("Entry not found."); | ||
295 | err = -ENOENT; | ||
296 | goto err_out; | ||
297 | } /* Child node present, descend into it. */ | ||
298 | /* Consistency check: Verify that an index allocation exists. */ | ||
299 | if (!NInoIndexAllocPresent(dir_ni)) { | ||
300 | ntfs_error(sb, "No index allocation attribute but index entry " | ||
301 | "requires one. Directory inode 0x%lx is " | ||
302 | "corrupt or driver bug.", dir_ni->mft_no); | ||
303 | goto err_out; | ||
304 | } | ||
305 | /* Get the starting vcn of the index_block holding the child node. */ | ||
306 | vcn = sle64_to_cpup((sle64*)((u8*)ie + le16_to_cpu(ie->length) - 8)); | ||
307 | ia_mapping = VFS_I(dir_ni)->i_mapping; | ||
308 | /* | ||
309 | * We are done with the index root and the mft record. Release them, | ||
310 | * otherwise we deadlock with ntfs_map_page(). | ||
311 | */ | ||
312 | ntfs_attr_put_search_ctx(ctx); | ||
313 | unmap_mft_record(dir_ni); | ||
314 | m = NULL; | ||
315 | ctx = NULL; | ||
316 | descend_into_child_node: | ||
317 | /* | ||
318 | * Convert vcn to index into the index allocation attribute in units | ||
319 | * of PAGE_CACHE_SIZE and map the page cache page, reading it from | ||
320 | * disk if necessary. | ||
321 | */ | ||
322 | page = ntfs_map_page(ia_mapping, vcn << | ||
323 | dir_ni->itype.index.vcn_size_bits >> PAGE_CACHE_SHIFT); | ||
324 | if (IS_ERR(page)) { | ||
325 | ntfs_error(sb, "Failed to map directory index page, error %ld.", | ||
326 | -PTR_ERR(page)); | ||
327 | err = PTR_ERR(page); | ||
328 | goto err_out; | ||
329 | } | ||
330 | lock_page(page); | ||
331 | kaddr = (u8*)page_address(page); | ||
332 | fast_descend_into_child_node: | ||
333 | /* Get to the index allocation block. */ | ||
334 | ia = (INDEX_ALLOCATION*)(kaddr + ((vcn << | ||
335 | dir_ni->itype.index.vcn_size_bits) & ~PAGE_CACHE_MASK)); | ||
336 | /* Bounds checks. */ | ||
337 | if ((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE) { | ||
338 | ntfs_error(sb, "Out of bounds check failed. Corrupt directory " | ||
339 | "inode 0x%lx or driver bug.", dir_ni->mft_no); | ||
340 | goto unm_err_out; | ||
341 | } | ||
342 | /* Catch multi sector transfer fixup errors. */ | ||
343 | if (unlikely(!ntfs_is_indx_record(ia->magic))) { | ||
344 | ntfs_error(sb, "Directory index record with vcn 0x%llx is " | ||
345 | "corrupt. Corrupt inode 0x%lx. Run chkdsk.", | ||
346 | (unsigned long long)vcn, dir_ni->mft_no); | ||
347 | goto unm_err_out; | ||
348 | } | ||
349 | if (sle64_to_cpu(ia->index_block_vcn) != vcn) { | ||
350 | ntfs_error(sb, "Actual VCN (0x%llx) of index buffer is " | ||
351 | "different from expected VCN (0x%llx). " | ||
352 | "Directory inode 0x%lx is corrupt or driver " | ||
353 | "bug.", (unsigned long long) | ||
354 | sle64_to_cpu(ia->index_block_vcn), | ||
355 | (unsigned long long)vcn, dir_ni->mft_no); | ||
356 | goto unm_err_out; | ||
357 | } | ||
358 | if (le32_to_cpu(ia->index.allocated_size) + 0x18 != | ||
359 | dir_ni->itype.index.block_size) { | ||
360 | ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode " | ||
361 | "0x%lx has a size (%u) differing from the " | ||
362 | "directory specified size (%u). Directory " | ||
363 | "inode is corrupt or driver bug.", | ||
364 | (unsigned long long)vcn, dir_ni->mft_no, | ||
365 | le32_to_cpu(ia->index.allocated_size) + 0x18, | ||
366 | dir_ni->itype.index.block_size); | ||
367 | goto unm_err_out; | ||
368 | } | ||
369 | index_end = (u8*)ia + dir_ni->itype.index.block_size; | ||
370 | if (index_end > kaddr + PAGE_CACHE_SIZE) { | ||
371 | ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode " | ||
372 | "0x%lx crosses page boundary. Impossible! " | ||
373 | "Cannot access! This is probably a bug in the " | ||
374 | "driver.", (unsigned long long)vcn, | ||
375 | dir_ni->mft_no); | ||
376 | goto unm_err_out; | ||
377 | } | ||
378 | index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length); | ||
379 | if (index_end > (u8*)ia + dir_ni->itype.index.block_size) { | ||
380 | ntfs_error(sb, "Size of index buffer (VCN 0x%llx) of directory " | ||
381 | "inode 0x%lx exceeds maximum size.", | ||
382 | (unsigned long long)vcn, dir_ni->mft_no); | ||
383 | goto unm_err_out; | ||
384 | } | ||
385 | /* The first index entry. */ | ||
386 | ie = (INDEX_ENTRY*)((u8*)&ia->index + | ||
387 | le32_to_cpu(ia->index.entries_offset)); | ||
388 | /* | ||
389 | * Iterate similar to above big loop but applied to index buffer, thus | ||
390 | * loop until we exceed valid memory (corruption case) or until we | ||
391 | * reach the last entry. | ||
392 | */ | ||
393 | for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { | ||
394 | /* Bounds check. */ | ||
395 | if ((u8*)ie < (u8*)ia || (u8*)ie + | ||
396 | sizeof(INDEX_ENTRY_HEADER) > index_end || | ||
397 | (u8*)ie + le16_to_cpu(ie->key_length) > | ||
398 | index_end) { | ||
399 | ntfs_error(sb, "Index entry out of bounds in " | ||
400 | "directory inode 0x%lx.", | ||
401 | dir_ni->mft_no); | ||
402 | goto unm_err_out; | ||
403 | } | ||
404 | /* | ||
405 | * The last entry cannot contain a name. It can however contain | ||
406 | * a pointer to a child node in the B+tree so we just break out. | ||
407 | */ | ||
408 | if (ie->flags & INDEX_ENTRY_END) | ||
409 | break; | ||
410 | /* | ||
411 | * We perform a case sensitive comparison and if that matches | ||
412 | * we are done and return the mft reference of the inode (i.e. | ||
413 | * the inode number together with the sequence number for | ||
414 | * consistency checking). We convert it to cpu format before | ||
415 | * returning. | ||
416 | */ | ||
417 | if (ntfs_are_names_equal(uname, uname_len, | ||
418 | (ntfschar*)&ie->key.file_name.file_name, | ||
419 | ie->key.file_name.file_name_length, | ||
420 | CASE_SENSITIVE, vol->upcase, vol->upcase_len)) { | ||
421 | found_it2: | ||
422 | /* | ||
423 | * We have a perfect match, so we don't need to care | ||
424 | * about having matched imperfectly before, so we can | ||
425 | * free name and set *res to NULL. | ||
426 | * However, if the perfect match is a short file name, | ||
427 | * we need to signal this through *res, so that | ||
428 | * ntfs_lookup() can fix dcache aliasing issues. | ||
429 | * As an optimization we just reuse an existing | ||
430 | * allocation of *res. | ||
431 | */ | ||
432 | if (ie->key.file_name.file_name_type == FILE_NAME_DOS) { | ||
433 | if (!name) { | ||
434 | name = kmalloc(sizeof(ntfs_name), | ||
435 | GFP_NOFS); | ||
436 | if (!name) { | ||
437 | err = -ENOMEM; | ||
438 | goto unm_err_out; | ||
439 | } | ||
440 | } | ||
441 | name->mref = le64_to_cpu( | ||
442 | ie->data.dir.indexed_file); | ||
443 | name->type = FILE_NAME_DOS; | ||
444 | name->len = 0; | ||
445 | *res = name; | ||
446 | } else { | ||
447 | if (name) | ||
448 | kfree(name); | ||
449 | *res = NULL; | ||
450 | } | ||
451 | mref = le64_to_cpu(ie->data.dir.indexed_file); | ||
452 | unlock_page(page); | ||
453 | ntfs_unmap_page(page); | ||
454 | return mref; | ||
455 | } | ||
456 | /* | ||
457 | * For a case insensitive mount, we also perform a case | ||
458 | * insensitive comparison (provided the file name is not in the | ||
459 | * POSIX namespace). If the comparison matches, and the name is | ||
460 | * in the WIN32 namespace, we cache the filename in *res so | ||
461 | * that the caller, ntfs_lookup(), can work on it. If the | ||
462 | * comparison matches, and the name is in the DOS namespace, we | ||
463 | * only cache the mft reference and the file name type (we set | ||
464 | * the name length to zero for simplicity). | ||
465 | */ | ||
466 | if (!NVolCaseSensitive(vol) && | ||
467 | ie->key.file_name.file_name_type && | ||
468 | ntfs_are_names_equal(uname, uname_len, | ||
469 | (ntfschar*)&ie->key.file_name.file_name, | ||
470 | ie->key.file_name.file_name_length, | ||
471 | IGNORE_CASE, vol->upcase, vol->upcase_len)) { | ||
472 | int name_size = sizeof(ntfs_name); | ||
473 | u8 type = ie->key.file_name.file_name_type; | ||
474 | u8 len = ie->key.file_name.file_name_length; | ||
475 | |||
476 | /* Only one case insensitive matching name allowed. */ | ||
477 | if (name) { | ||
478 | ntfs_error(sb, "Found already allocated name " | ||
479 | "in phase 2. Please run chkdsk " | ||
480 | "and if that doesn't find any " | ||
481 | "errors please report you saw " | ||
482 | "this message to " | ||
483 | "linux-ntfs-dev@lists." | ||
484 | "sourceforge.net."); | ||
485 | unlock_page(page); | ||
486 | ntfs_unmap_page(page); | ||
487 | goto dir_err_out; | ||
488 | } | ||
489 | |||
490 | if (type != FILE_NAME_DOS) | ||
491 | name_size += len * sizeof(ntfschar); | ||
492 | name = kmalloc(name_size, GFP_NOFS); | ||
493 | if (!name) { | ||
494 | err = -ENOMEM; | ||
495 | goto unm_err_out; | ||
496 | } | ||
497 | name->mref = le64_to_cpu(ie->data.dir.indexed_file); | ||
498 | name->type = type; | ||
499 | if (type != FILE_NAME_DOS) { | ||
500 | name->len = len; | ||
501 | memcpy(name->name, ie->key.file_name.file_name, | ||
502 | len * sizeof(ntfschar)); | ||
503 | } else | ||
504 | name->len = 0; | ||
505 | *res = name; | ||
506 | } | ||
507 | /* | ||
508 | * Not a perfect match, need to do full blown collation so we | ||
509 | * know which way in the B+tree we have to go. | ||
510 | */ | ||
511 | rc = ntfs_collate_names(uname, uname_len, | ||
512 | (ntfschar*)&ie->key.file_name.file_name, | ||
513 | ie->key.file_name.file_name_length, 1, | ||
514 | IGNORE_CASE, vol->upcase, vol->upcase_len); | ||
515 | /* | ||
516 | * If uname collates before the name of the current entry, there | ||
517 | * is definitely no such name in this index but we might need to | ||
518 | * descend into the B+tree so we just break out of the loop. | ||
519 | */ | ||
520 | if (rc == -1) | ||
521 | break; | ||
522 | /* The names are not equal, continue the search. */ | ||
523 | if (rc) | ||
524 | continue; | ||
525 | /* | ||
526 | * Names match with case insensitive comparison, now try the | ||
527 | * case sensitive comparison, which is required for proper | ||
528 | * collation. | ||
529 | */ | ||
530 | rc = ntfs_collate_names(uname, uname_len, | ||
531 | (ntfschar*)&ie->key.file_name.file_name, | ||
532 | ie->key.file_name.file_name_length, 1, | ||
533 | CASE_SENSITIVE, vol->upcase, vol->upcase_len); | ||
534 | if (rc == -1) | ||
535 | break; | ||
536 | if (rc) | ||
537 | continue; | ||
538 | /* | ||
539 | * Perfect match, this will never happen as the | ||
540 | * ntfs_are_names_equal() call will have gotten a match but we | ||
541 | * still treat it correctly. | ||
542 | */ | ||
543 | goto found_it2; | ||
544 | } | ||
545 | /* | ||
546 | * We have finished with this index buffer without success. Check for | ||
547 | * the presence of a child node. | ||
548 | */ | ||
549 | if (ie->flags & INDEX_ENTRY_NODE) { | ||
550 | if ((ia->index.flags & NODE_MASK) == LEAF_NODE) { | ||
551 | ntfs_error(sb, "Index entry with child node found in " | ||
552 | "a leaf node in directory inode 0x%lx.", | ||
553 | dir_ni->mft_no); | ||
554 | goto unm_err_out; | ||
555 | } | ||
556 | /* Child node present, descend into it. */ | ||
557 | old_vcn = vcn; | ||
558 | vcn = sle64_to_cpup((sle64*)((u8*)ie + | ||
559 | le16_to_cpu(ie->length) - 8)); | ||
560 | if (vcn >= 0) { | ||
561 | /* If vcn is in the same page cache page as old_vcn we | ||
562 | * recycle the mapped page. */ | ||
563 | if (old_vcn << vol->cluster_size_bits >> | ||
564 | PAGE_CACHE_SHIFT == vcn << | ||
565 | vol->cluster_size_bits >> | ||
566 | PAGE_CACHE_SHIFT) | ||
567 | goto fast_descend_into_child_node; | ||
568 | unlock_page(page); | ||
569 | ntfs_unmap_page(page); | ||
570 | goto descend_into_child_node; | ||
571 | } | ||
572 | ntfs_error(sb, "Negative child node vcn in directory inode " | ||
573 | "0x%lx.", dir_ni->mft_no); | ||
574 | goto unm_err_out; | ||
575 | } | ||
576 | /* | ||
577 | * No child node present, return -ENOENT, unless we have got a matching | ||
578 | * name cached in name in which case return the mft reference | ||
579 | * associated with it. | ||
580 | */ | ||
581 | if (name) { | ||
582 | unlock_page(page); | ||
583 | ntfs_unmap_page(page); | ||
584 | return name->mref; | ||
585 | } | ||
586 | ntfs_debug("Entry not found."); | ||
587 | err = -ENOENT; | ||
588 | unm_err_out: | ||
589 | unlock_page(page); | ||
590 | ntfs_unmap_page(page); | ||
591 | err_out: | ||
592 | if (!err) | ||
593 | err = -EIO; | ||
594 | if (ctx) | ||
595 | ntfs_attr_put_search_ctx(ctx); | ||
596 | if (m) | ||
597 | unmap_mft_record(dir_ni); | ||
598 | if (name) { | ||
599 | kfree(name); | ||
600 | *res = NULL; | ||
601 | } | ||
602 | return ERR_MREF(err); | ||
603 | dir_err_out: | ||
604 | ntfs_error(sb, "Corrupt directory. Aborting lookup."); | ||
605 | goto err_out; | ||
606 | } | ||
607 | |||
608 | #if 0 | ||
609 | |||
610 | // TODO: (AIA) | ||
611 | // The algorithm embedded in this code will be required for the time when we | ||
612 | // want to support adding of entries to directories, where we require correct | ||
613 | // collation of file names in order not to cause corruption of the file system. | ||
614 | |||
615 | /** | ||
616 | * ntfs_lookup_inode_by_name - find an inode in a directory given its name | ||
617 | * @dir_ni: ntfs inode of the directory in which to search for the name | ||
618 | * @uname: Unicode name for which to search in the directory | ||
619 | * @uname_len: length of the name @uname in Unicode characters | ||
620 | * | ||
621 | * Look for an inode with name @uname in the directory with inode @dir_ni. | ||
622 | * ntfs_lookup_inode_by_name() walks the contents of the directory looking for | ||
623 | * the Unicode name. If the name is found in the directory, the corresponding | ||
624 | * inode number (>= 0) is returned as a mft reference in cpu format, i.e. it | ||
625 | * is a 64-bit number containing the sequence number. | ||
626 | * | ||
627 | * On error, a negative value is returned corresponding to the error code. In | ||
628 | * particular if the inode is not found -ENOENT is returned. Note that you | ||
629 | * can't just check the return value for being negative, you have to check the | ||
630 | * inode number for being negative which you can extract using MREC(return | ||
631 | * value). | ||
632 | * | ||
633 | * Note, @uname_len does not include the (optional) terminating NULL character. | ||
634 | */ | ||
635 | u64 ntfs_lookup_inode_by_name(ntfs_inode *dir_ni, const ntfschar *uname, | ||
636 | const int uname_len) | ||
637 | { | ||
638 | ntfs_volume *vol = dir_ni->vol; | ||
639 | struct super_block *sb = vol->sb; | ||
640 | MFT_RECORD *m; | ||
641 | INDEX_ROOT *ir; | ||
642 | INDEX_ENTRY *ie; | ||
643 | INDEX_ALLOCATION *ia; | ||
644 | u8 *index_end; | ||
645 | u64 mref; | ||
646 | ntfs_attr_search_ctx *ctx; | ||
647 | int err, rc; | ||
648 | IGNORE_CASE_BOOL ic; | ||
649 | VCN vcn, old_vcn; | ||
650 | struct address_space *ia_mapping; | ||
651 | struct page *page; | ||
652 | u8 *kaddr; | ||
653 | |||
654 | /* Get hold of the mft record for the directory. */ | ||
655 | m = map_mft_record(dir_ni); | ||
656 | if (IS_ERR(m)) { | ||
657 | ntfs_error(sb, "map_mft_record() failed with error code %ld.", | ||
658 | -PTR_ERR(m)); | ||
659 | return ERR_MREF(PTR_ERR(m)); | ||
660 | } | ||
661 | ctx = ntfs_attr_get_search_ctx(dir_ni, m); | ||
662 | if (!ctx) { | ||
663 | err = -ENOMEM; | ||
664 | goto err_out; | ||
665 | } | ||
666 | /* Find the index root attribute in the mft record. */ | ||
667 | err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, | ||
668 | 0, ctx); | ||
669 | if (unlikely(err)) { | ||
670 | if (err == -ENOENT) { | ||
671 | ntfs_error(sb, "Index root attribute missing in " | ||
672 | "directory inode 0x%lx.", | ||
673 | dir_ni->mft_no); | ||
674 | err = -EIO; | ||
675 | } | ||
676 | goto err_out; | ||
677 | } | ||
678 | /* Get to the index root value (it's been verified in read_inode). */ | ||
679 | ir = (INDEX_ROOT*)((u8*)ctx->attr + | ||
680 | le16_to_cpu(ctx->attr->data.resident.value_offset)); | ||
681 | index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length); | ||
682 | /* The first index entry. */ | ||
683 | ie = (INDEX_ENTRY*)((u8*)&ir->index + | ||
684 | le32_to_cpu(ir->index.entries_offset)); | ||
685 | /* | ||
686 | * Loop until we exceed valid memory (corruption case) or until we | ||
687 | * reach the last entry. | ||
688 | */ | ||
689 | for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { | ||
690 | /* Bounds checks. */ | ||
691 | if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie + | ||
692 | sizeof(INDEX_ENTRY_HEADER) > index_end || | ||
693 | (u8*)ie + le16_to_cpu(ie->key_length) > | ||
694 | index_end) | ||
695 | goto dir_err_out; | ||
696 | /* | ||
697 | * The last entry cannot contain a name. It can however contain | ||
698 | * a pointer to a child node in the B+tree so we just break out. | ||
699 | */ | ||
700 | if (ie->flags & INDEX_ENTRY_END) | ||
701 | break; | ||
702 | /* | ||
703 | * If the current entry has a name type of POSIX, the name is | ||
704 | * case sensitive and not otherwise. This has the effect of us | ||
705 | * not being able to access any POSIX file names which collate | ||
706 | * after the non-POSIX one when they only differ in case, but | ||
707 | * anyone doing screwy stuff like that deserves to burn in | ||
708 | * hell... Doing that kind of stuff on NT4 actually causes | ||
709 | * corruption on the partition even when using SP6a and Linux | ||
710 | * is not involved at all. | ||
711 | */ | ||
712 | ic = ie->key.file_name.file_name_type ? IGNORE_CASE : | ||
713 | CASE_SENSITIVE; | ||
714 | /* | ||
715 | * If the names match perfectly, we are done and return the | ||
716 | * mft reference of the inode (i.e. the inode number together | ||
717 | * with the sequence number for consistency checking. We | ||
718 | * convert it to cpu format before returning. | ||
719 | */ | ||
720 | if (ntfs_are_names_equal(uname, uname_len, | ||
721 | (ntfschar*)&ie->key.file_name.file_name, | ||
722 | ie->key.file_name.file_name_length, ic, | ||
723 | vol->upcase, vol->upcase_len)) { | ||
724 | found_it: | ||
725 | mref = le64_to_cpu(ie->data.dir.indexed_file); | ||
726 | ntfs_attr_put_search_ctx(ctx); | ||
727 | unmap_mft_record(dir_ni); | ||
728 | return mref; | ||
729 | } | ||
730 | /* | ||
731 | * Not a perfect match, need to do full blown collation so we | ||
732 | * know which way in the B+tree we have to go. | ||
733 | */ | ||
734 | rc = ntfs_collate_names(uname, uname_len, | ||
735 | (ntfschar*)&ie->key.file_name.file_name, | ||
736 | ie->key.file_name.file_name_length, 1, | ||
737 | IGNORE_CASE, vol->upcase, vol->upcase_len); | ||
738 | /* | ||
739 | * If uname collates before the name of the current entry, there | ||
740 | * is definitely no such name in this index but we might need to | ||
741 | * descend into the B+tree so we just break out of the loop. | ||
742 | */ | ||
743 | if (rc == -1) | ||
744 | break; | ||
745 | /* The names are not equal, continue the search. */ | ||
746 | if (rc) | ||
747 | continue; | ||
748 | /* | ||
749 | * Names match with case insensitive comparison, now try the | ||
750 | * case sensitive comparison, which is required for proper | ||
751 | * collation. | ||
752 | */ | ||
753 | rc = ntfs_collate_names(uname, uname_len, | ||
754 | (ntfschar*)&ie->key.file_name.file_name, | ||
755 | ie->key.file_name.file_name_length, 1, | ||
756 | CASE_SENSITIVE, vol->upcase, vol->upcase_len); | ||
757 | if (rc == -1) | ||
758 | break; | ||
759 | if (rc) | ||
760 | continue; | ||
761 | /* | ||
762 | * Perfect match, this will never happen as the | ||
763 | * ntfs_are_names_equal() call will have gotten a match but we | ||
764 | * still treat it correctly. | ||
765 | */ | ||
766 | goto found_it; | ||
767 | } | ||
768 | /* | ||
769 | * We have finished with this index without success. Check for the | ||
770 | * presence of a child node. | ||
771 | */ | ||
772 | if (!(ie->flags & INDEX_ENTRY_NODE)) { | ||
773 | /* No child node, return -ENOENT. */ | ||
774 | err = -ENOENT; | ||
775 | goto err_out; | ||
776 | } /* Child node present, descend into it. */ | ||
777 | /* Consistency check: Verify that an index allocation exists. */ | ||
778 | if (!NInoIndexAllocPresent(dir_ni)) { | ||
779 | ntfs_error(sb, "No index allocation attribute but index entry " | ||
780 | "requires one. Directory inode 0x%lx is " | ||
781 | "corrupt or driver bug.", dir_ni->mft_no); | ||
782 | goto err_out; | ||
783 | } | ||
784 | /* Get the starting vcn of the index_block holding the child node. */ | ||
785 | vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8); | ||
786 | ia_mapping = VFS_I(dir_ni)->i_mapping; | ||
787 | /* | ||
788 | * We are done with the index root and the mft record. Release them, | ||
789 | * otherwise we deadlock with ntfs_map_page(). | ||
790 | */ | ||
791 | ntfs_attr_put_search_ctx(ctx); | ||
792 | unmap_mft_record(dir_ni); | ||
793 | m = NULL; | ||
794 | ctx = NULL; | ||
795 | descend_into_child_node: | ||
796 | /* | ||
797 | * Convert vcn to index into the index allocation attribute in units | ||
798 | * of PAGE_CACHE_SIZE and map the page cache page, reading it from | ||
799 | * disk if necessary. | ||
800 | */ | ||
801 | page = ntfs_map_page(ia_mapping, vcn << | ||
802 | dir_ni->itype.index.vcn_size_bits >> PAGE_CACHE_SHIFT); | ||
803 | if (IS_ERR(page)) { | ||
804 | ntfs_error(sb, "Failed to map directory index page, error %ld.", | ||
805 | -PTR_ERR(page)); | ||
806 | err = PTR_ERR(page); | ||
807 | goto err_out; | ||
808 | } | ||
809 | lock_page(page); | ||
810 | kaddr = (u8*)page_address(page); | ||
811 | fast_descend_into_child_node: | ||
812 | /* Get to the index allocation block. */ | ||
813 | ia = (INDEX_ALLOCATION*)(kaddr + ((vcn << | ||
814 | dir_ni->itype.index.vcn_size_bits) & ~PAGE_CACHE_MASK)); | ||
815 | /* Bounds checks. */ | ||
816 | if ((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE) { | ||
817 | ntfs_error(sb, "Out of bounds check failed. Corrupt directory " | ||
818 | "inode 0x%lx or driver bug.", dir_ni->mft_no); | ||
819 | goto unm_err_out; | ||
820 | } | ||
821 | /* Catch multi sector transfer fixup errors. */ | ||
822 | if (unlikely(!ntfs_is_indx_record(ia->magic))) { | ||
823 | ntfs_error(sb, "Directory index record with vcn 0x%llx is " | ||
824 | "corrupt. Corrupt inode 0x%lx. Run chkdsk.", | ||
825 | (unsigned long long)vcn, dir_ni->mft_no); | ||
826 | goto unm_err_out; | ||
827 | } | ||
828 | if (sle64_to_cpu(ia->index_block_vcn) != vcn) { | ||
829 | ntfs_error(sb, "Actual VCN (0x%llx) of index buffer is " | ||
830 | "different from expected VCN (0x%llx). " | ||
831 | "Directory inode 0x%lx is corrupt or driver " | ||
832 | "bug.", (unsigned long long) | ||
833 | sle64_to_cpu(ia->index_block_vcn), | ||
834 | (unsigned long long)vcn, dir_ni->mft_no); | ||
835 | goto unm_err_out; | ||
836 | } | ||
837 | if (le32_to_cpu(ia->index.allocated_size) + 0x18 != | ||
838 | dir_ni->itype.index.block_size) { | ||
839 | ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode " | ||
840 | "0x%lx has a size (%u) differing from the " | ||
841 | "directory specified size (%u). Directory " | ||
842 | "inode is corrupt or driver bug.", | ||
843 | (unsigned long long)vcn, dir_ni->mft_no, | ||
844 | le32_to_cpu(ia->index.allocated_size) + 0x18, | ||
845 | dir_ni->itype.index.block_size); | ||
846 | goto unm_err_out; | ||
847 | } | ||
848 | index_end = (u8*)ia + dir_ni->itype.index.block_size; | ||
849 | if (index_end > kaddr + PAGE_CACHE_SIZE) { | ||
850 | ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode " | ||
851 | "0x%lx crosses page boundary. Impossible! " | ||
852 | "Cannot access! This is probably a bug in the " | ||
853 | "driver.", (unsigned long long)vcn, | ||
854 | dir_ni->mft_no); | ||
855 | goto unm_err_out; | ||
856 | } | ||
857 | index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length); | ||
858 | if (index_end > (u8*)ia + dir_ni->itype.index.block_size) { | ||
859 | ntfs_error(sb, "Size of index buffer (VCN 0x%llx) of directory " | ||
860 | "inode 0x%lx exceeds maximum size.", | ||
861 | (unsigned long long)vcn, dir_ni->mft_no); | ||
862 | goto unm_err_out; | ||
863 | } | ||
864 | /* The first index entry. */ | ||
865 | ie = (INDEX_ENTRY*)((u8*)&ia->index + | ||
866 | le32_to_cpu(ia->index.entries_offset)); | ||
867 | /* | ||
868 | * Iterate similar to above big loop but applied to index buffer, thus | ||
869 | * loop until we exceed valid memory (corruption case) or until we | ||
870 | * reach the last entry. | ||
871 | */ | ||
872 | for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { | ||
873 | /* Bounds check. */ | ||
874 | if ((u8*)ie < (u8*)ia || (u8*)ie + | ||
875 | sizeof(INDEX_ENTRY_HEADER) > index_end || | ||
876 | (u8*)ie + le16_to_cpu(ie->key_length) > | ||
877 | index_end) { | ||
878 | ntfs_error(sb, "Index entry out of bounds in " | ||
879 | "directory inode 0x%lx.", | ||
880 | dir_ni->mft_no); | ||
881 | goto unm_err_out; | ||
882 | } | ||
883 | /* | ||
884 | * The last entry cannot contain a name. It can however contain | ||
885 | * a pointer to a child node in the B+tree so we just break out. | ||
886 | */ | ||
887 | if (ie->flags & INDEX_ENTRY_END) | ||
888 | break; | ||
889 | /* | ||
890 | * If the current entry has a name type of POSIX, the name is | ||
891 | * case sensitive and not otherwise. This has the effect of us | ||
892 | * not being able to access any POSIX file names which collate | ||
893 | * after the non-POSIX one when they only differ in case, but | ||
894 | * anyone doing screwy stuff like that deserves to burn in | ||
895 | * hell... Doing that kind of stuff on NT4 actually causes | ||
896 | * corruption on the partition even when using SP6a and Linux | ||
897 | * is not involved at all. | ||
898 | */ | ||
899 | ic = ie->key.file_name.file_name_type ? IGNORE_CASE : | ||
900 | CASE_SENSITIVE; | ||
901 | /* | ||
902 | * If the names match perfectly, we are done and return the | ||
903 | * mft reference of the inode (i.e. the inode number together | ||
904 | * with the sequence number for consistency checking. We | ||
905 | * convert it to cpu format before returning. | ||
906 | */ | ||
907 | if (ntfs_are_names_equal(uname, uname_len, | ||
908 | (ntfschar*)&ie->key.file_name.file_name, | ||
909 | ie->key.file_name.file_name_length, ic, | ||
910 | vol->upcase, vol->upcase_len)) { | ||
911 | found_it2: | ||
912 | mref = le64_to_cpu(ie->data.dir.indexed_file); | ||
913 | unlock_page(page); | ||
914 | ntfs_unmap_page(page); | ||
915 | return mref; | ||
916 | } | ||
917 | /* | ||
918 | * Not a perfect match, need to do full blown collation so we | ||
919 | * know which way in the B+tree we have to go. | ||
920 | */ | ||
921 | rc = ntfs_collate_names(uname, uname_len, | ||
922 | (ntfschar*)&ie->key.file_name.file_name, | ||
923 | ie->key.file_name.file_name_length, 1, | ||
924 | IGNORE_CASE, vol->upcase, vol->upcase_len); | ||
925 | /* | ||
926 | * If uname collates before the name of the current entry, there | ||
927 | * is definitely no such name in this index but we might need to | ||
928 | * descend into the B+tree so we just break out of the loop. | ||
929 | */ | ||
930 | if (rc == -1) | ||
931 | break; | ||
932 | /* The names are not equal, continue the search. */ | ||
933 | if (rc) | ||
934 | continue; | ||
935 | /* | ||
936 | * Names match with case insensitive comparison, now try the | ||
937 | * case sensitive comparison, which is required for proper | ||
938 | * collation. | ||
939 | */ | ||
940 | rc = ntfs_collate_names(uname, uname_len, | ||
941 | (ntfschar*)&ie->key.file_name.file_name, | ||
942 | ie->key.file_name.file_name_length, 1, | ||
943 | CASE_SENSITIVE, vol->upcase, vol->upcase_len); | ||
944 | if (rc == -1) | ||
945 | break; | ||
946 | if (rc) | ||
947 | continue; | ||
948 | /* | ||
949 | * Perfect match, this will never happen as the | ||
950 | * ntfs_are_names_equal() call will have gotten a match but we | ||
951 | * still treat it correctly. | ||
952 | */ | ||
953 | goto found_it2; | ||
954 | } | ||
955 | /* | ||
956 | * We have finished with this index buffer without success. Check for | ||
957 | * the presence of a child node. | ||
958 | */ | ||
959 | if (ie->flags & INDEX_ENTRY_NODE) { | ||
960 | if ((ia->index.flags & NODE_MASK) == LEAF_NODE) { | ||
961 | ntfs_error(sb, "Index entry with child node found in " | ||
962 | "a leaf node in directory inode 0x%lx.", | ||
963 | dir_ni->mft_no); | ||
964 | goto unm_err_out; | ||
965 | } | ||
966 | /* Child node present, descend into it. */ | ||
967 | old_vcn = vcn; | ||
968 | vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8); | ||
969 | if (vcn >= 0) { | ||
970 | /* If vcn is in the same page cache page as old_vcn we | ||
971 | * recycle the mapped page. */ | ||
972 | if (old_vcn << vol->cluster_size_bits >> | ||
973 | PAGE_CACHE_SHIFT == vcn << | ||
974 | vol->cluster_size_bits >> | ||
975 | PAGE_CACHE_SHIFT) | ||
976 | goto fast_descend_into_child_node; | ||
977 | unlock_page(page); | ||
978 | ntfs_unmap_page(page); | ||
979 | goto descend_into_child_node; | ||
980 | } | ||
981 | ntfs_error(sb, "Negative child node vcn in directory inode " | ||
982 | "0x%lx.", dir_ni->mft_no); | ||
983 | goto unm_err_out; | ||
984 | } | ||
985 | /* No child node, return -ENOENT. */ | ||
986 | ntfs_debug("Entry not found."); | ||
987 | err = -ENOENT; | ||
988 | unm_err_out: | ||
989 | unlock_page(page); | ||
990 | ntfs_unmap_page(page); | ||
991 | err_out: | ||
992 | if (!err) | ||
993 | err = -EIO; | ||
994 | if (ctx) | ||
995 | ntfs_attr_put_search_ctx(ctx); | ||
996 | if (m) | ||
997 | unmap_mft_record(dir_ni); | ||
998 | return ERR_MREF(err); | ||
999 | dir_err_out: | ||
1000 | ntfs_error(sb, "Corrupt directory. Aborting lookup."); | ||
1001 | goto err_out; | ||
1002 | } | ||
1003 | |||
1004 | #endif | ||
1005 | |||
1006 | /** | ||
1007 | * ntfs_filldir - ntfs specific filldir method | ||
1008 | * @vol: current ntfs volume | ||
1009 | * @fpos: position in the directory | ||
1010 | * @ndir: ntfs inode of current directory | ||
1011 | * @ia_page: page in which the index allocation buffer @ie is in resides | ||
1012 | * @ie: current index entry | ||
1013 | * @name: buffer to use for the converted name | ||
1014 | * @dirent: vfs filldir callback context | ||
1015 | * @filldir: vfs filldir callback | ||
1016 | * | ||
1017 | * Convert the Unicode @name to the loaded NLS and pass it to the @filldir | ||
1018 | * callback. | ||
1019 | * | ||
1020 | * If @ia_page is not NULL it is the locked page containing the index | ||
1021 | * allocation block containing the index entry @ie. | ||
1022 | * | ||
1023 | * Note, we drop (and then reacquire) the page lock on @ia_page across the | ||
1024 | * @filldir() call otherwise we would deadlock with NFSd when it calls ->lookup | ||
1025 | * since ntfs_lookup() will lock the same page. As an optimization, we do not | ||
1026 | * retake the lock if we are returning a non-zero value as ntfs_readdir() | ||
1027 | * would need to drop the lock immediately anyway. | ||
1028 | */ | ||
1029 | static inline int ntfs_filldir(ntfs_volume *vol, loff_t fpos, | ||
1030 | ntfs_inode *ndir, struct page *ia_page, INDEX_ENTRY *ie, | ||
1031 | u8 *name, void *dirent, filldir_t filldir) | ||
1032 | { | ||
1033 | unsigned long mref; | ||
1034 | int name_len, rc; | ||
1035 | unsigned dt_type; | ||
1036 | FILE_NAME_TYPE_FLAGS name_type; | ||
1037 | |||
1038 | name_type = ie->key.file_name.file_name_type; | ||
1039 | if (name_type == FILE_NAME_DOS) { | ||
1040 | ntfs_debug("Skipping DOS name space entry."); | ||
1041 | return 0; | ||
1042 | } | ||
1043 | if (MREF_LE(ie->data.dir.indexed_file) == FILE_root) { | ||
1044 | ntfs_debug("Skipping root directory self reference entry."); | ||
1045 | return 0; | ||
1046 | } | ||
1047 | if (MREF_LE(ie->data.dir.indexed_file) < FILE_first_user && | ||
1048 | !NVolShowSystemFiles(vol)) { | ||
1049 | ntfs_debug("Skipping system file."); | ||
1050 | return 0; | ||
1051 | } | ||
1052 | name_len = ntfs_ucstonls(vol, (ntfschar*)&ie->key.file_name.file_name, | ||
1053 | ie->key.file_name.file_name_length, &name, | ||
1054 | NTFS_MAX_NAME_LEN * NLS_MAX_CHARSET_SIZE + 1); | ||
1055 | if (name_len <= 0) { | ||
1056 | ntfs_debug("Skipping unrepresentable file."); | ||
1057 | return 0; | ||
1058 | } | ||
1059 | if (ie->key.file_name.file_attributes & | ||
1060 | FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT) | ||
1061 | dt_type = DT_DIR; | ||
1062 | else | ||
1063 | dt_type = DT_REG; | ||
1064 | mref = MREF_LE(ie->data.dir.indexed_file); | ||
1065 | /* | ||
1066 | * Drop the page lock otherwise we deadlock with NFS when it calls | ||
1067 | * ->lookup since ntfs_lookup() will lock the same page. | ||
1068 | */ | ||
1069 | if (ia_page) | ||
1070 | unlock_page(ia_page); | ||
1071 | ntfs_debug("Calling filldir for %s with len %i, fpos 0x%llx, inode " | ||
1072 | "0x%lx, DT_%s.", name, name_len, fpos, mref, | ||
1073 | dt_type == DT_DIR ? "DIR" : "REG"); | ||
1074 | rc = filldir(dirent, name, name_len, fpos, mref, dt_type); | ||
1075 | /* Relock the page but not if we are aborting ->readdir. */ | ||
1076 | if (!rc && ia_page) | ||
1077 | lock_page(ia_page); | ||
1078 | return rc; | ||
1079 | } | ||
1080 | |||
1081 | /* | ||
1082 | * We use the same basic approach as the old NTFS driver, i.e. we parse the | ||
1083 | * index root entries and then the index allocation entries that are marked | ||
1084 | * as in use in the index bitmap. | ||
1085 | * | ||
1086 | * While this will return the names in random order this doesn't matter for | ||
1087 | * ->readdir but OTOH results in a faster ->readdir. | ||
1088 | * | ||
1089 | * VFS calls ->readdir without BKL but with i_sem held. This protects the VFS | ||
1090 | * parts (e.g. ->f_pos and ->i_size, and it also protects against directory | ||
1091 | * modifications). | ||
1092 | * | ||
1093 | * Locking: - Caller must hold i_sem on the directory. | ||
1094 | * - Each page cache page in the index allocation mapping must be | ||
1095 | * locked whilst being accessed otherwise we may find a corrupt | ||
1096 | * page due to it being under ->writepage at the moment which | ||
1097 | * applies the mst protection fixups before writing out and then | ||
1098 | * removes them again after the write is complete after which it | ||
1099 | * unlocks the page. | ||
1100 | */ | ||
1101 | static int ntfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | ||
1102 | { | ||
1103 | s64 ia_pos, ia_start, prev_ia_pos, bmp_pos; | ||
1104 | loff_t fpos; | ||
1105 | struct inode *bmp_vi, *vdir = filp->f_dentry->d_inode; | ||
1106 | struct super_block *sb = vdir->i_sb; | ||
1107 | ntfs_inode *ndir = NTFS_I(vdir); | ||
1108 | ntfs_volume *vol = NTFS_SB(sb); | ||
1109 | MFT_RECORD *m; | ||
1110 | INDEX_ROOT *ir = NULL; | ||
1111 | INDEX_ENTRY *ie; | ||
1112 | INDEX_ALLOCATION *ia; | ||
1113 | u8 *name = NULL; | ||
1114 | int rc, err, ir_pos, cur_bmp_pos; | ||
1115 | struct address_space *ia_mapping, *bmp_mapping; | ||
1116 | struct page *bmp_page = NULL, *ia_page = NULL; | ||
1117 | u8 *kaddr, *bmp, *index_end; | ||
1118 | ntfs_attr_search_ctx *ctx; | ||
1119 | |||
1120 | fpos = filp->f_pos; | ||
1121 | ntfs_debug("Entering for inode 0x%lx, fpos 0x%llx.", | ||
1122 | vdir->i_ino, fpos); | ||
1123 | rc = err = 0; | ||
1124 | /* Are we at end of dir yet? */ | ||
1125 | if (fpos >= vdir->i_size + vol->mft_record_size) | ||
1126 | goto done; | ||
1127 | /* Emulate . and .. for all directories. */ | ||
1128 | if (!fpos) { | ||
1129 | ntfs_debug("Calling filldir for . with len 1, fpos 0x0, " | ||
1130 | "inode 0x%lx, DT_DIR.", vdir->i_ino); | ||
1131 | rc = filldir(dirent, ".", 1, fpos, vdir->i_ino, DT_DIR); | ||
1132 | if (rc) | ||
1133 | goto done; | ||
1134 | fpos++; | ||
1135 | } | ||
1136 | if (fpos == 1) { | ||
1137 | ntfs_debug("Calling filldir for .. with len 2, fpos 0x1, " | ||
1138 | "inode 0x%lx, DT_DIR.", | ||
1139 | parent_ino(filp->f_dentry)); | ||
1140 | rc = filldir(dirent, "..", 2, fpos, | ||
1141 | parent_ino(filp->f_dentry), DT_DIR); | ||
1142 | if (rc) | ||
1143 | goto done; | ||
1144 | fpos++; | ||
1145 | } | ||
1146 | m = NULL; | ||
1147 | ctx = NULL; | ||
1148 | /* | ||
1149 | * Allocate a buffer to store the current name being processed | ||
1150 | * converted to format determined by current NLS. | ||
1151 | */ | ||
1152 | name = (u8*)kmalloc(NTFS_MAX_NAME_LEN * NLS_MAX_CHARSET_SIZE + 1, | ||
1153 | GFP_NOFS); | ||
1154 | if (unlikely(!name)) { | ||
1155 | err = -ENOMEM; | ||
1156 | goto err_out; | ||
1157 | } | ||
1158 | /* Are we jumping straight into the index allocation attribute? */ | ||
1159 | if (fpos >= vol->mft_record_size) | ||
1160 | goto skip_index_root; | ||
1161 | /* Get hold of the mft record for the directory. */ | ||
1162 | m = map_mft_record(ndir); | ||
1163 | if (IS_ERR(m)) { | ||
1164 | err = PTR_ERR(m); | ||
1165 | m = NULL; | ||
1166 | goto err_out; | ||
1167 | } | ||
1168 | ctx = ntfs_attr_get_search_ctx(ndir, m); | ||
1169 | if (unlikely(!ctx)) { | ||
1170 | err = -ENOMEM; | ||
1171 | goto err_out; | ||
1172 | } | ||
1173 | /* Get the offset into the index root attribute. */ | ||
1174 | ir_pos = (s64)fpos; | ||
1175 | /* Find the index root attribute in the mft record. */ | ||
1176 | err = ntfs_attr_lookup(AT_INDEX_ROOT, I30, 4, CASE_SENSITIVE, 0, NULL, | ||
1177 | 0, ctx); | ||
1178 | if (unlikely(err)) { | ||
1179 | ntfs_error(sb, "Index root attribute missing in directory " | ||
1180 | "inode 0x%lx.", vdir->i_ino); | ||
1181 | goto err_out; | ||
1182 | } | ||
1183 | /* | ||
1184 | * Copy the index root attribute value to a buffer so that we can put | ||
1185 | * the search context and unmap the mft record before calling the | ||
1186 | * filldir() callback. We need to do this because of NFSd which calls | ||
1187 | * ->lookup() from its filldir callback() and this causes NTFS to | ||
1188 | * deadlock as ntfs_lookup() maps the mft record of the directory and | ||
1189 | * we have got it mapped here already. The only solution is for us to | ||
1190 | * unmap the mft record here so that a call to ntfs_lookup() is able to | ||
1191 | * map the mft record without deadlocking. | ||
1192 | */ | ||
1193 | rc = le32_to_cpu(ctx->attr->data.resident.value_length); | ||
1194 | ir = (INDEX_ROOT*)kmalloc(rc, GFP_NOFS); | ||
1195 | if (unlikely(!ir)) { | ||
1196 | err = -ENOMEM; | ||
1197 | goto err_out; | ||
1198 | } | ||
1199 | /* Copy the index root value (it has been verified in read_inode). */ | ||
1200 | memcpy(ir, (u8*)ctx->attr + | ||
1201 | le16_to_cpu(ctx->attr->data.resident.value_offset), rc); | ||
1202 | ntfs_attr_put_search_ctx(ctx); | ||
1203 | unmap_mft_record(ndir); | ||
1204 | ctx = NULL; | ||
1205 | m = NULL; | ||
1206 | index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length); | ||
1207 | /* The first index entry. */ | ||
1208 | ie = (INDEX_ENTRY*)((u8*)&ir->index + | ||
1209 | le32_to_cpu(ir->index.entries_offset)); | ||
1210 | /* | ||
1211 | * Loop until we exceed valid memory (corruption case) or until we | ||
1212 | * reach the last entry or until filldir tells us it has had enough | ||
1213 | * or signals an error (both covered by the rc test). | ||
1214 | */ | ||
1215 | for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { | ||
1216 | ntfs_debug("In index root, offset 0x%zx.", (u8*)ie - (u8*)ir); | ||
1217 | /* Bounds checks. */ | ||
1218 | if (unlikely((u8*)ie < (u8*)ir || (u8*)ie + | ||
1219 | sizeof(INDEX_ENTRY_HEADER) > index_end || | ||
1220 | (u8*)ie + le16_to_cpu(ie->key_length) > | ||
1221 | index_end)) | ||
1222 | goto err_out; | ||
1223 | /* The last entry cannot contain a name. */ | ||
1224 | if (ie->flags & INDEX_ENTRY_END) | ||
1225 | break; | ||
1226 | /* Skip index root entry if continuing previous readdir. */ | ||
1227 | if (ir_pos > (u8*)ie - (u8*)ir) | ||
1228 | continue; | ||
1229 | /* Advance the position even if going to skip the entry. */ | ||
1230 | fpos = (u8*)ie - (u8*)ir; | ||
1231 | /* Submit the name to the filldir callback. */ | ||
1232 | rc = ntfs_filldir(vol, fpos, ndir, NULL, ie, name, dirent, | ||
1233 | filldir); | ||
1234 | if (rc) { | ||
1235 | kfree(ir); | ||
1236 | goto abort; | ||
1237 | } | ||
1238 | } | ||
1239 | /* We are done with the index root and can free the buffer. */ | ||
1240 | kfree(ir); | ||
1241 | ir = NULL; | ||
1242 | /* If there is no index allocation attribute we are finished. */ | ||
1243 | if (!NInoIndexAllocPresent(ndir)) | ||
1244 | goto EOD; | ||
1245 | /* Advance fpos to the beginning of the index allocation. */ | ||
1246 | fpos = vol->mft_record_size; | ||
1247 | skip_index_root: | ||
1248 | kaddr = NULL; | ||
1249 | prev_ia_pos = -1LL; | ||
1250 | /* Get the offset into the index allocation attribute. */ | ||
1251 | ia_pos = (s64)fpos - vol->mft_record_size; | ||
1252 | ia_mapping = vdir->i_mapping; | ||
1253 | bmp_vi = ndir->itype.index.bmp_ino; | ||
1254 | if (unlikely(!bmp_vi)) { | ||
1255 | ntfs_debug("Inode 0x%lx, regetting index bitmap.", vdir->i_ino); | ||
1256 | bmp_vi = ntfs_attr_iget(vdir, AT_BITMAP, I30, 4); | ||
1257 | if (IS_ERR(bmp_vi)) { | ||
1258 | ntfs_error(sb, "Failed to get bitmap attribute."); | ||
1259 | err = PTR_ERR(bmp_vi); | ||
1260 | goto err_out; | ||
1261 | } | ||
1262 | ndir->itype.index.bmp_ino = bmp_vi; | ||
1263 | } | ||
1264 | bmp_mapping = bmp_vi->i_mapping; | ||
1265 | /* Get the starting bitmap bit position and sanity check it. */ | ||
1266 | bmp_pos = ia_pos >> ndir->itype.index.block_size_bits; | ||
1267 | if (unlikely(bmp_pos >> 3 >= bmp_vi->i_size)) { | ||
1268 | ntfs_error(sb, "Current index allocation position exceeds " | ||
1269 | "index bitmap size."); | ||
1270 | goto err_out; | ||
1271 | } | ||
1272 | /* Get the starting bit position in the current bitmap page. */ | ||
1273 | cur_bmp_pos = bmp_pos & ((PAGE_CACHE_SIZE * 8) - 1); | ||
1274 | bmp_pos &= ~(u64)((PAGE_CACHE_SIZE * 8) - 1); | ||
1275 | get_next_bmp_page: | ||
1276 | ntfs_debug("Reading bitmap with page index 0x%llx, bit ofs 0x%llx", | ||
1277 | (unsigned long long)bmp_pos >> (3 + PAGE_CACHE_SHIFT), | ||
1278 | (unsigned long long)bmp_pos & | ||
1279 | (unsigned long long)((PAGE_CACHE_SIZE * 8) - 1)); | ||
1280 | bmp_page = ntfs_map_page(bmp_mapping, | ||
1281 | bmp_pos >> (3 + PAGE_CACHE_SHIFT)); | ||
1282 | if (IS_ERR(bmp_page)) { | ||
1283 | ntfs_error(sb, "Reading index bitmap failed."); | ||
1284 | err = PTR_ERR(bmp_page); | ||
1285 | bmp_page = NULL; | ||
1286 | goto err_out; | ||
1287 | } | ||
1288 | bmp = (u8*)page_address(bmp_page); | ||
1289 | /* Find next index block in use. */ | ||
1290 | while (!(bmp[cur_bmp_pos >> 3] & (1 << (cur_bmp_pos & 7)))) { | ||
1291 | find_next_index_buffer: | ||
1292 | cur_bmp_pos++; | ||
1293 | /* | ||
1294 | * If we have reached the end of the bitmap page, get the next | ||
1295 | * page, and put away the old one. | ||
1296 | */ | ||
1297 | if (unlikely((cur_bmp_pos >> 3) >= PAGE_CACHE_SIZE)) { | ||
1298 | ntfs_unmap_page(bmp_page); | ||
1299 | bmp_pos += PAGE_CACHE_SIZE * 8; | ||
1300 | cur_bmp_pos = 0; | ||
1301 | goto get_next_bmp_page; | ||
1302 | } | ||
1303 | /* If we have reached the end of the bitmap, we are done. */ | ||
1304 | if (unlikely(((bmp_pos + cur_bmp_pos) >> 3) >= vdir->i_size)) | ||
1305 | goto unm_EOD; | ||
1306 | ia_pos = (bmp_pos + cur_bmp_pos) << | ||
1307 | ndir->itype.index.block_size_bits; | ||
1308 | } | ||
1309 | ntfs_debug("Handling index buffer 0x%llx.", | ||
1310 | (unsigned long long)bmp_pos + cur_bmp_pos); | ||
1311 | /* If the current index buffer is in the same page we reuse the page. */ | ||
1312 | if ((prev_ia_pos & PAGE_CACHE_MASK) != (ia_pos & PAGE_CACHE_MASK)) { | ||
1313 | prev_ia_pos = ia_pos; | ||
1314 | if (likely(ia_page != NULL)) { | ||
1315 | unlock_page(ia_page); | ||
1316 | ntfs_unmap_page(ia_page); | ||
1317 | } | ||
1318 | /* | ||
1319 | * Map the page cache page containing the current ia_pos, | ||
1320 | * reading it from disk if necessary. | ||
1321 | */ | ||
1322 | ia_page = ntfs_map_page(ia_mapping, ia_pos >> PAGE_CACHE_SHIFT); | ||
1323 | if (IS_ERR(ia_page)) { | ||
1324 | ntfs_error(sb, "Reading index allocation data failed."); | ||
1325 | err = PTR_ERR(ia_page); | ||
1326 | ia_page = NULL; | ||
1327 | goto err_out; | ||
1328 | } | ||
1329 | lock_page(ia_page); | ||
1330 | kaddr = (u8*)page_address(ia_page); | ||
1331 | } | ||
1332 | /* Get the current index buffer. */ | ||
1333 | ia = (INDEX_ALLOCATION*)(kaddr + (ia_pos & ~PAGE_CACHE_MASK & | ||
1334 | ~(s64)(ndir->itype.index.block_size - 1))); | ||
1335 | /* Bounds checks. */ | ||
1336 | if (unlikely((u8*)ia < kaddr || (u8*)ia > kaddr + PAGE_CACHE_SIZE)) { | ||
1337 | ntfs_error(sb, "Out of bounds check failed. Corrupt directory " | ||
1338 | "inode 0x%lx or driver bug.", vdir->i_ino); | ||
1339 | goto err_out; | ||
1340 | } | ||
1341 | /* Catch multi sector transfer fixup errors. */ | ||
1342 | if (unlikely(!ntfs_is_indx_record(ia->magic))) { | ||
1343 | ntfs_error(sb, "Directory index record with vcn 0x%llx is " | ||
1344 | "corrupt. Corrupt inode 0x%lx. Run chkdsk.", | ||
1345 | (unsigned long long)ia_pos >> | ||
1346 | ndir->itype.index.vcn_size_bits, vdir->i_ino); | ||
1347 | goto err_out; | ||
1348 | } | ||
1349 | if (unlikely(sle64_to_cpu(ia->index_block_vcn) != (ia_pos & | ||
1350 | ~(s64)(ndir->itype.index.block_size - 1)) >> | ||
1351 | ndir->itype.index.vcn_size_bits)) { | ||
1352 | ntfs_error(sb, "Actual VCN (0x%llx) of index buffer is " | ||
1353 | "different from expected VCN (0x%llx). " | ||
1354 | "Directory inode 0x%lx is corrupt or driver " | ||
1355 | "bug. ", (unsigned long long) | ||
1356 | sle64_to_cpu(ia->index_block_vcn), | ||
1357 | (unsigned long long)ia_pos >> | ||
1358 | ndir->itype.index.vcn_size_bits, vdir->i_ino); | ||
1359 | goto err_out; | ||
1360 | } | ||
1361 | if (unlikely(le32_to_cpu(ia->index.allocated_size) + 0x18 != | ||
1362 | ndir->itype.index.block_size)) { | ||
1363 | ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode " | ||
1364 | "0x%lx has a size (%u) differing from the " | ||
1365 | "directory specified size (%u). Directory " | ||
1366 | "inode is corrupt or driver bug.", | ||
1367 | (unsigned long long)ia_pos >> | ||
1368 | ndir->itype.index.vcn_size_bits, vdir->i_ino, | ||
1369 | le32_to_cpu(ia->index.allocated_size) + 0x18, | ||
1370 | ndir->itype.index.block_size); | ||
1371 | goto err_out; | ||
1372 | } | ||
1373 | index_end = (u8*)ia + ndir->itype.index.block_size; | ||
1374 | if (unlikely(index_end > kaddr + PAGE_CACHE_SIZE)) { | ||
1375 | ntfs_error(sb, "Index buffer (VCN 0x%llx) of directory inode " | ||
1376 | "0x%lx crosses page boundary. Impossible! " | ||
1377 | "Cannot access! This is probably a bug in the " | ||
1378 | "driver.", (unsigned long long)ia_pos >> | ||
1379 | ndir->itype.index.vcn_size_bits, vdir->i_ino); | ||
1380 | goto err_out; | ||
1381 | } | ||
1382 | ia_start = ia_pos & ~(s64)(ndir->itype.index.block_size - 1); | ||
1383 | index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length); | ||
1384 | if (unlikely(index_end > (u8*)ia + ndir->itype.index.block_size)) { | ||
1385 | ntfs_error(sb, "Size of index buffer (VCN 0x%llx) of directory " | ||
1386 | "inode 0x%lx exceeds maximum size.", | ||
1387 | (unsigned long long)ia_pos >> | ||
1388 | ndir->itype.index.vcn_size_bits, vdir->i_ino); | ||
1389 | goto err_out; | ||
1390 | } | ||
1391 | /* The first index entry in this index buffer. */ | ||
1392 | ie = (INDEX_ENTRY*)((u8*)&ia->index + | ||
1393 | le32_to_cpu(ia->index.entries_offset)); | ||
1394 | /* | ||
1395 | * Loop until we exceed valid memory (corruption case) or until we | ||
1396 | * reach the last entry or until filldir tells us it has had enough | ||
1397 | * or signals an error (both covered by the rc test). | ||
1398 | */ | ||
1399 | for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { | ||
1400 | ntfs_debug("In index allocation, offset 0x%llx.", | ||
1401 | (unsigned long long)ia_start + | ||
1402 | (unsigned long long)((u8*)ie - (u8*)ia)); | ||
1403 | /* Bounds checks. */ | ||
1404 | if (unlikely((u8*)ie < (u8*)ia || (u8*)ie + | ||
1405 | sizeof(INDEX_ENTRY_HEADER) > index_end || | ||
1406 | (u8*)ie + le16_to_cpu(ie->key_length) > | ||
1407 | index_end)) | ||
1408 | goto err_out; | ||
1409 | /* The last entry cannot contain a name. */ | ||
1410 | if (ie->flags & INDEX_ENTRY_END) | ||
1411 | break; | ||
1412 | /* Skip index block entry if continuing previous readdir. */ | ||
1413 | if (ia_pos - ia_start > (u8*)ie - (u8*)ia) | ||
1414 | continue; | ||
1415 | /* Advance the position even if going to skip the entry. */ | ||
1416 | fpos = (u8*)ie - (u8*)ia + | ||
1417 | (sle64_to_cpu(ia->index_block_vcn) << | ||
1418 | ndir->itype.index.vcn_size_bits) + | ||
1419 | vol->mft_record_size; | ||
1420 | /* | ||
1421 | * Submit the name to the @filldir callback. Note, | ||
1422 | * ntfs_filldir() drops the lock on @ia_page but it retakes it | ||
1423 | * before returning, unless a non-zero value is returned in | ||
1424 | * which case the page is left unlocked. | ||
1425 | */ | ||
1426 | rc = ntfs_filldir(vol, fpos, ndir, ia_page, ie, name, dirent, | ||
1427 | filldir); | ||
1428 | if (rc) { | ||
1429 | /* @ia_page is already unlocked in this case. */ | ||
1430 | ntfs_unmap_page(ia_page); | ||
1431 | ntfs_unmap_page(bmp_page); | ||
1432 | goto abort; | ||
1433 | } | ||
1434 | } | ||
1435 | goto find_next_index_buffer; | ||
1436 | unm_EOD: | ||
1437 | if (ia_page) { | ||
1438 | unlock_page(ia_page); | ||
1439 | ntfs_unmap_page(ia_page); | ||
1440 | } | ||
1441 | ntfs_unmap_page(bmp_page); | ||
1442 | EOD: | ||
1443 | /* We are finished, set fpos to EOD. */ | ||
1444 | fpos = vdir->i_size + vol->mft_record_size; | ||
1445 | abort: | ||
1446 | kfree(name); | ||
1447 | done: | ||
1448 | #ifdef DEBUG | ||
1449 | if (!rc) | ||
1450 | ntfs_debug("EOD, fpos 0x%llx, returning 0.", fpos); | ||
1451 | else | ||
1452 | ntfs_debug("filldir returned %i, fpos 0x%llx, returning 0.", | ||
1453 | rc, fpos); | ||
1454 | #endif | ||
1455 | filp->f_pos = fpos; | ||
1456 | return 0; | ||
1457 | err_out: | ||
1458 | if (bmp_page) | ||
1459 | ntfs_unmap_page(bmp_page); | ||
1460 | if (ia_page) { | ||
1461 | unlock_page(ia_page); | ||
1462 | ntfs_unmap_page(ia_page); | ||
1463 | } | ||
1464 | if (ir) | ||
1465 | kfree(ir); | ||
1466 | if (name) | ||
1467 | kfree(name); | ||
1468 | if (ctx) | ||
1469 | ntfs_attr_put_search_ctx(ctx); | ||
1470 | if (m) | ||
1471 | unmap_mft_record(ndir); | ||
1472 | if (!err) | ||
1473 | err = -EIO; | ||
1474 | ntfs_debug("Failed. Returning error code %i.", -err); | ||
1475 | filp->f_pos = fpos; | ||
1476 | return err; | ||
1477 | } | ||
1478 | |||
1479 | /** | ||
1480 | * ntfs_dir_open - called when an inode is about to be opened | ||
1481 | * @vi: inode to be opened | ||
1482 | * @filp: file structure describing the inode | ||
1483 | * | ||
1484 | * Limit directory size to the page cache limit on architectures where unsigned | ||
1485 | * long is 32-bits. This is the most we can do for now without overflowing the | ||
1486 | * page cache page index. Doing it this way means we don't run into problems | ||
1487 | * because of existing too large directories. It would be better to allow the | ||
1488 | * user to read the accessible part of the directory but I doubt very much | ||
1489 | * anyone is going to hit this check on a 32-bit architecture, so there is no | ||
1490 | * point in adding the extra complexity required to support this. | ||
1491 | * | ||
1492 | * On 64-bit architectures, the check is hopefully optimized away by the | ||
1493 | * compiler. | ||
1494 | */ | ||
1495 | static int ntfs_dir_open(struct inode *vi, struct file *filp) | ||
1496 | { | ||
1497 | if (sizeof(unsigned long) < 8) { | ||
1498 | if (vi->i_size > MAX_LFS_FILESIZE) | ||
1499 | return -EFBIG; | ||
1500 | } | ||
1501 | return 0; | ||
1502 | } | ||
1503 | |||
1504 | #ifdef NTFS_RW | ||
1505 | |||
1506 | /** | ||
1507 | * ntfs_dir_fsync - sync a directory to disk | ||
1508 | * @filp: directory to be synced | ||
1509 | * @dentry: dentry describing the directory to sync | ||
1510 | * @datasync: if non-zero only flush user data and not metadata | ||
1511 | * | ||
1512 | * Data integrity sync of a directory to disk. Used for fsync, fdatasync, and | ||
1513 | * msync system calls. This function is based on file.c::ntfs_file_fsync(). | ||
1514 | * | ||
1515 | * Write the mft record and all associated extent mft records as well as the | ||
1516 | * $INDEX_ALLOCATION and $BITMAP attributes and then sync the block device. | ||
1517 | * | ||
1518 | * If @datasync is true, we do not wait on the inode(s) to be written out | ||
1519 | * but we always wait on the page cache pages to be written out. | ||
1520 | * | ||
1521 | * Note: In the past @filp could be NULL so we ignore it as we don't need it | ||
1522 | * anyway. | ||
1523 | * | ||
1524 | * Locking: Caller must hold i_sem on the inode. | ||
1525 | * | ||
1526 | * TODO: We should probably also write all attribute/index inodes associated | ||
1527 | * with this inode but since we have no simple way of getting to them we ignore | ||
1528 | * this problem for now. We do write the $BITMAP attribute if it is present | ||
1529 | * which is the important one for a directory so things are not too bad. | ||
1530 | */ | ||
1531 | static int ntfs_dir_fsync(struct file *filp, struct dentry *dentry, | ||
1532 | int datasync) | ||
1533 | { | ||
1534 | struct inode *vi = dentry->d_inode; | ||
1535 | ntfs_inode *ni = NTFS_I(vi); | ||
1536 | int err, ret; | ||
1537 | |||
1538 | ntfs_debug("Entering for inode 0x%lx.", vi->i_ino); | ||
1539 | BUG_ON(!S_ISDIR(vi->i_mode)); | ||
1540 | if (NInoIndexAllocPresent(ni) && ni->itype.index.bmp_ino) | ||
1541 | write_inode_now(ni->itype.index.bmp_ino, !datasync); | ||
1542 | ret = ntfs_write_inode(vi, 1); | ||
1543 | write_inode_now(vi, !datasync); | ||
1544 | err = sync_blockdev(vi->i_sb->s_bdev); | ||
1545 | if (unlikely(err && !ret)) | ||
1546 | ret = err; | ||
1547 | if (likely(!ret)) | ||
1548 | ntfs_debug("Done."); | ||
1549 | else | ||
1550 | ntfs_warning(vi->i_sb, "Failed to f%ssync inode 0x%lx. Error " | ||
1551 | "%u.", datasync ? "data" : "", vi->i_ino, -ret); | ||
1552 | return ret; | ||
1553 | } | ||
1554 | |||
1555 | #endif /* NTFS_RW */ | ||
1556 | |||
1557 | struct file_operations ntfs_dir_ops = { | ||
1558 | .llseek = generic_file_llseek, /* Seek inside directory. */ | ||
1559 | .read = generic_read_dir, /* Return -EISDIR. */ | ||
1560 | .readdir = ntfs_readdir, /* Read directory contents. */ | ||
1561 | #ifdef NTFS_RW | ||
1562 | .fsync = ntfs_dir_fsync, /* Sync a directory to disk. */ | ||
1563 | /*.aio_fsync = ,*/ /* Sync all outstanding async | ||
1564 | i/o operations on a kiocb. */ | ||
1565 | #endif /* NTFS_RW */ | ||
1566 | /*.ioctl = ,*/ /* Perform function on the | ||
1567 | mounted filesystem. */ | ||
1568 | .open = ntfs_dir_open, /* Open directory. */ | ||
1569 | }; | ||