OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [ntfs/] [namei.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * namei.c - NTFS kernel directory inode operations. Part of the Linux-NTFS
3
 *           project.
4
 *
5
 * Copyright (c) 2001-2006 Anton Altaparmakov
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/dcache.h>
24
#include <linux/exportfs.h>
25
#include <linux/security.h>
26
 
27
#include "attrib.h"
28
#include "debug.h"
29
#include "dir.h"
30
#include "mft.h"
31
#include "ntfs.h"
32
 
33
/**
34
 * ntfs_lookup - find the inode represented by a dentry in a directory inode
35
 * @dir_ino:    directory inode in which to look for the inode
36
 * @dent:       dentry representing the inode to look for
37
 * @nd:         lookup nameidata
38
 *
39
 * In short, ntfs_lookup() looks for the inode represented by the dentry @dent
40
 * in the directory inode @dir_ino and if found attaches the inode to the
41
 * dentry @dent.
42
 *
43
 * In more detail, the dentry @dent specifies which inode to look for by
44
 * supplying the name of the inode in @dent->d_name.name. ntfs_lookup()
45
 * converts the name to Unicode and walks the contents of the directory inode
46
 * @dir_ino looking for the converted Unicode name. If the name is found in the
47
 * directory, the corresponding inode is loaded by calling ntfs_iget() on its
48
 * inode number and the inode is associated with the dentry @dent via a call to
49
 * d_splice_alias().
50
 *
51
 * If the name is not found in the directory, a NULL inode is inserted into the
52
 * dentry @dent via a call to d_add(). The dentry is then termed a negative
53
 * dentry.
54
 *
55
 * Only if an actual error occurs, do we return an error via ERR_PTR().
56
 *
57
 * In order to handle the case insensitivity issues of NTFS with regards to the
58
 * dcache and the dcache requiring only one dentry per directory, we deal with
59
 * dentry aliases that only differ in case in ->ntfs_lookup() while maintaining
60
 * a case sensitive dcache. This means that we get the full benefit of dcache
61
 * speed when the file/directory is looked up with the same case as returned by
62
 * ->ntfs_readdir() but that a lookup for any other case (or for the short file
63
 * name) will not find anything in dcache and will enter ->ntfs_lookup()
64
 * instead, where we search the directory for a fully matching file name
65
 * (including case) and if that is not found, we search for a file name that
66
 * matches with different case and if that has non-POSIX semantics we return
67
 * that. We actually do only one search (case sensitive) and keep tabs on
68
 * whether we have found a case insensitive match in the process.
69
 *
70
 * To simplify matters for us, we do not treat the short vs long filenames as
71
 * two hard links but instead if the lookup matches a short filename, we
72
 * return the dentry for the corresponding long filename instead.
73
 *
74
 * There are three cases we need to distinguish here:
75
 *
76
 * 1) @dent perfectly matches (i.e. including case) a directory entry with a
77
 *    file name in the WIN32 or POSIX namespaces. In this case
78
 *    ntfs_lookup_inode_by_name() will return with name set to NULL and we
79
 *    just d_splice_alias() @dent.
80
 * 2) @dent matches (not including case) a directory entry with a file name in
81
 *    the WIN32 namespace. In this case ntfs_lookup_inode_by_name() will return
82
 *    with name set to point to a kmalloc()ed ntfs_name structure containing
83
 *    the properly cased little endian Unicode name. We convert the name to the
84
 *    current NLS code page, search if a dentry with this name already exists
85
 *    and if so return that instead of @dent.  At this point things are
86
 *    complicated by the possibility of 'disconnected' dentries due to NFS
87
 *    which we deal with appropriately (see the code comments).  The VFS will
88
 *    then destroy the old @dent and use the one we returned.  If a dentry is
89
 *    not found, we allocate a new one, d_splice_alias() it, and return it as
90
 *    above.
91
 * 3) @dent matches either perfectly or not (i.e. we don't care about case) a
92
 *    directory entry with a file name in the DOS namespace. In this case
93
 *    ntfs_lookup_inode_by_name() will return with name set to point to a
94
 *    kmalloc()ed ntfs_name structure containing the mft reference (cpu endian)
95
 *    of the inode. We use the mft reference to read the inode and to find the
96
 *    file name in the WIN32 namespace corresponding to the matched short file
97
 *    name. We then convert the name to the current NLS code page, and proceed
98
 *    searching for a dentry with this name, etc, as in case 2), above.
99
 *
100
 * Locking: Caller must hold i_mutex on the directory.
101
 */
102
static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent,
103
                struct nameidata *nd)
