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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [affs/] [amigaffs.c] - Diff between revs 1765 and 1782

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

Rev 1765 Rev 1782
/*
/*
 *  linux/fs/affs/amigaffs.c
 *  linux/fs/affs/amigaffs.c
 *
 *
 *  (c) 1996  Hans-Joachim Widmaier - Rewritten
 *  (c) 1996  Hans-Joachim Widmaier - Rewritten
 *
 *
 *  (C) 1993  Ray Burr - Amiga FFS filesystem.
 *  (C) 1993  Ray Burr - Amiga FFS filesystem.
 *
 *
 */
 */
 
 
#include <linux/stat.h>
#include <linux/stat.h>
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/affs_fs.h>
#include <linux/affs_fs.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/locks.h>
#include <linux/locks.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/amigaffs.h>
#include <linux/amigaffs.h>
 
 
extern struct timezone sys_tz;
extern struct timezone sys_tz;
 
 
/*
/*
 * Functions for accessing Amiga-FFS structures.
 * Functions for accessing Amiga-FFS structures.
 *
 *
 */
 */
 
 
/* Find the next used hash entry at or after *HASH_POS in a directory's hash
/* Find the next used hash entry at or after *HASH_POS in a directory's hash
   table.  *HASH_POS is assigned that entry's number.  DIR_DATA points to
   table.  *HASH_POS is assigned that entry's number.  DIR_DATA points to
   the directory header block in memory.  If there are no more entries,
   the directory header block in memory.  If there are no more entries,
   0 is returned.  Otherwise, the key number in the next used hash slot
   0 is returned.  Otherwise, the key number in the next used hash slot
   is returned. */
   is returned. */
 
 
int
int
affs_find_next_hash_entry(int hsize, void *dir_data, int *hash_pos)
affs_find_next_hash_entry(int hsize, void *dir_data, int *hash_pos)
{
{
        struct dir_front *dir_front = dir_data;
        struct dir_front *dir_front = dir_data;
        int i;
        int i;
 
 
        for (i = *hash_pos; i < hsize; i++)
        for (i = *hash_pos; i < hsize; i++)
                if (dir_front->hashtable[i] != 0)
                if (dir_front->hashtable[i] != 0)
                        break;
                        break;
        if (i >= hsize)
        if (i >= hsize)
                return 0;
                return 0;
        *hash_pos = i;
        *hash_pos = i;
        return htonl(dir_front->hashtable[i]);
        return htonl(dir_front->hashtable[i]);
}
}
 
 
/* Set *NAME to point to the file name in a file header block in memory
/* Set *NAME to point to the file name in a file header block in memory
   pointed to by FH_DATA.  The length of the name is returned. */
   pointed to by FH_DATA.  The length of the name is returned. */
 
 
