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

Subversion Repositories or1k

[/] [or1k/] [tags/] [before_ORP/] [uclinux/] [uClinux-2.0.x/] [fs/] [isofs/] [dir.c] - Diff between revs 901 and 1765

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

Rev 901 Rev 1765
/*
/*
 *  linux/fs/isofs/dir.c
 *  linux/fs/isofs/dir.c
 *
 *
 *  (C) 1992, 1993, 1994  Eric Youngdale Modified for ISO9660 filesystem.
 *  (C) 1992, 1993, 1994  Eric Youngdale Modified for ISO9660 filesystem.
 *
 *
 *  (C) 1991  Linus Torvalds - minix filesystem
 *  (C) 1991  Linus Torvalds - minix filesystem
 *
 *
 *  Steve Beynon                       : Missing last directory entries fixed
 *  Steve Beynon                       : Missing last directory entries fixed
 *  (stephen@askone.demon.co.uk)      : 21st June 1996
 *  (stephen@askone.demon.co.uk)      : 21st June 1996
 *
 *
 *  isofs directory handling functions
 *  isofs directory handling functions
 */
 */
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/fs.h>
#include <linux/iso_fs.h>
#include <linux/iso_fs.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/stat.h>
#include <linux/stat.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/malloc.h>
#include <linux/malloc.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/locks.h>
#include <linux/locks.h>
 
 
#include <asm/segment.h>
#include <asm/segment.h>
 
 
 
 
static int isofs_readdir(struct inode *, struct file *, void *, filldir_t);
static int isofs_readdir(struct inode *, struct file *, void *, filldir_t);
 
 
static struct file_operations isofs_dir_operations =
static struct file_operations isofs_dir_operations =
{
{
        NULL,                   /* lseek - default */
        NULL,                   /* lseek - default */
        NULL,                   /* read */
        NULL,                   /* read */
        NULL,                   /* write - bad */
        NULL,                   /* write - bad */
        isofs_readdir,          /* readdir */
        isofs_readdir,          /* readdir */
        NULL,                   /* select - default */
        NULL,                   /* select - default */
        NULL,                   /* ioctl - default */
        NULL,                   /* ioctl - default */
        NULL,                   /* no special open code */
        NULL,                   /* no special open code */
        NULL,                   /* no special release code */
        NULL,                   /* no special release code */
        NULL                    /* fsync */
        NULL                    /* fsync */
};
};
 
 
/*
/*
 * directories can handle most operations...
 * directories can handle most operations...
 */
 */
struct inode_operations isofs_dir_inode_operations =
struct inode_operations isofs_dir_inode_operations =
{
{
        &isofs_dir_operations,  /* default directory file-ops */
        &isofs_dir_operations,  /* default directory file-ops */
        NULL,                   /* create */
        NULL,                   /* create */
        isofs_lookup,           /* lookup */
        isofs_lookup,           /* lookup */
        NULL,                   /* link */
        NULL,                   /* link */
        NULL,                   /* unlink */
        NULL,                   /* unlink */
        NULL,                   /* symlink */
        NULL,                   /* symlink */
        NULL,                   /* mkdir */
        NULL,                   /* mkdir */
        NULL,                   /* rmdir */
        NULL,                   /* rmdir */
        NULL,                   /* mknod */
        NULL,                   /* mknod */
        NULL,                   /* rename */
        NULL,                   /* rename */
        NULL,                   /* readlink */
        NULL,                   /* readlink */
        NULL,                   /* follow_link */
        NULL,                   /* follow_link */
        NULL,                   /* readpage */
        NULL,                   /* readpage */
        NULL,                   /* writepage */
        NULL,                   /* writepage */
        isofs_bmap,             /* bmap */
        isofs_bmap,             /* bmap */
        NULL,                   /* truncate */
        NULL,                   /* truncate */
        NULL                    /* permission */
        NULL                    /* permission */
};
};
 
 
static int parent_inode_number(struct inode * inode, struct iso_directory_record * de)
static int parent_inode_number(struct inode * inode, struct iso_directory_record * de)
{
{
        int inode_number = inode->i_ino;
        int inode_number = inode->i_ino;
 
 
        if ((inode->i_sb->u.isofs_sb.s_firstdatazone) != inode->i_ino)
        if ((inode->i_sb->u.isofs_sb.s_firstdatazone) != inode->i_ino)
                inode_number = inode->u.isofs_i.i_backlink;
                inode_number = inode->u.isofs_i.i_backlink;
 
 
        if (inode_number != -1)
        if (inode_number != -1)
                return inode_number;
                return inode_number;
 
 
        /* This should never happen, but who knows.  Try to be forgiving */
        /* This should never happen, but who knows.  Try to be forgiving */
        return isofs_lookup_grandparent(inode, find_rock_ridge_relocation(de, inode));
        return isofs_lookup_grandparent(inode, find_rock_ridge_relocation(de, inode));
}
}
 
 
static int isofs_name_translate(char * old, int len, char * new)
static int isofs_name_translate(char * old, int len, char * new)
{
{
        int i, c;
        int i, c;
 
 
        for (i = 0; i < len; i++) {
        for (i = 0; i < len; i++) {
                c = old[i];
                c = old[i];
                if (!c)
                if (!c)
                        break;
                        break;
                if (c >= 'A' && c <= 'Z')
                if (c >= 'A' && c <= 'Z')
                        c |= 0x20;      /* lower case */
                        c |= 0x20;      /* lower case */
 
 
                /* Drop trailing '.;1' (ISO9660:1988 7.5.1 requires period) */
                /* Drop trailing '.;1' (ISO9660:1988 7.5.1 requires period) */
                if (c == '.' && i == len - 3 && old[i + 1] == ';' && old[i + 2] == '1')
                if (c == '.' && i == len - 3 && old[i + 1] == ';' && old[i + 2] == '1')
                        break;
                        break;
 
 
                /* Drop trailing ';1' */
                /* Drop trailing ';1' */
                if (c == ';' && i == len - 2 && old[i + 1] == '1')
                if (c == ';' && i == len - 2 && old[i + 1] == '1')
                        break;
                        break;
 
 
                /* Convert remaining ';' to '.' */
                /* Convert remaining ';' to '.' */
                if (c == ';')
                if (c == ';')
                        c = '.';
                        c = '.';
 
 
                new[i] = c;
                new[i] = c;
        }
        }
        return i;
        return i;
}
}
 
 
/*
/*
 * This should _really_ be cleaned up some day..
 * This should _really_ be cleaned up some day..
 */
 */