104
{
105
        ntfs_volume *vol = NTFS_SB(dir_ino->i_sb);
106
        struct inode *dent_inode;
107
        ntfschar *uname;
108
        ntfs_name *name = NULL;
109
        MFT_REF mref;
110
        unsigned long dent_ino;
111
        int uname_len;
112
 
113
        ntfs_debug("Looking up %s in directory inode 0x%lx.",
114
                        dent->d_name.name, dir_ino->i_ino);
115
        /* Convert the name of the dentry to Unicode. */
116
        uname_len = ntfs_nlstoucs(vol, dent->d_name.name, dent->d_name.len,
117
                        &uname);
118
        if (uname_len < 0) {
119
                if (uname_len != -ENAMETOOLONG)
120
                        ntfs_error(vol->sb, "Failed to convert name to "
121
                                        "Unicode.");
122
                return ERR_PTR(uname_len);
123
        }
124
        mref = ntfs_lookup_inode_by_name(NTFS_I(dir_ino), uname, uname_len,
125
                        &name);
126
        kmem_cache_free(ntfs_name_cache, uname);
127
        if (!IS_ERR_MREF(mref)) {
128
                dent_ino = MREF(mref);
129
                ntfs_debug("Found inode 0x%lx. Calling ntfs_iget.", dent_ino);
130
                dent_inode = ntfs_iget(vol->sb, dent_ino);
131
                if (likely(!IS_ERR(dent_inode))) {
132
                        /* Consistency check. */
133
                        if (is_bad_inode(dent_inode) || MSEQNO(mref) ==
134
                                        NTFS_I(dent_inode)->seq_no ||
135
                                        dent_ino == FILE_MFT) {
136
                                /* Perfect WIN32/POSIX match. -- Case 1. */
137
                                if (!name) {
138
                                        ntfs_debug("Done.  (Case 1.)");
139
                                        return d_splice_alias(dent_inode, dent);
140
                                }
141
                                /*
142
                                 * We are too indented.  Handle imperfect
143
                                 * matches and short file names further below.
144
                                 */
145
                                goto handle_name;
146
                        }
147
                        ntfs_error(vol->sb, "Found stale reference to inode "
148
                                        "0x%lx (reference sequence number = "
149
                                        "0x%x, inode sequence number = 0x%x), "
150
                                        "returning -EIO. Run chkdsk.",
151
                                        dent_ino, MSEQNO(mref),
152
                                        NTFS_I(dent_inode)->seq_no);
153
                        iput(dent_inode);
154
                        dent_inode = ERR_PTR(-EIO);
155
                } else
156
                        ntfs_error(vol->sb, "ntfs_iget(0x%lx) failed with "
157
                                        "error code %li.", dent_ino,
158
                                        PTR_ERR(dent_inode));
159
                kfree(name);
160
                /* Return the error code. */
161
                return (struct dentry *)dent_inode;
162
        }
163
        /* It is guaranteed that @name is no longer allocated at this point. */
164
        if (MREF_ERR(mref) == -ENOENT) {
165
                ntfs_debug("Entry was not found, adding negative dentry.");
166
                /* The dcache will handle negative entries. */
167
                d_add(dent, NULL);
168
                ntfs_debug("Done.");
169
                return NULL;
170
        }
171
        ntfs_error(vol->sb, "ntfs_lookup_ino_by_name() failed with error "
172
                        "code %i.", -MREF_ERR(mref));
173
        return ERR_PTR(MREF_ERR(mref));
174
        // TODO: Consider moving this lot to a separate function! (AIA)
175
handle_name:
176
   {
177
        struct dentry *real_dent, *new_dent;
178
        MFT_RECORD *m;
179
        ntfs_attr_search_ctx *ctx;
180
        ntfs_inode *ni = NTFS_I(dent_inode);
181
        int err;
182
        struct qstr nls_name;
183
 
184
        nls_name.name = NULL;
185
        if (name->type != FILE_NAME_DOS) {                      /* Case 2. */
186
                ntfs_debug("Case 2.");
187
                nls_name.len = (unsigned)ntfs_ucstonls(vol,
188
                                (ntfschar*)&name->name, name->len,
189
                                (unsigned char**)&nls_name.name, 0);
190
                kfree(name);
191
        } else /* if (name->type == FILE_NAME_DOS) */ {         /* Case 3. */
192
                FILE_NAME_ATTR *fn;
193
 
194
                ntfs_debug("Case 3.");
195
                kfree(name);
196
 
197
                /* Find the WIN32 name corresponding to the matched DOS name. */
198
                ni = NTFS_I(dent_inode);
199
                m = map_mft_record(ni);
200
                if (IS_ERR(m)) {
201
                        err = PTR_ERR(m);
202
                        m = NULL;
203
                        ctx = NULL;
204
                        goto err_out;
205
                }
206
                ctx = ntfs_attr_get_search_ctx(ni, m);
207
                if (unlikely(!ctx)) {
208
                        err = -ENOMEM;
209
                        goto err_out;
210
                }
211
                do {
212
                        ATTR_RECORD *a;
213
                        u32 val_len;
214
 
215
                        err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0,
216
                                        NULL, 0, ctx);
217
                        if (unlikely(err)) {
218
                                ntfs_error(vol->sb, "Inode corrupt: No WIN32 "
219
                                                "namespace counterpart to DOS "
220
                                                "file name. Run chkdsk.");
221
                                if (err == -ENOENT)
222
                                        err = -EIO;
223
                                goto err_out;
224
                        }
225
                        /* Consistency checks. */
226
                        a = ctx->attr;
227
                        if (a->non_resident || a->flags)
228
                                goto eio_err_out;
229
                        val_len = le32_to_cpu(a->data.resident.value_length);
230
                        if (le16_to_cpu(a->data.resident.value_offset) +
231
                                        val_len > le32_to_cpu(a->length))
232
                                goto eio_err_out;
233
                        fn = (FILE_NAME_ATTR*)((u8*)ctx->attr + le16_to_cpu(
234
                                        ctx->attr->data.resident.value_offset));
235
                        if ((u32)(fn->file_name_length * sizeof(ntfschar) +
236
                                        sizeof(FILE_NAME_ATTR)) > val_len)
237
                                goto eio_err_out;
238
                } while (fn->file_name_type != FILE_NAME_WIN32);
239
 
240
                /* Convert the found WIN32 name to current NLS code page. */
241
                nls_name.len = (unsigned)ntfs_ucstonls(vol,
242
                                (ntfschar*)&fn->file_name, fn->file_name_length,
243
                                (unsigned char**)&nls_name.name, 0);
244
 
245
                ntfs_attr_put_search_ctx(ctx);
246
                unmap_mft_record(ni);
247
        }
248
        m = NULL;
249
        ctx = NULL;
250
 
251
        /* Check if a conversion error occurred. */
252
        if ((signed)nls_name.len < 0) {
253
                err = (signed)nls_name.len;
254
                goto err_out;
255
        }
256
        nls_name.hash = full_name_hash(nls_name.name, nls_name.len);
257
 
258
        /*
259
         * Note: No need for dent->d_lock lock as i_mutex is held on the
260
         * parent inode.
261
         */
262
 
263
        /* Does a dentry matching the nls_name exist already? */
264
        real_dent = d_lookup(dent->d_parent, &nls_name);
265
        /* If not, create it now. */
266
        if (!real_dent) {
267
                real_dent = d_alloc(dent->d_parent, &nls_name);
268
                kfree(nls_name.name);
269
                if (!real_dent) {
270
                        err = -ENOMEM;
271
                        goto err_out;
272
                }
273
                new_dent = d_splice_alias(dent_inode, real_dent);
274
                if (new_dent)
275
                        dput(real_dent);
276
                else
277
                        new_dent = real_dent;
278
                ntfs_debug("Done.  (Created new dentry.)");
279
                return new_dent;
280
        }
281
        kfree(nls_name.name);
282
        /* Matching dentry exists, check if it is negative. */
283
        if (real_dent->d_inode) {
284
                if (unlikely(real_dent->d_inode != dent_inode)) {
285
                        /* This can happen because bad inodes are unhashed. */
286
                        BUG_ON(!is_bad_inode(dent_inode));
287
                        BUG_ON(!is_bad_inode(real_dent->d_inode));
288
                }
289
                /*
290
                 * Already have the inode and the dentry attached, decrement
291
                 * the reference count to balance the ntfs_iget() we did
292
                 * earlier on.  We found the dentry using d_lookup() so it
293
                 * cannot be disconnected and thus we do not need to worry
294
                 * about any NFS/disconnectedness issues here.
295
                 */
296
                iput(dent_inode);
297
                ntfs_debug("Done.  (Already had inode and dentry.)");
298
                return real_dent;
299
        }
300
        /*
301
         * Negative dentry: instantiate it unless the inode is a directory and
302
         * has a 'disconnected' dentry (i.e. IS_ROOT and DCACHE_DISCONNECTED),
303
         * in which case d_move() that in place of the found dentry.
304
         */
305
        if (!S_ISDIR(dent_inode->i_mode)) {
306
                /* Not a directory; everything is easy. */
307
                d_instantiate(real_dent, dent_inode);
308
                ntfs_debug("Done.  (Already had negative file dentry.)");
309
                return real_dent;
310
        }
311
        spin_lock(&dcache_lock);
312
        if (list_empty(&dent_inode->i_dentry)) {
313
                /*
314
                 * Directory without a 'disconnected' dentry; we need to do
315
                 * d_instantiate() by hand because it takes dcache_lock which
316
                 * we already hold.
317
                 */
318
                list_add(&real_dent->d_alias, &dent_inode->i_dentry);
319
                real_dent->d_inode = dent_inode;
320
                spin_unlock(&dcache_lock);
321
                security_d_instantiate(real_dent, dent_inode);
322
                ntfs_debug("Done.  (Already had negative directory dentry.)");
323
                return real_dent;
324
        }
325
        /*
326
         * Directory with a 'disconnected' dentry; get a reference to the
327
         * 'disconnected' dentry.
328
         */
329
        new_dent = list_entry(dent_inode->i_dentry.next, struct dentry,
330
                        d_alias);
331
        dget_locked(new_dent);
332
        spin_unlock(&dcache_lock);
333
        /* Do security vodoo. */
334
        security_d_instantiate(real_dent, dent_inode);
335
        /* Move new_dent in place of real_dent. */
336
        d_move(new_dent, real_dent);
337
        /* Balance the ntfs_iget() we did above. */
338
        iput(dent_inode);
339
        /* Throw away real_dent. */
340
        dput(real_dent);
341
        /* Use new_dent as the actual dentry. */
342
        ntfs_debug("Done.  (Already had negative, disconnected directory "
343
                        "dentry.)");
344
        return new_dent;
345
 
346
eio_err_out:
347
        ntfs_error(vol->sb, "Illegal file name attribute. Run chkdsk.");
348
        err = -EIO;
349
err_out:
350
        if (ctx)
351
                ntfs_attr_put_search_ctx(ctx);
352
        if (m)
353
                unmap_mft_record(ni);
354
        iput(dent_inode);
355
        ntfs_error(vol->sb, "Failed, returning error code %i.", err);
356
        return ERR_PTR(err);
357
   }
