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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [udf/] [dir.c] - Diff between revs 1275 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 1275 Rev 1765
/*
/*
 * dir.c
 * dir.c
 *
 *
 * PURPOSE
 * PURPOSE
 *  Directory handling routines for the OSTA-UDF(tm) filesystem.
 *  Directory handling routines for the OSTA-UDF(tm) filesystem.
 *
 *
 * CONTACTS
 * CONTACTS
 *      E-mail regarding any portion of the Linux UDF file system should be
 *      E-mail regarding any portion of the Linux UDF file system should be
 *      directed to the development team mailing list (run by majordomo):
 *      directed to the development team mailing list (run by majordomo):
 *              linux_udf@hpesjro.fc.hp.com
 *              linux_udf@hpesjro.fc.hp.com
 *
 *
 * COPYRIGHT
 * COPYRIGHT
 *      This file is distributed under the terms of the GNU General Public
 *      This file is distributed under the terms of the GNU General Public
 *      License (GPL). Copies of the GPL can be obtained from:
 *      License (GPL). Copies of the GPL can be obtained from:
 *              ftp://prep.ai.mit.edu/pub/gnu/GPL
 *              ftp://prep.ai.mit.edu/pub/gnu/GPL
 *      Each contributing author retains all rights to their own work.
 *      Each contributing author retains all rights to their own work.
 *
 *
 *  (C) 1998-2001 Ben Fennema
 *  (C) 1998-2001 Ben Fennema
 *
 *
 * HISTORY
 * HISTORY
 *
 *
 *  10/05/98 dgb  Split directory operations into it's own file
 *  10/05/98 dgb  Split directory operations into it's own file
 *                Implemented directory reads via do_udf_readdir
 *                Implemented directory reads via do_udf_readdir
 *  10/06/98      Made directory operations work!
 *  10/06/98      Made directory operations work!
 *  11/17/98      Rewrote directory to support ICBTAG_FLAG_AD_LONG
 *  11/17/98      Rewrote directory to support ICBTAG_FLAG_AD_LONG
 *  11/25/98 blf  Rewrote directory handling (readdir+lookup) to support reading
 *  11/25/98 blf  Rewrote directory handling (readdir+lookup) to support reading
 *                across blocks.
 *                across blocks.
 *  12/12/98      Split out the lookup code to namei.c. bulk of directory
 *  12/12/98      Split out the lookup code to namei.c. bulk of directory
 *                code now in directory.c:udf_fileident_read.
 *                code now in directory.c:udf_fileident_read.
 */
 */
 
 
#include "udfdecl.h"
#include "udfdecl.h"
 
 
#include <linux/string.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/slab.h>
 
 
#include "udf_i.h"
#include "udf_i.h"
#include "udf_sb.h"
#include "udf_sb.h"
 
 
/* Prototypes for file operations */
/* Prototypes for file operations */
static int udf_readdir(struct file *, void *, filldir_t);
static int udf_readdir(struct file *, void *, filldir_t);
static int do_udf_readdir(struct inode *, struct file *, filldir_t, void *);
static int do_udf_readdir(struct inode *, struct file *, filldir_t, void *);
 
 
/* readdir and lookup functions */
/* readdir and lookup functions */
 
 
struct file_operations udf_dir_operations = {
struct file_operations udf_dir_operations = {
        read:                   generic_read_dir,
        read:                   generic_read_dir,
        readdir:                udf_readdir,
        readdir:                udf_readdir,
        ioctl:                  udf_ioctl,
        ioctl:                  udf_ioctl,
        fsync:                  udf_fsync_file,
        fsync:                  udf_fsync_file,
};
};
 
 
/*
/*
 * udf_readdir
 * udf_readdir
 *
 *
 * PURPOSE
 * PURPOSE
 *      Read a directory entry.
 *      Read a directory entry.
 *
 *
 * DESCRIPTION
 * DESCRIPTION
 *      Optional - sys_getdents() will return -ENOTDIR if this routine is not
 *      Optional - sys_getdents() will return -ENOTDIR if this routine is not
 *      available.
 *      available.
 *
 *
 *      Refer to sys_getdents() in fs/readdir.c
 *      Refer to sys_getdents() in fs/readdir.c
 *      sys_getdents() -> .
 *      sys_getdents() -> .
 *
 *
 * PRE-CONDITIONS
 * PRE-CONDITIONS
 *      filp                    Pointer to directory file.
 *      filp                    Pointer to directory file.
 *      buf                     Pointer to directory entry buffer.
 *      buf                     Pointer to directory entry buffer.
 *      filldir                 Pointer to filldir function.
 *      filldir                 Pointer to filldir function.
 *
 *
 * POST-CONDITIONS
 * POST-CONDITIONS
 *      <return>                >=0 on success.
 *      <return>                >=0 on success.
 *
 *
 * HISTORY
 * HISTORY
 *      July 1, 1997 - Andrew E. Mileski
 *      July 1, 1997 - Andrew E. Mileski
 *      Written, tested, and released.
 *      Written, tested, and released.
 */
 */
 
 