static int do_isofs_readdir(struct inode *inode, struct file *filp,
static int do_isofs_readdir(struct inode *inode, struct file *filp,
                void *dirent, filldir_t filldir,
                void *dirent, filldir_t filldir,
                char * tmpname, struct iso_directory_record * tmpde)
                char * tmpname, struct iso_directory_record * tmpde)
{
{
        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
        unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
        unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
        unsigned int block, offset;
        unsigned int block, offset;
        int inode_number = 0;    /* Quiet GCC */
        int inode_number = 0;    /* Quiet GCC */
        struct buffer_head *bh;
        struct buffer_head *bh;
        int len;
        int len;
        int map;
        int map;
        int high_sierra;
        int high_sierra;
        int first_de = 1;
        int first_de = 1;
        char *p = NULL;         /* Quiet GCC */
        char *p = NULL;         /* Quiet GCC */
        struct iso_directory_record *de;
        struct iso_directory_record *de;
 
 
        offset = filp->f_pos & (bufsize - 1);
        offset = filp->f_pos & (bufsize - 1);
        block = isofs_bmap(inode, filp->f_pos >> bufbits);
        block = isofs_bmap(inode, filp->f_pos >> bufbits);
        high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
        high_sierra = inode->i_sb->u.isofs_sb.s_high_sierra;
 
 
        if (!block)
        if (!block)
                return 0;
                return 0;
 
 
        if (!(bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size)))
        if (!(bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size)))
                return 0;
                return 0;
 
 
        while (filp->f_pos < inode->i_size) {
        while (filp->f_pos < inode->i_size) {
                int de_len, next_offset;
                int de_len, next_offset;
#ifdef DEBUG
#ifdef DEBUG
                printk("Block, offset, f_pos: %x %x %x\n",
                printk("Block, offset, f_pos: %x %x %x\n",
                       block, offset, filp->f_pos);
                       block, offset, filp->f_pos);
                printk("inode->i_size = %x\n",inode->i_size);
                printk("inode->i_size = %x\n",inode->i_size);
#endif
#endif
                /* Next directory_record on next CDROM sector */
                /* Next directory_record on next CDROM sector */
                if (offset >= bufsize) {
                if (offset >= bufsize) {
#ifdef DEBUG
#ifdef DEBUG
                        printk("offset >= bufsize\n");
                        printk("offset >= bufsize\n");
#endif
#endif
                        brelse(bh);
                        brelse(bh);
                        offset = 0;
                        offset = 0;
                        block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
                        block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
                        if (!block)
                        if (!block)
                                return 0;
                                return 0;
                        bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size);
                        bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size);
                        if (!bh)
                        if (!bh)
                                return 0;
                                return 0;
                        continue;
                        continue;
                }
                }
 
 
                de = (struct iso_directory_record *) (bh->b_data + offset);
                de = (struct iso_directory_record *) (bh->b_data + offset);
                if(first_de) inode_number = (block << bufbits) + (offset & (bufsize - 1));
                if(first_de) inode_number = (block << bufbits) + (offset & (bufsize - 1));
 
 
                de_len = *(unsigned char *) de;
                de_len = *(unsigned char *) de;