358
}
359
 
360
/**
361
 * Inode operations for directories.
362
 */
363
const struct inode_operations ntfs_dir_inode_ops = {
364
        .lookup = ntfs_lookup,  /* VFS: Lookup directory. */
365
};
366
 
367
/**
368
 * ntfs_get_parent - find the dentry of the parent of a given directory dentry
369
 * @child_dent:         dentry of the directory whose parent directory to find
370
 *
371
 * Find the dentry for the parent directory of the directory specified by the
372
 * dentry @child_dent.  This function is called from
373
 * fs/exportfs/expfs.c::find_exported_dentry() which in turn is called from the
374
 * default ->decode_fh() which is export_decode_fh() in the same file.
375
 *
376
 * The code is based on the ext3 ->get_parent() implementation found in
377
 * fs/ext3/namei.c::ext3_get_parent().
378
 *
379
 * Note: ntfs_get_parent() is called with @child_dent->d_inode->i_mutex down.
380
 *
381
 * Return the dentry of the parent directory on success or the error code on
382
 * error (IS_ERR() is true).
383
 */
384
static struct dentry *ntfs_get_parent(struct dentry *child_dent)
385
{
386
        struct inode *vi = child_dent->d_inode;
387
        ntfs_inode *ni = NTFS_I(vi);
388
        MFT_RECORD *mrec;
389
        ntfs_attr_search_ctx *ctx;
390
        ATTR_RECORD *attr;
391
        FILE_NAME_ATTR *fn;
392
        struct inode *parent_vi;
393
        struct dentry *parent_dent;
394
        unsigned long parent_ino;
395
        int err;
396
 
397
        ntfs_debug("Entering for inode 0x%lx.", vi->i_ino);
398
        /* Get the mft record of the inode belonging to the child dentry. */
399
        mrec = map_mft_record(ni);
400
        if (IS_ERR(mrec))
401
                return (struct dentry *)mrec;
402
        /* Find the first file name attribute in the mft record. */
403
        ctx = ntfs_attr_get_search_ctx(ni, mrec);
404
        if (unlikely(!ctx)) {
405
                unmap_mft_record(ni);
406
                return ERR_PTR(-ENOMEM);
407
        }
408
try_next:
409
        err = ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0, NULL,
410
                        0, ctx);