int
int
affs_get_file_name(int bsize, void *fh_data, char **name)
affs_get_file_name(int bsize, void *fh_data, char **name)
{
{
        struct file_end *file_end;
        struct file_end *file_end;
 
 
        file_end = GET_END_PTR(struct file_end, fh_data, bsize);
        file_end = GET_END_PTR(struct file_end, fh_data, bsize);
        if (file_end->file_name[0] == 0
        if (file_end->file_name[0] == 0
            || file_end->file_name[0] > 30) {
            || file_end->file_name[0] > 30) {
                printk ("affs_get_file_name: OOPS! bad filename\n");
                printk ("affs_get_file_name: OOPS! bad filename\n");
                printk ("  file_end->file_name[0] = %d\n",
                printk ("  file_end->file_name[0] = %d\n",
                        file_end->file_name[0]);
                        file_end->file_name[0]);
                *name = "***BAD_FILE***";
                *name = "***BAD_FILE***";
                return 14;
                return 14;
        }
        }
        *name = (char *) &file_end->file_name[1];
        *name = (char *) &file_end->file_name[1];
        return file_end->file_name[0];
        return file_end->file_name[0];
}
}
 
 
/* Find the predecessor in the hash chain */
/* Find the predecessor in the hash chain */
 
 
int
int
affs_fix_hash_pred(struct inode *startino, int startoffset, int key, int newkey)
affs_fix_hash_pred(struct inode *startino, int startoffset, int key, int newkey)
{
{
        struct buffer_head      *bh = NULL;
        struct buffer_head      *bh = NULL;
        int                      nextkey;
        int                      nextkey;
        int                      ptype, stype;
        int                      ptype, stype;
        int                      retval;
        int                      retval;
 
 
        nextkey = startino->i_ino;
        nextkey = startino->i_ino;
        retval  = -ENOENT;
        retval  = -ENOENT;
        lock_super(startino->i_sb);
        lock_super(startino->i_sb);
        while (1) {
        while (1) {
                pr_debug("AFFS: fix_hash_pred(): next key=%d, offset=%d\n",nextkey,startoffset);
                pr_debug("AFFS: fix_hash_pred(): next key=%d, offset=%d\n",nextkey,startoffset);
                if (nextkey == 0)
                if (nextkey == 0)
                        break;
                        break;
                if (!(bh = affs_bread(startino->i_dev,nextkey,AFFS_I2BSIZE(startino))))
                if (!(bh = affs_bread(startino->i_dev,nextkey,AFFS_I2BSIZE(startino))))
                        break;
                        break;
                if (affs_checksum_block(AFFS_I2BSIZE(startino),bh->b_data,&ptype,&stype)
                if (affs_checksum_block(AFFS_I2BSIZE(startino),bh->b_data,&ptype,&stype)
                    || ptype != T_SHORT || (stype != ST_FILE && stype != ST_USERDIR &&
                    || ptype != T_SHORT || (stype != ST_FILE && stype != ST_USERDIR &&
                                            stype != ST_LINKFILE && stype != ST_LINKDIR &&
                                            stype != ST_LINKFILE && stype != ST_LINKDIR &&
                                            stype != ST_ROOT && stype != ST_SOFTLINK)) {
                                            stype != ST_ROOT && stype != ST_SOFTLINK)) {
                        printk("AFFS: bad block found in link chain (ptype=%d, stype=%d)\n",
                        printk("AFFS: bad block found in link chain (ptype=%d, stype=%d)\n",
                               ptype,stype);
                               ptype,stype);
                        affs_brelse(bh);
                        affs_brelse(bh);
                        break;
                        break;
                }
                }
                nextkey = htonl(((__u32 *)bh->b_data)[startoffset]);
                nextkey = htonl(((__u32 *)bh->b_data)[startoffset]);
                if (nextkey == key) {
                if (nextkey == key) {
                        ((__u32 *)bh->b_data)[startoffset] = newkey;
                        ((__u32 *)bh->b_data)[startoffset] = newkey;
                        affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5);
                        affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5);
                        mark_buffer_dirty(bh,1);
                        mark_buffer_dirty(bh,1);
                        affs_brelse(bh);
                        affs_brelse(bh);
                        retval = 0;
                        retval = 0;
                        break;
                        break;
                }
                }
                affs_brelse(bh);
                affs_brelse(bh);
                startoffset = AFFS_I2BSIZE(startino) / 4 - 4;
                startoffset = AFFS_I2BSIZE(startino) / 4 - 4;
        }
        }
        unlock_super(startino->i_sb);
        unlock_super(startino->i_sb);
 
 
        return retval;
        return retval;
}
}
 
 
/* Remove inode from link chain */
/* Remove inode from link chain */
 
 
int
int
affs_fix_link_pred(struct inode *startino, int key, int newkey)
affs_fix_link_pred(struct inode *startino, int key, int newkey)
{
{
        struct buffer_head      *bh = NULL;
        struct buffer_head      *bh = NULL;
        int                      nextkey;
        int                      nextkey;
        int                      offset;
        int                      offset;
        int                      etype = 0;
        int                      etype = 0;
        int                      ptype, stype;
        int                      ptype, stype;
        int                      retval;
        int                      retval;
 
 
        offset  = AFFS_I2BSIZE(startino) / 4 - 10;
        offset  = AFFS_I2BSIZE(startino) / 4 - 10;
        nextkey = startino->i_ino;
        nextkey = startino->i_ino;
        retval  = -ENOENT;
        retval  = -ENOENT;
        lock_super(startino->i_sb);
        lock_super(startino->i_sb);
        while (1) {
        while (1) {
                if (nextkey == 0)
                if (nextkey == 0)
                        break;
                        break;
                pr_debug("AFFS: find_link_pred(): next key=%d\n",nextkey);
                pr_debug("AFFS: find_link_pred(): next key=%d\n",nextkey);
                if (!(bh = affs_bread(startino->i_dev,nextkey,AFFS_I2BSIZE(startino))))
                if (!(bh = affs_bread(startino->i_dev,nextkey,AFFS_I2BSIZE(startino))))
                        break;
                        break;
                if (affs_checksum_block(AFFS_I2BSIZE(startino),bh->b_data,&ptype,&stype)
                if (affs_checksum_block(AFFS_I2BSIZE(startino),bh->b_data,&ptype,&stype)
                    || ptype != T_SHORT) {
                    || ptype != T_SHORT) {
                        affs_brelse(bh);
                        affs_brelse(bh);
                        break;
                        break;
                }
                }
                if (!etype) {
                if (!etype) {
                        if (stype != ST_FILE && stype != ST_USERDIR) {
                        if (stype != ST_FILE && stype != ST_USERDIR) {
                                affs_brelse(bh);
                                affs_brelse(bh);
                                break;
                                break;
                        }
                        }
                        if (stype == ST_FILE)
                        if (stype == ST_FILE)
                                etype = ST_LINKFILE;
                                etype = ST_LINKFILE;
                        else
                        else
                                etype = ST_LINKDIR;
                                etype = ST_LINKDIR;
                } else if (stype != etype) {
                } else if (stype != etype) {
                        affs_brelse(bh);
                        affs_brelse(bh);
                        retval = -EPERM;
                        retval = -EPERM;
                        break;
                        break;
                }
                }
                nextkey = htonl(((__u32 *)bh->b_data)[offset]);
                nextkey = htonl(((__u32 *)bh->b_data)[offset]);
                if (nextkey == key) {
                if (nextkey == key) {
                        FILE_END(bh->b_data,startino)->link_chain = newkey;
                        FILE_END(bh->b_data,startino)->link_chain = newkey;
                        affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5);
                        affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5);
                        mark_buffer_dirty(bh,1);
                        mark_buffer_dirty(bh,1);
                        affs_brelse(bh);
                        affs_brelse(bh);
                        retval = 0;
                        retval = 0;
                        break;
                        break;
                }
                }
                affs_brelse(bh);
                affs_brelse(bh);
        }
        }
        unlock_super(startino->i_sb);
        unlock_super(startino->i_sb);
        return retval;
        return retval;
}
}
 
 
/* Checksum a block, do various consistency checks and optionally return
/* Checksum a block, do various consistency checks and optionally return
   the blocks type number.  DATA points to the block.  If their pointers
   the blocks type number.  DATA points to the block.  If their pointers
   are non-null, *PTYPE and *STYPE are set to the primary and secondary
   are non-null, *PTYPE and *STYPE are set to the primary and secondary
   block types respectively, *HASHSIZE is set to the size of the hashtable
   block types respectively, *HASHSIZE is set to the size of the hashtable
   (which lets us calculate the block size).
   (which lets us calculate the block size).
   Returns non-zero if the block is not consistent. */
   Returns non-zero if the block is not consistent. */
 
 
