~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/fs/udf/dir.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * dir.c
  3  *
  4  * PURPOSE
  5  *  Directory handling routines for the OSTA-UDF(tm) filesystem.
  6  *
  7  * CONTACTS
  8  *      E-mail regarding any portion of the Linux UDF file system should be
  9  *      directed to the development team mailing list (run by majordomo):
 10  *              linux_udf@hootie.lvld.hp.com
 11  *
 12  * COPYRIGHT
 13  *      This file is distributed under the terms of the GNU General Public
 14  *      License (GPL). Copies of the GPL can be obtained from:
 15  *              ftp://prep.ai.mit.edu/pub/gnu/GPL
 16  *      Each contributing author retains all rights to their own work.
 17  *
 18  *  (C) 1998-2000 Ben Fennema
 19  *
 20  * HISTORY
 21  *
 22  *  10/05/98 dgb  Split directory operations into it's own file
 23  *                Implemented directory reads via do_udf_readdir
 24  *  10/06/98      Made directory operations work!
 25  *  11/17/98      Rewrote directory to support ICB_FLAG_AD_LONG
 26  *  11/25/98 blf  Rewrote directory handling (readdir+lookup) to support reading
 27  *                across blocks.
 28  *  12/12/98      Split out the lookup code to namei.c. bulk of directory
 29  *                code now in directory.c:udf_fileident_read.
 30  */
 31 
 32 #include "udfdecl.h"
 33 
 34 #if defined(__linux__) && defined(__KERNEL__)
 35 #include <linux/version.h>
 36 #include "udf_i.h"
 37 #include "udf_sb.h"
 38 #include <linux/string.h>
 39 #include <linux/errno.h>
 40 #include <linux/mm.h>
 41 #include <linux/malloc.h>
 42 #include <linux/udf_fs.h>
 43 #endif
 44 
 45 /* Prototypes for file operations */
 46 static int udf_readdir(struct file *, void *, filldir_t);
 47 static int do_udf_readdir(struct inode *, struct file *, filldir_t, void *);
 48 
 49 /* readdir and lookup functions */
 50 
 51 struct file_operations udf_dir_operations = {
 52         read:                           generic_read_dir,
 53         readdir:                        udf_readdir,
 54         ioctl:                          udf_ioctl,
 55         fsync:                          udf_sync_file,
 56 };
 57 
 58 /*
 59  * udf_readdir
 60  *
 61  * PURPOSE
 62  *      Read a directory entry.
 63  *
 64  * DESCRIPTION
 65  *      Optional - sys_getdents() will return -ENOTDIR if this routine is not
 66  *      available.
 67  *
 68  *      Refer to sys_getdents() in fs/readdir.c
 69  *      sys_getdents() -> .
 70  *
 71  * PRE-CONDITIONS
 72  *      filp                    Pointer to directory file.
 73  *      buf                     Pointer to directory entry buffer.
 74  *      filldir                 Pointer to filldir function.
 75  *
 76  * POST-CONDITIONS
 77  *      <return>                >=0 on success.
 78  *
 79  * HISTORY
 80  *      July 1, 1997 - Andrew E. Mileski
 81  *      Written, tested, and released.
 82  */
 83 
 84 int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
 85 {
 86         struct inode *dir = filp->f_dentry->d_inode;
 87         int result;
 88 
 89         if ( filp->f_pos == 0 ) 
 90         {
 91                 if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR))
 92                         return 0;
 93         }
 94  
 95         result = do_udf_readdir(dir, filp, filldir, dirent);
 96         UPDATE_ATIME(dir);
 97         return result;
 98 }
 99 