int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
{
        struct inode *dir = filp->f_dentry->d_inode;
        struct inode *dir = filp->f_dentry->d_inode;
        int result;
        int result;
 
 
        if ( filp->f_pos == 0 )
        if ( filp->f_pos == 0 )
        {
        {
                if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0)
                if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0)
                        return 0;
                        return 0;
                filp->f_pos ++;
                filp->f_pos ++;
        }
        }
 
 
        result = do_udf_readdir(dir, filp, filldir, dirent);
        result = do_udf_readdir(dir, filp, filldir, dirent);
        UPDATE_ATIME(dir);
        UPDATE_ATIME(dir);
        return result;
        return result;
}
}
 
 
static int
static int
do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *dirent)
do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *dirent)
{
{
        struct udf_fileident_bh fibh;
        struct udf_fileident_bh fibh;
        struct fileIdentDesc *fi=NULL;
        struct fileIdentDesc *fi=NULL;
        struct fileIdentDesc cfi;
        struct fileIdentDesc cfi;
        int block, iblock;
        int block, iblock;
        loff_t nf_pos = filp->f_pos - 1;
        loff_t nf_pos = filp->f_pos - 1;
        int flen;
        int flen;
        char fname[255];
        char fname[255];
        char *nameptr;
        char *nameptr;
        uint16_t liu;
        uint16_t liu;
        uint8_t lfi;
        uint8_t lfi;
        loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
        loff_t size = (udf_ext0_offset(dir) + dir->i_size) >> 2;
        struct buffer_head * bh = NULL, * tmp, * bha[16];
        struct buffer_head * bh = NULL, * tmp, * bha[16];
        lb_addr bloc, eloc;
        lb_addr bloc, eloc;
        uint32_t extoffset, elen, offset;
        uint32_t extoffset, elen, offset;
        int i, num;
        int i, num;
        unsigned int dt_type;
        unsigned int dt_type;
 
 
        if (nf_pos >= size)
        if (nf_pos >= size)
                return 0;
                return 0;
 
 
        if (nf_pos == 0)
        if (nf_pos == 0)
                nf_pos = (udf_ext0_offset(dir) >> 2);
                nf_pos = (udf_ext0_offset(dir) >> 2);
 
 
        fibh.soffset = fibh.eoffset = (nf_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
        fibh.soffset = fibh.eoffset = (nf_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
        if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
        if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
                &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
                &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
        {
        {
                offset >>= dir->i_sb->s_blocksize_bits;
                offset >>= dir->i_sb->s_blocksize_bits;
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
                block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
                if ((++offset << dir->i_sb->s_blocksize_bits) < elen)
                {
                {
                        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
                        if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_SHORT)
                                extoffset -= sizeof(short_ad);
                                extoffset -= sizeof(short_ad);
                        else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
                        else if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_LONG)
                                extoffset -= sizeof(long_ad);
                                extoffset -= sizeof(long_ad);
                }
                }
                else
                else
                        offset = 0;
                        offset = 0;
        }
        }
        else
        else
        {
        {
                udf_release_data(bh);
                udf_release_data(bh);
                return -ENOENT;
                return -ENOENT;
        }
        }
 
 
        if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
        if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
        {
        {
                udf_release_data(bh);
                udf_release_data(bh);
                return -EIO;
                return -EIO;
        }
        }
 
 
        if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
        if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
        {
        {
                i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
                i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
                if (i+offset > (elen >> dir->i_sb->s_blocksize_bits))
                if (i+offset > (elen >> dir->i_sb->s_blocksize_bits))
                        i = (elen >> dir->i_sb->s_blocksize_bits)-offset;
                        i = (elen >> dir->i_sb->s_blocksize_bits)-offset;
                for (num=0; i>0; i--)
                for (num=0; i>0; i--)
                {
                {
                        block = udf_get_lb_pblock(dir->i_sb, eloc, offset+i);
                        block = udf_get_lb_pblock(dir->i_sb, eloc, offset+i);
                        tmp = udf_tgetblk(dir->i_sb, block);
                        tmp = udf_tgetblk(dir->i_sb, block);
                        if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
                        if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
                                bha[num++] = tmp;
                                bha[num++] = tmp;
                        else
                        else
                                brelse(tmp);
                                brelse(tmp);
                }
                }
                if (num)
                if (num)
                {
                {
                        ll_rw_block(READA, num, bha);
                        ll_rw_block(READA, num, bha);
                        for (i=0; i<num; i++)
                        for (i=0; i<num; i++)
                                brelse(bha[i]);
                                brelse(bha[i]);
                }
                }
        }
        }
 
 
        while ( nf_pos < size )
        while ( nf_pos < size )
        {
        {
                filp->f_pos = nf_pos + 1;
                filp->f_pos = nf_pos + 1;
 
 
                fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
                fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
 
 
                if (!fi)
                if (!fi)
                {
                {
                        if (fibh.sbh != fibh.ebh)
                        if (fibh.sbh != fibh.ebh)
                                udf_release_data(fibh.ebh);
                                udf_release_data(fibh.ebh);
                        udf_release_data(fibh.sbh);
                        udf_release_data(fibh.sbh);
                        udf_release_data(bh);
                        udf_release_data(bh);
                        return 0;
                        return 0;
                }
                }
 
 
                liu = le16_to_cpu(cfi.lengthOfImpUse);
                liu = le16_to_cpu(cfi.lengthOfImpUse);
                lfi = cfi.lengthFileIdent;
                lfi = cfi.lengthFileIdent;
 
 
                if (fibh.sbh == fibh.ebh)
                if (fibh.sbh == fibh.ebh)
                        nameptr = fi->fileIdent + liu;
                        nameptr = fi->fileIdent + liu;
                else
                else
                {
                {
                        int poffset;    /* Unpaded ending offset */
                        int poffset;    /* Unpaded ending offset */
 
 
                        poffset = fibh.soffset + sizeof(struct fileIdentDesc) + liu + lfi;
                        poffset = fibh.soffset + sizeof(struct fileIdentDesc) + liu + lfi;
 
 
                        if (poffset >= lfi)
                        if (poffset >= lfi)
                                nameptr = (char *)(fibh.ebh->b_data + poffset - lfi);
                                nameptr = (char *)(fibh.ebh->b_data + poffset - lfi);
                        else
                        else
                        {
                        {
                                nameptr = fname;
                                nameptr = fname;
                                memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
                                memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
                                memcpy(nameptr + lfi - poffset, fibh.ebh->b_data, poffset);
                                memcpy(nameptr + lfi - poffset, fibh.ebh->b_data, poffset);
                        }
                        }
                }
                }
 
 
                if ( (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) != 0 )
                if ( (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) != 0 )
                {
                {
                        if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE) )
                        if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE) )
                                continue;
                                continue;
                }
                }
 
 
                if ( (cfi.fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0 )
                if ( (cfi.fileCharacteristics & FID_FILE_CHAR_HIDDEN) != 0 )
                {
                {
                        if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE) )
                        if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE) )
                                continue;
                                continue;
                }
                }
 
 
                if ( cfi.fileCharacteristics & FID_FILE_CHAR_PARENT )
                if ( cfi.fileCharacteristics & FID_FILE_CHAR_PARENT )
                {
                {
                        iblock = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(filp->f_dentry->d_parent->d_inode), 0);
                        iblock = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(filp->f_dentry->d_parent->d_inode), 0);
                        flen = 2;
                        flen = 2;
                        memcpy(fname, "..", flen);
                        memcpy(fname, "..", flen);
                        dt_type = DT_DIR;
                        dt_type = DT_DIR;
                }
                }
                else
                else
                {
                {
                        iblock = udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0);
                        iblock = udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0);
                        flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
                        flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
                        dt_type = DT_UNKNOWN;
                        dt_type = DT_UNKNOWN;
                }
                }
 
 
                if (flen)
                if (flen)
                {
                {
                        if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0)
                        if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0)
                        {
                        {
                                if (fibh.sbh != fibh.ebh)
                                if (fibh.sbh != fibh.ebh)
                                        udf_release_data(fibh.ebh);
                                        udf_release_data(fibh.ebh);
                                udf_release_data(fibh.sbh);
                                udf_release_data(fibh.sbh);
                                udf_release_data(bh);
                                udf_release_data(bh);
                                return 0;
                                return 0;
                        }
                        }
                }
                }
        } /* end while */
        } /* end while */
 
 
        filp->f_pos = nf_pos + 1;
        filp->f_pos = nf_pos + 1;
 
 
        if (fibh.sbh != fibh.ebh)
        if (fibh.sbh != fibh.ebh)
                udf_release_data(fibh.ebh);
                udf_release_data(fibh.ebh);
        udf_release_data(fibh.sbh);
        udf_release_data(fibh.sbh);
        udf_release_data(bh);
        udf_release_data(bh);
 
 
        return 0;
        return 0;
}
}
 
 

powered by: WebSVN 2.1.0

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