__u32
__u32
affs_checksum_block(int bsize, void *data, int *ptype, int *stype)
affs_checksum_block(int bsize, void *data, int *ptype, int *stype)
{
{
        __u32    sum;
        __u32    sum;
        __u32   *p;
        __u32   *p;
 
 
        bsize /= 4;
        bsize /= 4;
        if (ptype)
        if (ptype)
                *ptype = htonl(((__s32 *)data)[0]);
                *ptype = htonl(((__s32 *)data)[0]);
        if (stype)
        if (stype)
                *stype = htonl(((__s32 *)data)[bsize - 1]);
                *stype = htonl(((__s32 *)data)[bsize - 1]);
 
 
        sum    = 0;
        sum    = 0;
        p      = data;
        p      = data;
        while (bsize--)
        while (bsize--)
                sum += htonl(*p++);
                sum += htonl(*p++);
        return sum;
        return sum;
}
}
 
 
void
void
affs_fix_checksum(int bsize, void *data, int cspos)
affs_fix_checksum(int bsize, void *data, int cspos)
{
{
        __u32    ocs;
        __u32    ocs;
        __u32    cs;
        __u32    cs;
 
 
        cs   = affs_checksum_block(bsize,data,NULL,NULL);
        cs   = affs_checksum_block(bsize,data,NULL,NULL);
        ocs  = htonl (((__u32 *)data)[cspos]);
        ocs  = htonl (((__u32 *)data)[cspos]);
        ocs -= cs;
        ocs -= cs;
        ((__u32 *)data)[cspos] = htonl(ocs);
        ((__u32 *)data)[cspos] = htonl(ocs);
}
}
 
 
void
void
secs_to_datestamp(int secs, struct DateStamp *ds)
secs_to_datestamp(int secs, struct DateStamp *ds)
{
{
        __u32    days;
        __u32    days;
        __u32    minute;
        __u32    minute;
 
 
        secs -= sys_tz.tz_minuteswest * 60 +((8 * 365 + 2) * 24 * 60 * 60);
        secs -= sys_tz.tz_minuteswest * 60 +((8 * 365 + 2) * 24 * 60 * 60);
        if (secs < 0)
        if (secs < 0)
                secs = 0;
                secs = 0;
        days    = secs / 86400;
        days    = secs / 86400;
        secs   -= days * 86400;
        secs   -= days * 86400;
        minute  = secs / 60;
        minute  = secs / 60;
        secs   -= minute * 60;
        secs   -= minute * 60;
 
 
        ds->ds_Days   = htonl(days);
        ds->ds_Days   = htonl(days);
        ds->ds_Minute = htonl(minute);
        ds->ds_Minute = htonl(minute);
        ds->ds_Tick   = htonl(secs * 50);
        ds->ds_Tick   = htonl(secs * 50);
}
}
 
 
int
int
prot_to_mode(__u32 prot)
prot_to_mode(__u32 prot)
{
{
        int      mode = 0;
        int      mode = 0;
 
 
        if (AFFS_UMAYWRITE(prot))
        if (AFFS_UMAYWRITE(prot))
                mode |= S_IWUSR;
                mode |= S_IWUSR;
        if (AFFS_UMAYREAD(prot))
        if (AFFS_UMAYREAD(prot))
                mode |= S_IRUSR;
                mode |= S_IRUSR;
        if (AFFS_UMAYEXECUTE(prot))
        if (AFFS_UMAYEXECUTE(prot))
                mode |= S_IXUSR;
                mode |= S_IXUSR;
        if (AFFS_GMAYWRITE(prot))
        if (AFFS_GMAYWRITE(prot))
                mode |= S_IWGRP;
                mode |= S_IWGRP;
        if (AFFS_GMAYREAD(prot))
        if (AFFS_GMAYREAD(prot))
                mode |= S_IRGRP;
                mode |= S_IRGRP;
        if (AFFS_GMAYEXECUTE(prot))
        if (AFFS_GMAYEXECUTE(prot))
                mode |= S_IXGRP;
                mode |= S_IXGRP;
        if (AFFS_OMAYWRITE(prot))
        if (AFFS_OMAYWRITE(prot))
                mode |= S_IWOTH;
                mode |= S_IWOTH;
        if (AFFS_OMAYREAD(prot))
        if (AFFS_OMAYREAD(prot))
                mode |= S_IROTH;
                mode |= S_IROTH;
        if (AFFS_OMAYEXECUTE(prot))
        if (AFFS_OMAYEXECUTE(prot))
                mode |= S_IXOTH;
                mode |= S_IXOTH;
 
 
        return mode;
        return mode;
}
}
 
 
unsigned int
unsigned int
mode_to_prot(int mode)
mode_to_prot(int mode)
{
{
        unsigned int     prot = 0;
        unsigned int     prot = 0;
 
 
        if (mode & S_IXUSR)
        if (mode & S_IXUSR)
                prot |= FIBF_SCRIPT;
                prot |= FIBF_SCRIPT;
        if (mode & S_IRUSR)
        if (mode & S_IRUSR)
                prot |= FIBF_READ;
                prot |= FIBF_READ;
        if (mode & S_IWUSR)
        if (mode & S_IWUSR)
                prot |= FIBF_WRITE | FIBF_DELETE;
                prot |= FIBF_WRITE | FIBF_DELETE;
        if (mode & S_IRGRP)
        if (mode & S_IRGRP)
                prot |= FIBF_GRP_READ;
                prot |= FIBF_GRP_READ;
        if (mode & S_IWGRP)
        if (mode & S_IWGRP)
                prot |= FIBF_GRP_WRITE;
                prot |= FIBF_GRP_WRITE;
        if (mode & S_IROTH)
        if (mode & S_IROTH)
                prot |= FIBF_OTR_READ;
                prot |= FIBF_OTR_READ;
        if (mode & S_IWOTH)
        if (mode & S_IWOTH)
                prot |= FIBF_OTR_WRITE;
                prot |= FIBF_OTR_WRITE;
 
 
        return prot;
        return prot;
}
}
 
 

powered by: WebSVN 2.1.0

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