411
        if (unlikely(err)) {
412
                ntfs_attr_put_search_ctx(ctx);
413
                unmap_mft_record(ni);
414
                if (err == -ENOENT)
415
                        ntfs_error(vi->i_sb, "Inode 0x%lx does not have a "
416
                                        "file name attribute.  Run chkdsk.",
417
                                        vi->i_ino);
418
                return ERR_PTR(err);
419
        }
420
        attr = ctx->attr;
421
        if (unlikely(attr->non_resident))
422
                goto try_next;
423
        fn = (FILE_NAME_ATTR *)((u8 *)attr +
424
                        le16_to_cpu(attr->data.resident.value_offset));
425
        if (unlikely((u8 *)fn + le32_to_cpu(attr->data.resident.value_length) >
426
                        (u8*)attr + le32_to_cpu(attr->length)))
427
                goto try_next;
428
        /* Get the inode number of the parent directory. */
429
        parent_ino = MREF_LE(fn->parent_directory);
430
        /* Release the search context and the mft record of the child. */
431
        ntfs_attr_put_search_ctx(ctx);
432
        unmap_mft_record(ni);
433
        /* Get the inode of the parent directory. */
434
        parent_vi = ntfs_iget(vi->i_sb, parent_ino);
435
        if (IS_ERR(parent_vi) || unlikely(is_bad_inode(parent_vi))) {
436
                if (!IS_ERR(parent_vi))
437
                        iput(parent_vi);
438
                ntfs_error(vi->i_sb, "Failed to get parent directory inode "
439
                                "0x%lx of child inode 0x%lx.", parent_ino,
440
                                vi->i_ino);
441
                return ERR_PTR(-EACCES);
442
        }
