]> Git Repo - linux.git/blob - fs/udf/dir.c
selftests: error out if kernel header files are not yet built
[linux.git] / fs / udf / dir.c
1 /*
2  * dir.c
3  *
4  * PURPOSE
5  *  Directory handling routines for the OSTA-UDF(tm) filesystem.
6  *
7  * COPYRIGHT
8  *      This file is distributed under the terms of the GNU General Public
9  *      License (GPL). Copies of the GPL can be obtained from:
10  *              ftp://prep.ai.mit.edu/pub/gnu/GPL
11  *      Each contributing author retains all rights to their own work.
12  *
13  *  (C) 1998-2004 Ben Fennema
14  *
15  * HISTORY
16  *
17  *  10/05/98 dgb  Split directory operations into its own file
18  *                Implemented directory reads via do_udf_readdir
19  *  10/06/98      Made directory operations work!
20  *  11/17/98      Rewrote directory to support ICBTAG_FLAG_AD_LONG
21  *  11/25/98 blf  Rewrote directory handling (readdir+lookup) to support reading
22  *                across blocks.
23  *  12/12/98      Split out the lookup code to namei.c. bulk of directory
24  *                code now in directory.c:udf_fileident_read.
25  */
26
27 #include "udfdecl.h"
28
29 #include <linux/string.h>
30 #include <linux/errno.h>
31 #include <linux/mm.h>
32 #include <linux/slab.h>
33 #include <linux/bio.h>
34 #include <linux/iversion.h>
35
36 #include "udf_i.h"
37 #include "udf_sb.h"
38
39 static int udf_readdir(struct file *file, struct dir_context *ctx)
40 {
41         struct inode *dir = file_inode(file);
42         loff_t nf_pos, emit_pos = 0;
43         int flen;
44         unsigned char *fname = NULL;
45         int ret = 0;
46         struct super_block *sb = dir->i_sb;
47         bool pos_valid = false;
48         struct udf_fileident_iter iter;
49
50         if (ctx->pos == 0) {
51                 if (!dir_emit_dot(file, ctx))
52                         return 0;
53                 ctx->pos = 1;
54         }
55         nf_pos = (ctx->pos - 1) << 2;
56         if (nf_pos >= dir->i_size)
57                 goto out;
58
59         /*
60          * Something changed since last readdir (either lseek was called or dir
61          * changed)?  We need to verify the position correctly points at the
62          * beginning of some dir entry so that the directory parsing code does
63          * not get confused. Since UDF does not have any reliable way of
64          * identifying beginning of dir entry (names are under user control),
65          * we need to scan the directory from the beginning.
66          */
67         if (!inode_eq_iversion(dir, file->f_version)) {
68                 emit_pos = nf_pos;
69                 nf_pos = 0;
70         } else {
71                 pos_valid = true;
72         }
73
74         fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
75         if (!fname) {
76                 ret = -ENOMEM;
77                 goto out;
78         }
79
80         for (ret = udf_fiiter_init(&iter, dir, nf_pos);
81              !ret && iter.pos < dir->i_size;
82              ret = udf_fiiter_advance(&iter)) {
83                 struct kernel_lb_addr tloc;
84                 udf_pblk_t iblock;
85
86                 /* Still not at offset where user asked us to read from? */
87                 if (iter.pos < emit_pos)
88                         continue;
89
90                 /* Update file position only if we got past the current one */
91                 pos_valid = true;
92                 ctx->pos = (iter.pos >> 2) + 1;
93
94                 if (iter.fi.fileCharacteristics & FID_FILE_CHAR_DELETED) {
95                         if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNDELETE))
96                                 continue;
97                 }
98
99                 if (iter.fi.fileCharacteristics & FID_FILE_CHAR_HIDDEN) {
100                         if (!UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE))
101                                 continue;
102                 }
103
104                 if (iter.fi.fileCharacteristics & FID_FILE_CHAR_PARENT) {
105                         if (!dir_emit_dotdot(file, ctx))
106                                 goto out_iter;
107                         continue;
108                 }
109
110                 flen = udf_get_filename(sb, iter.name,
111                                 iter.fi.lengthFileIdent, fname, UDF_NAME_LEN);
112                 if (flen < 0)
113                         continue;
114
115                 tloc = lelb_to_cpu(iter.fi.icb.extLocation);
116                 iblock = udf_get_lb_pblock(sb, &tloc, 0);
117                 if (!dir_emit(ctx, fname, flen, iblock, DT_UNKNOWN))
118                         goto out_iter;
119         }
120
121         if (!ret) {
122                 ctx->pos = (iter.pos >> 2) + 1;
123                 pos_valid = true;
124         }
125 out_iter:
126         udf_fiiter_release(&iter);
127 out:
128         if (pos_valid)
129                 file->f_version = inode_query_iversion(dir);
130         kfree(fname);
131
132         return ret;
133 }
134
135 /* readdir and lookup functions */
136 const struct file_operations udf_dir_operations = {
137         .llseek                 = generic_file_llseek,
138         .read                   = generic_read_dir,
139         .iterate_shared         = udf_readdir,
140         .unlocked_ioctl         = udf_ioctl,
141         .fsync                  = generic_file_fsync,
142 };
This page took 0.035009 seconds and 4 git commands to generate.