100 static int 
101 do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *dirent)
102 {
103         struct udf_fileident_bh fibh;
104         struct FileIdentDesc *fi=NULL;
105         struct FileIdentDesc cfi;
106         int block, iblock;
107         loff_t nf_pos = filp->f_pos;
108         int flen;
109         char fname[255];
110         char *nameptr;
111         Uint16 liu;
112         Uint8 lfi;
113         loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
114         struct buffer_head * bh = NULL;
115         lb_addr bloc, eloc;
116         Uint32 extoffset, elen, offset;
117 
118         if (nf_pos >= size)
119                 return 1;
120 
121         if (nf_pos == 0)
122                 nf_pos = (udf_ext0_offset(dir) >> 2);
123 
124         fibh.soffset = fibh.eoffset = (nf_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
125         if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
126                 &bloc, &extoffset, &eloc, &elen, &offset, &bh) == EXTENT_RECORDED_ALLOCATED)
127         {
128                 block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
129                 if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
130                 {
131                         if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_SHORT)
132                                 extoffset -= sizeof(short_ad);
133                         else if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_LONG)
134                                 extoffset -= sizeof(long_ad);
135                 }
136                 else
137                         offset = 0;
138         }
139         else
140         {
141                 udf_release_data(bh);
142                 return 0;
143         }
144 
145         if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
146         {
147                 udf_release_data(bh);
148                 return 0;
149         }
150 
151         while ( nf_pos < size )
152         {
153                 filp->f_pos = nf_pos;
154 
155                 fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
156 
157                 if (!fi)
158                 {
159                         if (fibh.sbh != fibh.ebh)
160                                 udf_release_data(fibh.ebh);
161                         udf_release_data(fibh.sbh);
162                         udf_release_data(bh);
163                         return 1;
164                 }
165 
166                 liu = le16_to_cpu(cfi.lengthOfImpUse);
167                 lfi = cfi.lengthFileIdent;
168 
169                 if (fibh.sbh == fibh.ebh)
170                         nameptr = fi->fileIdent + liu;
171                 else
172                 {
173                         int poffset;    /* Unpaded ending offset */
174 
175                         poffset = fibh.soffset + sizeof(struct FileIdentDesc) + liu + lfi;
176 
177                         if (poffset >= lfi)
178                                 nameptr = (char *)(fibh.ebh->b_data + poffset - lfi);
179                         else
180                         {
181                                 nameptr = fname;
182                                 memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
183                                 memcpy(nameptr + lfi - poffset, fibh.ebh->b_data, poffset);
184                         }
185                 }
186 
187                 if ( (cfi.fileCharacteristics & FILE_DELETED) != 0 )
188                 {
189                         if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE) )
190                                 continue;
191                 }
192                 
193                 if ( (cfi.fileCharacteristics & FILE_HIDDEN) != 0 )
194                 {
195                         if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE) )
196                                 continue;
197                 }
198 
199                 iblock = udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0);
200  
201                 if (!lfi) /* parent directory */
202                 {
203                         if (filldir(dirent, "..", 2, filp->f_pos, filp->f_dentry->d_parent->d_inode->i_ino, DT_DIR))
204                         {
205                                 if (fibh.sbh != fibh.ebh)
206                                         udf_release_data(fibh.ebh);
207                                 udf_release_data(fibh.sbh);
208                                 udf_release_data(bh);
209                                 return 1;
210                         }
211                 }
212                 else
213                 {
214                         if ((flen = udf_get_filename(nameptr, fname, lfi)))
215                         {
216                                 if (filldir(dirent, fname, flen, filp->f_pos, iblock, DT_UNKNOWN))
217                                 {
218                                         if (fibh.sbh != fibh.ebh)
219                                                 udf_release_data(fibh.ebh);
220                                         udf_release_data(fibh.sbh);
221                                         udf_release_data(bh);
222                                         return 1; /* halt enum */
223                                 }
224                         }
225                 }
226         } /* end while */
227 
228         filp->f_pos = nf_pos;
229 
230         if (fibh.sbh != fibh.ebh)
231                 udf_release_data(fibh.ebh);
232         udf_release_data(fibh.sbh);
233         udf_release_data(bh);
234 
235         if ( filp->f_pos >= size)
236                 return 1;
237         else
238                 return 0;
239 }
240 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.