aboutsummaryrefslogtreecommitdiffstats
path: root/fs/udf/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/udf/dir.c')
-rw-r--r--fs/udf/dir.c141
1 files changed, 69 insertions, 72 deletions
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index 9e3b9f97ddbc..8d8643ada199 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -36,80 +36,20 @@
36#include "udf_i.h" 36#include "udf_i.h"
37#include "udf_sb.h" 37#include "udf_sb.h"
38 38
39/* Prototypes for file operations */ 39static int do_udf_readdir(struct inode *dir, struct file *filp,
40static int udf_readdir(struct file *, void *, filldir_t); 40 filldir_t filldir, void *dirent)
41static int do_udf_readdir(struct inode *, struct file *, filldir_t, void *);
42
43/* readdir and lookup functions */
44
45const struct file_operations udf_dir_operations = {
46 .read = generic_read_dir,
47 .readdir = udf_readdir,
48 .ioctl = udf_ioctl,
49 .fsync = udf_fsync_file,
50};
51
52/*
53 * udf_readdir
54 *
55 * PURPOSE
56 * Read a directory entry.
57 *
58 * DESCRIPTION
59 * Optional - sys_getdents() will return -ENOTDIR if this routine is not
60 * available.
61 *
62 * Refer to sys_getdents() in fs/readdir.c
63 * sys_getdents() -> .
64 *
65 * PRE-CONDITIONS
66 * filp Pointer to directory file.
67 * buf Pointer to directory entry buffer.
68 * filldir Pointer to filldir function.
69 *
70 * POST-CONDITIONS
71 * <return> >=0 on success.
72 *
73 * HISTORY
74 * July 1, 1997 - Andrew E. Mileski
75 * Written, tested, and released.
76 */
77
78int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
79{
80 struct inode *dir = filp->f_path.dentry->d_inode;
81 int result;
82
83 lock_kernel();
84
85 if (filp->f_pos == 0) {
86 if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0) {
87 unlock_kernel();
88 return 0;
89 }
90 filp->f_pos++;
91 }
92
93 result = do_udf_readdir(dir, filp, filldir, dirent);
94 unlock_kernel();
95 return result;
96}
97
98static int
99do_udf_readdir(struct inode *dir, struct file *filp, filldir_t filldir,
100 void *dirent)
101{ 41{
102 struct udf_fileident_bh fibh; 42 struct udf_fileident_bh fibh;
103 struct fileIdentDesc *fi = NULL; 43 struct fileIdentDesc *fi = NULL;
104 struct fileIdentDesc cfi; 44 struct fileIdentDesc cfi;
105 int block, iblock; 45 int block, iblock;
106 loff_t nf_pos = filp->f_pos - 1; 46 loff_t nf_pos = (filp->f_pos - 1) << 2;
107 int flen; 47 int flen;
108 char fname[UDF_NAME_LEN]; 48 char fname[UDF_NAME_LEN];
109 char *nameptr; 49 char *nameptr;
110 uint16_t liu; 50 uint16_t liu;
111 uint8_t lfi; 51 uint8_t lfi;
112 loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2; 52 loff_t size = udf_ext0_offset(dir) + dir->i_size;
113 struct buffer_head *tmp, *bha[16]; 53 struct buffer_head *tmp, *bha[16];
114 kernel_lb_addr eloc; 54 kernel_lb_addr eloc;
115 uint32_t elen; 55 uint32_t elen;
@@ -117,23 +57,26 @@ do_udf_readdir(struct inode *dir, struct file *filp, filldir_t filldir,
117 int i, num; 57 int i, num;
118 unsigned int dt_type; 58 unsigned int dt_type;
119 struct extent_position epos = { NULL, 0, {0, 0} }; 59 struct extent_position epos = { NULL, 0, {0, 0} };
60 struct udf_inode_info *iinfo;
120 61
121 if (nf_pos >= size) 62 if (nf_pos >= size)
122 return 0; 63 return 0;
123 64
124 if (nf_pos == 0) 65 if (nf_pos == 0)
125 nf_pos = (udf_ext0_offset(dir) >> 2); 66 nf_pos = udf_ext0_offset(dir);
126 67
127 fibh.soffset = fibh.eoffset = (nf_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2; 68 fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1);
128 if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB) { 69 iinfo = UDF_I(dir);
70 if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
129 fibh.sbh = fibh.ebh = NULL; 71 fibh.sbh = fibh.ebh = NULL;
130 } else if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2), 72 } else if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
131 &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) { 73 &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) {
132 block = udf_get_lb_pblock(dir->i_sb, eloc, offset); 74 block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
133 if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { 75 if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
134 if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT) 76 if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
135 epos.offset -= sizeof(short_ad); 77 epos.offset -= sizeof(short_ad);
136 else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG) 78 else if (iinfo->i_alloc_type ==
79 ICBTAG_FLAG_AD_LONG)
137 epos.offset -= sizeof(long_ad); 80 epos.offset -= sizeof(long_ad);
138 } else { 81 } else {
139 offset = 0; 82 offset = 0;
@@ -168,7 +111,7 @@ do_udf_readdir(struct inode *dir, struct file *filp, filldir_t filldir,
168 } 111 }
169 112
170 while (nf_pos < size) { 113 while (nf_pos < size) {
171 filp->f_pos = nf_pos + 1; 114 filp->f_pos = (nf_pos >> 2) + 1;
172 115
173 fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, 116 fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc,
174 &elen, &offset); 117 &elen, &offset);
@@ -235,7 +178,7 @@ do_udf_readdir(struct inode *dir, struct file *filp, filldir_t filldir,
235 } 178 }
236 } /* end while */ 179 } /* end while */
237 180
238 filp->f_pos = nf_pos + 1; 181 filp->f_pos = (nf_pos >> 2) + 1;
239 182
240 if (fibh.sbh != fibh.ebh) 183 if (fibh.sbh != fibh.ebh)
241 brelse(fibh.ebh); 184 brelse(fibh.ebh);
@@ -244,3 +187,57 @@ do_udf_readdir(struct inode *dir, struct file *filp, filldir_t filldir,
244 187
245 return 0; 188 return 0;
246} 189}
190
191/*
192 * udf_readdir
193 *
194 * PURPOSE
195 * Read a directory entry.
196 *
197 * DESCRIPTION
198 * Optional - sys_getdents() will return -ENOTDIR if this routine is not
199 * available.
200 *
201 * Refer to sys_getdents() in fs/readdir.c
202 * sys_getdents() -> .
203 *
204 * PRE-CONDITIONS
205 * filp Pointer to directory file.
206 * buf Pointer to directory entry buffer.
207 * filldir Pointer to filldir function.
208 *
209 * POST-CONDITIONS
210 * <return> >=0 on success.
211 *
212 * HISTORY
213 * July 1, 1997 - Andrew E. Mileski
214 * Written, tested, and released.
215 */
216
217static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
218{
219 struct inode *dir = filp->f_path.dentry->d_inode;
220 int result;
221
222 lock_kernel();
223
224 if (filp->f_pos == 0) {
225 if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0) {
226 unlock_kernel();
227 return 0;
228 }
229 filp->f_pos++;
230 }
231
232 result = do_udf_readdir(dir, filp, filldir, dirent);
233 unlock_kernel();
234 return result;
235}
236
237/* readdir and lookup functions */
238const struct file_operations udf_dir_operations = {
239 .read = generic_read_dir,
240 .readdir = udf_readdir,
241 .ioctl = udf_ioctl,
242 .fsync = udf_fsync_file,
243};