443
        /* Finally get a dentry for the parent directory and return it. */
444
        parent_dent = d_alloc_anon(parent_vi);
445
        if (unlikely(!parent_dent)) {
446
                iput(parent_vi);
447
                return ERR_PTR(-ENOMEM);
448
        }
449
        ntfs_debug("Done for inode 0x%lx.", vi->i_ino);
450
        return parent_dent;
451
}
452
 
453
static struct inode *ntfs_nfs_get_inode(struct super_block *sb,
454
                u64 ino, u32 generation)
455
{
456
        struct inode *inode;
457
 
458
        inode = ntfs_iget(sb, ino);
459
        if (!IS_ERR(inode)) {
460
                if (is_bad_inode(inode) || inode->i_generation != generation) {
461
                        iput(inode);
462
                        inode = ERR_PTR(-ESTALE);
463
                }
464
        }
465
 
466
        return inode;
467
}
468
 
469
static struct dentry *ntfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
470
                int fh_len, int fh_type)
471
{
472
        return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
473
                                    ntfs_nfs_get_inode);
474
}
475
 
476
static struct dentry *ntfs_fh_to_parent(struct super_block *sb, struct fid *fid,
477
                int fh_len, int fh_type)
478
{
479
        return generic_fh_to_parent(sb, fid, fh_len, fh_type,
480
                                    ntfs_nfs_get_inode);
481
}
482
 
483
/**
484
 * Export operations allowing NFS exporting of mounted NTFS partitions.
485
 *
486
 * We use the default ->encode_fh() for now.  Note that they
487
 * use 32 bits to store the inode number which is an unsigned long so on 64-bit
488
 * architectures is usually 64 bits so it would all fail horribly on huge
489
 * volumes.  I guess we need to define our own encode and decode fh functions
490
 * that store 64-bit inode numbers at some point but for now we will ignore the
491
 * problem...
492
 *
493
 * We also use the default ->get_name() helper (used by ->decode_fh() via
494
 * fs/exportfs/expfs.c::find_exported_dentry()) as that is completely fs
495
 * independent.
496
 *
497
 * The default ->get_parent() just returns -EACCES so we have to provide our
498
 * own and the default ->get_dentry() is incompatible with NTFS due to not
499
 * allowing the inode number 0 which is used in NTFS for the system file $MFT
500
 * and due to using iget() whereas NTFS needs ntfs_iget().
501
 */
502
const struct export_operations ntfs_export_ops = {
503
        .get_parent     = ntfs_get_parent,      /* Find the parent of a given
504
                                                   directory. */
505
        .fh_to_dentry   = ntfs_fh_to_dentry,
506
        .fh_to_parent   = ntfs_fh_to_parent,
507
};

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.