1
2
3
4
5
6
7
8
9#include <linux/dcache.h>
10#include <linux/exportfs.h>
11#include <linux/security.h>
12#include <linux/slab.h>
13
14#include "attrib.h"
15#include "debug.h"
16#include "dir.h"
17#include "mft.h"
18#include "ntfs.h"
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent,
90 unsigned int flags)
91{
92 ntfs_volume *vol = NTFS_SB(dir_ino->i_sb);
93 struct inode *dent_inode;
94 ntfschar *uname;
95 ntfs_name *name = NULL;
96 MFT_REF mref;
97 unsigned long dent_ino;
98 int uname_len;
99
100 ntfs_debug("Looking up %pd in directory inode 0x%lx.",
101 dent, dir_ino->i_ino);
102
103 uname_len = ntfs_nlstoucs(vol, dent->d_name.name, dent->d_name.len,
104 &uname);
105 if (uname_len < 0) {
106 if (uname_len != -ENAMETOOLONG)
107 ntfs_error(vol->sb, "Failed to convert name to "
108 "Unicode.");
109 return ERR_PTR(uname_len);
110 }
111 mref = ntfs_lookup_inode_by_name(NTFS_I(dir_ino), uname, uname_len,
112 &name);
113 kmem_cache_free(ntfs_name_cache, uname);
114 if (!IS_ERR_MREF(mref)) {
115 dent_ino = MREF(mref);
116 ntfs_debug("Found inode 0x%lx. Calling ntfs_iget.", dent_ino);
117 dent_inode = ntfs_iget(vol->sb, dent_ino);
118 if (!IS_ERR(dent_inode)) {
119
120 if (is_bad_inode(dent_inode) || MSEQNO(mref) ==
121 NTFS_I(dent_inode)->seq_no ||
122 dent_ino == FILE_MFT) {
123
124 if (!name) {
125 ntfs_debug("Done. (Case 1.)");
126 return d_splice_alias(dent_inode, dent);
127 }
128
129
130
131
132 goto handle_name;
133 }
134 ntfs_error(vol->sb, "Found stale reference to inode "
135 "0x%lx (reference sequence number = "
136 "0x%x, inode sequence number = 0x%x), "
137 "returning -EIO. Run chkdsk.",
138 dent_ino, MSEQNO(mref),
139 NTFS_I(dent_inode)->seq_no);
140 iput(dent_inode);
141 dent_inode = ERR_PTR(-EIO);
142 } else
143 ntfs_error(vol->sb, "ntfs_iget(0x%lx) failed with "
144 "error code %li.", dent_ino,
145 PTR_ERR(dent_inode));
146 kfree(name);
147
148 return ERR_CAST(dent_inode);
149 }
150
151 if (MREF_ERR(mref) == -ENOENT) {
152 ntfs_debug("Entry was not found, adding negative dentry.");
153
154 d_add(dent, NULL);
155 ntfs_debug("Done.");
156 return NULL;
157 }
158 ntfs_error(vol->sb, "ntfs_lookup_ino_by_name() failed with error "
159 "code %i.", -MREF_ERR(mref));
160 return ERR_PTR(MREF_ERR(mref));
161
162handle_name:
163 {
164 MFT_RECORD *m;
165 ntfs_attr_search_ctx *ctx;
166 ntfs_inode *ni = NTFS_I(dent_inode);
167 int err;
168 struct qstr nls_name;
169
170 nls_name.name = NULL;
171 if (name->type != FILE_NAME_DOS) {
172 ntfs_debug("Case 2.");
173 nls_name.len = (unsigned)ntfs_ucstonls(vol,
174 (ntfschar*)&name->name, name->len,
175 (unsigned char**)&nls_name.name, 0);
176 kfree(name);
177 } else {
178 FILE_NAME_ATTR *fn;
179
180 ntfs_debug("Case 3.");
181 kfree(name);
182
183
184 ni = NTFS_I(dent_inode);
185 m = map_mft_record(ni);
186 if (IS_ERR(m)) {
187 err = PTR_ERR(m);
188 m = NULL;
189 ctx = NULL;
190 goto err_out;
191 }
192 ctx = ntfs_attr_get_search_ctx(ni, m);
193 if (unlikely(!ctx)) {
194 err = -ENOMEM;
195 goto err_out;
196 }
197 do {
198 ATTR_RECORD *a;
199 u32 val_len;
200
201 err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0,
202 NULL, 0, ctx);
203 if (unlikely(err)) {
204 ntfs_error(vol->sb, "Inode corrupt: No WIN32 "
205 "namespace counterpart to DOS "
206 "file name. Run chkdsk.");
207 if (err == -ENOENT)
208 err = -EIO;
209 goto err_out;
210 }
211
212 a = ctx->attr;
213 if (a->non_resident || a->flags)
214 goto eio_err_out;
215 val_len = le32_to_cpu(a->data.resident.value_length);
216 if (le16_to_cpu(a->data.resident.value_offset) +
217 val_len > le32_to_cpu(a->length))
218 goto eio_err_out;
219 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr + le16_to_cpu(
220 ctx->attr->data.resident.value_offset));
221 if ((u32)(fn->file_name_length * sizeof(ntfschar) +
222 sizeof(FILE_NAME_ATTR)) > val_len)
223 goto eio_err_out;
224 } while (fn->file_name_type != FILE_NAME_WIN32);
225
226
227 nls_name.len = (unsigned)ntfs_ucstonls(vol,
228 (ntfschar*)&fn->file_name, fn->file_name_length,
229 (unsigned char**)&nls_name.name, 0);
230
231 ntfs_attr_put_search_ctx(ctx);
232 unmap_mft_record(ni);
233 }
234 m = NULL;
235 ctx = NULL;
236
237
238 if ((signed)nls_name.len < 0) {
239 err = (signed)nls_name.len;
240 goto err_out;
241 }
242 nls_name.hash = full_name_hash(dent, nls_name.name, nls_name.len);
243
244 dent = d_add_ci(dent, dent_inode, &nls_name);
245 kfree(nls_name.name);
246 return dent;
247
248eio_err_out:
249 ntfs_error(vol->sb, "Illegal file name attribute. Run chkdsk.");
250 err = -EIO;
251err_out:
252 if (ctx)
253 ntfs_attr_put_search_ctx(ctx);
254 if (m)
255 unmap_mft_record(ni);
256 iput(dent_inode);
257 ntfs_error(vol->sb, "Failed, returning error code %i.", err);
258 return ERR_PTR(err);
259 }
260}
261
262
263
264
265const struct inode_operations ntfs_dir_inode_ops = {
266 .lookup = ntfs_lookup,
267};
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286static struct dentry *ntfs_get_parent(struct dentry *child_dent)
287{
288 struct inode *vi = d_inode(child_dent);
289 ntfs_inode *ni = NTFS_I(vi);
290 MFT_RECORD *mrec;
291 ntfs_attr_search_ctx *ctx;
292 ATTR_RECORD *attr;
293 FILE_NAME_ATTR *fn;
294 unsigned long parent_ino;
295 int err;
296
297 ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
298
299 mrec = map_mft_record(ni);
300 if (IS_ERR(mrec))
301 return ERR_CAST(mrec);
302
303 ctx = ntfs_attr_get_search_ctx(ni, mrec);
304 if (unlikely(!ctx)) {
305 unmap_mft_record(ni);
306 return ERR_PTR(-ENOMEM);
307 }
308try_next:
309 err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0, NULL,
310 0, ctx);
311 if (unlikely(err)) {
312 ntfs_attr_put_search_ctx(ctx);
313 unmap_mft_record(ni);
314 if (err == -ENOENT)
315 ntfs_error(vi->i_sb, "Inode 0x%lx does not have a "
316 "file name attribute. Run chkdsk.",
317 vi->i_ino);
318 return ERR_PTR(err);
319 }
320 attr = ctx->attr;
321 if (unlikely(attr->non_resident))
322 goto try_next;
323 fn = (FILE_NAME_ATTR *)((u8 *)attr +
324 le16_to_cpu(attr->data.resident.value_offset));
325 if (unlikely((u8 *)fn + le32_to_cpu(attr->data.resident.value_length) >
326 (u8*)attr + le32_to_cpu(attr->length)))
327 goto try_next;
328
329 parent_ino = MREF_LE(fn->parent_directory);
330
331 ntfs_attr_put_search_ctx(ctx);
332 unmap_mft_record(ni);
333
334 return d_obtain_alias(ntfs_iget(vi->i_sb, parent_ino));
335}
336
337static struct inode *ntfs_nfs_get_inode(struct super_block *sb,
338 u64 ino, u32 generation)
339{
340 struct inode *inode;
341
342 inode = ntfs_iget(sb, ino);
343 if (!IS_ERR(inode)) {
344 if (is_bad_inode(inode) || inode->i_generation != generation) {
345 iput(inode);
346 inode = ERR_PTR(-ESTALE);
347 }
348 }
349
350 return inode;
351}
352
353static struct dentry *ntfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
354 int fh_len, int fh_type)
355{
356 return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
357 ntfs_nfs_get_inode);
358}
359
360static struct dentry *ntfs_fh_to_parent(struct super_block *sb, struct fid *fid,
361 int fh_len, int fh_type)
362{
363 return generic_fh_to_parent(sb, fid, fh_len, fh_type,
364 ntfs_nfs_get_inode);
365}
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386const struct export_operations ntfs_export_ops = {
387 .get_parent = ntfs_get_parent,
388
389 .fh_to_dentry = ntfs_fh_to_dentry,
390 .fh_to_parent = ntfs_fh_to_parent,
391};
392