#ifdef DEBUG
#ifdef DEBUG
                printk("de_len = %ld\n", de_len);
                printk("de_len = %ld\n", de_len);
#endif
#endif
 
 
 
 
                /* If the length byte is zero, we should move on to the next
                /* If the length byte is zero, we should move on to the next
                   CDROM sector.  If we are at the end of the directory, we
                   CDROM sector.  If we are at the end of the directory, we
                   kick out of the while loop. */
                   kick out of the while loop. */
 
 
                if (de_len == 0) {
                if (de_len == 0) {
                        brelse(bh);
                        brelse(bh);
                        filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
                        filp->f_pos = ((filp->f_pos & ~(ISOFS_BLOCK_SIZE - 1))
                                       + ISOFS_BLOCK_SIZE);
                                       + ISOFS_BLOCK_SIZE);
                        offset = 0;
                        offset = 0;
                        block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
                        block = isofs_bmap(inode, (filp->f_pos) >> bufbits);
                        if (!block)
                        if (!block)
                                return 0;
                                return 0;
                        bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size);
                        bh = breada(inode->i_dev, block, bufsize, filp->f_pos, inode->i_size);
                        if (!bh)
                        if (!bh)
                                return 0;
                                return 0;
                        continue;
                        continue;
                }
                }
 
 
                /* Make sure that the entire directory record is in the
                /* Make sure that the entire directory record is in the
                   current bh block.
                   current bh block.
                   If not, put the two halves together in "tmpde" */
                   If not, put the two halves together in "tmpde" */
                next_offset = offset + de_len;
                next_offset = offset + de_len;
                if (next_offset > bufsize) {
                if (next_offset > bufsize) {
#ifdef DEBUG
#ifdef DEBUG
                        printk("next_offset (%x) > bufsize (%x)\n",next_offset,bufsize);
                        printk("next_offset (%x) > bufsize (%x)\n",next_offset,bufsize);
#endif
#endif
                        next_offset &= (bufsize - 1);
                        next_offset &= (bufsize - 1);
                        memcpy(tmpde, de, bufsize - offset);
                        memcpy(tmpde, de, bufsize - offset);
                        brelse(bh);
                        brelse(bh);
                        block = isofs_bmap(inode, (filp->f_pos + de_len) >> bufbits);
                        block = isofs_bmap(inode, (filp->f_pos + de_len) >> bufbits);
                        if (!block)
                        if (!block)
                        {
                        {
                                return 0;
                                return 0;
                        }
                        }
 
 
                        bh = breada(inode->i_dev, block, bufsize,
                        bh = breada(inode->i_dev, block, bufsize,
                                    filp->f_pos,
                                    filp->f_pos,
                                    inode->i_size);
                                    inode->i_size);
                        if (!bh)
                        if (!bh)
                        {
                        {
#ifdef DEBUG
#ifdef DEBUG
                                printk("!bh block=%ld, bufsize=%ld\n",block,bufsize);
                                printk("!bh block=%ld, bufsize=%ld\n",block,bufsize);
                                printk("filp->f_pos = %ld\n",filp->f_pos);
                                printk("filp->f_pos = %ld\n",filp->f_pos);
                                printk("inode->i_size = %ld\n", inode->i_size);
                                printk("inode->i_size = %ld\n", inode->i_size);
#endif
#endif
                                return 0;
                                return 0;
                        }
                        }
 
 
                        memcpy(bufsize - offset + (char *) tmpde, bh->b_data, next_offset);
                        memcpy(bufsize - offset + (char *) tmpde, bh->b_data, next_offset);
                        de = tmpde;
                        de = tmpde;
                }
                }
                offset = next_offset;
                offset = next_offset;
 
 
                if(de->flags[-high_sierra] & 0x80) {
                if(de->flags[-high_sierra] & 0x80) {
                        first_de = 0;
                        first_de = 0;
                        filp->f_pos += de_len;
                        filp->f_pos += de_len;
                        continue;
                        continue;
                }
                }
                first_de = 1;
                first_de = 1;
 
 
                /* Handle the case of the '.' directory */
                /* Handle the case of the '.' directory */
                if (de->name_len[0] == 1 && de->name[0] == 0) {
                if (de->name_len[0] == 1 && de->name[0] == 0) {
                        if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino) < 0)
                        if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino) < 0)
                                break;
                                break;
                        filp->f_pos += de_len;
                        filp->f_pos += de_len;
                        continue;
                        continue;
                }
                }
 
 
                len = 0;
                len = 0;
 
 
                /* Handle the case of the '..' directory */
                /* Handle the case of the '..' directory */
                if (de->name_len[0] == 1 && de->name[0] == 1) {
                if (de->name_len[0] == 1 && de->name[0] == 1) {
                        inode_number = parent_inode_number(inode, de);
                        inode_number = parent_inode_number(inode, de);
                        if (inode_number == -1)
                        if (inode_number == -1)
                                break;
                                break;
                        if (filldir(dirent, "..", 2, filp->f_pos, inode_number) < 0)
                        if (filldir(dirent, "..", 2, filp->f_pos, inode_number) < 0)
                                break;
                                break;
                        filp->f_pos += de_len;
                        filp->f_pos += de_len;
                        continue;
                        continue;
                }
                }
 
 
                /* Handle everything else.  Do name translation if there
                /* Handle everything else.  Do name translation if there
                   is no Rock Ridge NM field. */
                   is no Rock Ridge NM field. */
                if (inode->i_sb->u.isofs_sb.s_unhide == 'n') {
                if (inode->i_sb->u.isofs_sb.s_unhide == 'n') {
                        /* Do not report hidden or associated files */
                        /* Do not report hidden or associated files */
                        if (de->flags[-high_sierra] & 5) {
                        if (de->flags[-high_sierra] & 5) {
                                filp->f_pos += de_len;
                                filp->f_pos += de_len;
                                continue;
                                continue;
                        }
                        }
                }
                }
 
 
                map = 1;
                map = 1;
                if (inode->i_sb->u.isofs_sb.s_rock) {
                if (inode->i_sb->u.isofs_sb.s_rock) {
                        len = get_rock_ridge_filename(de, tmpname, inode);
                        len = get_rock_ridge_filename(de, tmpname, inode);
                        if (len != 0) {
                        if (len != 0) {
                                p = tmpname;
                                p = tmpname;
                                map = 0;
                                map = 0;
                        }
                        }
                }
                }
                if (map) {
                if (map) {
                        if (inode->i_sb->u.isofs_sb.s_joliet_level) {
                        if (inode->i_sb->u.isofs_sb.s_joliet_level) {
                                len = get_joliet_filename(de, inode, tmpname);
                                len = get_joliet_filename(de, inode, tmpname);
                                p = tmpname;
                                p = tmpname;
                        } else {
                        } else {
                                if (inode->i_sb->u.isofs_sb.s_mapping == 'n') {
                                if (inode->i_sb->u.isofs_sb.s_mapping == 'n') {
                                        len = isofs_name_translate(de->name, de->name_len[0],
                                        len = isofs_name_translate(de->name, de->name_len[0],
                                                                   tmpname);
                                                                   tmpname);
                                        p = tmpname;
                                        p = tmpname;
                                } else {
                                } else {
                                        p = de->name;
                                        p = de->name;
                                        len = de->name_len[0];
                                        len = de->name_len[0];
                                }
                                }
                        }
                        }
                }
                }
                if (len > 0) {
                if (len > 0) {
                        if (filldir(dirent, p, len, filp->f_pos, inode_number) < 0)
                        if (filldir(dirent, p, len, filp->f_pos, inode_number) < 0)
                                break;
                                break;
 
 
                        dcache_add(inode, p, len, inode_number);
                        dcache_add(inode, p, len, inode_number);
                }
                }
                filp->f_pos += de_len;
                filp->f_pos += de_len;
                continue;
                continue;
        }
        }
        brelse(bh);
        brelse(bh);
        return 0;
        return 0;
}
}
 
 
/*
/*
 * Handle allocation of temporary space for name translation and
 * Handle allocation of temporary space for name translation and
 * handling split directory entries.. The real work is done by
 * handling split directory entries.. The real work is done by
 * "do_isofs_readdir()".
 * "do_isofs_readdir()".
 */
 */
static int isofs_readdir(struct inode *inode, struct file *filp,
static int isofs_readdir(struct inode *inode, struct file *filp,
                void *dirent, filldir_t filldir)
                void *dirent, filldir_t filldir)
{
{
        int result;
        int result;
        char * tmpname;
        char * tmpname;
        struct iso_directory_record * tmpde;
        struct iso_directory_record * tmpde;
 
 
        if (!inode || !S_ISDIR(inode->i_mode))
        if (!inode || !S_ISDIR(inode->i_mode))
                return -EBADF;
                return -EBADF;
 
 
        tmpname = (char *) __get_free_page(GFP_KERNEL);
        tmpname = (char *) __get_free_page(GFP_KERNEL);
        if (!tmpname)
        if (!tmpname)
                return -ENOMEM;
                return -ENOMEM;
        tmpde = (struct iso_directory_record *) (tmpname+1024);
        tmpde = (struct iso_directory_record *) (tmpname+1024);
 
 
        result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde);
        result = do_isofs_readdir(inode, filp, dirent, filldir, tmpname, tmpde);
 
 
        free_page((unsigned long) tmpname);
        free_page((unsigned long) tmpname);
        return result;
        return result;
}
}
 
 

powered by: WebSVN 2.1.0

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