URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [affs/] [amigaffs.c] - Rev 1628
Go to most recent revision | Compare with Previous | Blame | View Log
/* * linux/fs/affs/amigaffs.c * * (c) 1996 Hans-Joachim Widmaier - Rewritten * * (C) 1993 Ray Burr - Amiga FFS filesystem. * */ #include <linux/stat.h> #include <linux/sched.h> #include <linux/affs_fs.h> #include <linux/string.h> #include <linux/locks.h> #include <linux/mm.h> #include <linux/amigaffs.h> extern struct timezone sys_tz; /* * Functions for accessing Amiga-FFS structures. * */ /* 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 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 is returned. */ int affs_find_next_hash_entry(int hsize, void *dir_data, int *hash_pos) { struct dir_front *dir_front = dir_data; int i; for (i = *hash_pos; i < hsize; i++) if (dir_front->hashtable[i] != 0) break; if (i >= hsize) return 0; *hash_pos = i; return htonl(dir_front->hashtable[i]); } /* 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. */ int affs_get_file_name(int bsize, void *fh_data, char **name) { struct file_end *file_end; file_end = GET_END_PTR(struct file_end, fh_data, bsize); if (file_end->file_name[0] == 0 || file_end->file_name[0] > 30) { printk ("affs_get_file_name: OOPS! bad filename\n"); printk (" file_end->file_name[0] = %d\n", file_end->file_name[0]); *name = "***BAD_FILE***"; return 14; } *name = (char *) &file_end->file_name[1]; return file_end->file_name[0]; } /* Find the predecessor in the hash chain */ int affs_fix_hash_pred(struct inode *startino, int startoffset, int key, int newkey) { struct buffer_head *bh = NULL; int nextkey; int ptype, stype; int retval; nextkey = startino->i_ino; retval = -ENOENT; lock_super(startino->i_sb); while (1) { pr_debug("AFFS: fix_hash_pred(): next key=%d, offset=%d\n",nextkey,startoffset); if (nextkey == 0) break; if (!(bh = affs_bread(startino->i_dev,nextkey,AFFS_I2BSIZE(startino)))) break; if (affs_checksum_block(AFFS_I2BSIZE(startino),bh->b_data,&ptype,&stype) || ptype != T_SHORT || (stype != ST_FILE && stype != ST_USERDIR && stype != ST_LINKFILE && stype != ST_LINKDIR && stype != ST_ROOT && stype != ST_SOFTLINK)) { printk("AFFS: bad block found in link chain (ptype=%d, stype=%d)\n", ptype,stype); affs_brelse(bh); break; } nextkey = htonl(((__u32 *)bh->b_data)[startoffset]); if (nextkey == key) { ((__u32 *)bh->b_data)[startoffset] = newkey; affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5); mark_buffer_dirty(bh,1); affs_brelse(bh); retval = 0; break; } affs_brelse(bh); startoffset = AFFS_I2BSIZE(startino) / 4 - 4; } unlock_super(startino->i_sb); return retval; } /* Remove inode from link chain */ int affs_fix_link_pred(struct inode *startino, int key, int newkey) { struct buffer_head *bh = NULL; int nextkey; int offset; int etype = 0; int ptype, stype; int retval; offset = AFFS_I2BSIZE(startino) / 4 - 10; nextkey = startino->i_ino; retval = -ENOENT; lock_super(startino->i_sb); while (1) { if (nextkey == 0) break; pr_debug("AFFS: find_link_pred(): next key=%d\n",nextkey); if (!(bh = affs_bread(startino->i_dev,nextkey,AFFS_I2BSIZE(startino)))) break; if (affs_checksum_block(AFFS_I2BSIZE(startino),bh->b_data,&ptype,&stype) || ptype != T_SHORT) { affs_brelse(bh); break; } if (!etype) { if (stype != ST_FILE && stype != ST_USERDIR) { affs_brelse(bh); break; } if (stype == ST_FILE) etype = ST_LINKFILE; else etype = ST_LINKDIR; } else if (stype != etype) { affs_brelse(bh); retval = -EPERM; break; } nextkey = htonl(((__u32 *)bh->b_data)[offset]); if (nextkey == key) { FILE_END(bh->b_data,startino)->link_chain = newkey; affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5); mark_buffer_dirty(bh,1); affs_brelse(bh); retval = 0; break; } affs_brelse(bh); } unlock_super(startino->i_sb); return retval; } /* Checksum a block, do various consistency checks and optionally return 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 block types respectively, *HASHSIZE is set to the size of the hashtable (which lets us calculate the block size). Returns non-zero if the block is not consistent. */ __u32 affs_checksum_block(int bsize, void *data, int *ptype, int *stype) { __u32 sum; __u32 *p; bsize /= 4; if (ptype) *ptype = htonl(((__s32 *)data)[0]); if (stype) *stype = htonl(((__s32 *)data)[bsize - 1]); sum = 0; p = data; while (bsize--) sum += htonl(*p++); return sum; } void affs_fix_checksum(int bsize, void *data, int cspos) { __u32 ocs; __u32 cs; cs = affs_checksum_block(bsize,data,NULL,NULL); ocs = htonl (((__u32 *)data)[cspos]); ocs -= cs; ((__u32 *)data)[cspos] = htonl(ocs); } void secs_to_datestamp(int secs, struct DateStamp *ds) { __u32 days; __u32 minute; secs -= sys_tz.tz_minuteswest * 60 +((8 * 365 + 2) * 24 * 60 * 60); if (secs < 0) secs = 0; days = secs / 86400; secs -= days * 86400; minute = secs / 60; secs -= minute * 60; ds->ds_Days = htonl(days); ds->ds_Minute = htonl(minute); ds->ds_Tick = htonl(secs * 50); } int prot_to_mode(__u32 prot) { int mode = 0; if (AFFS_UMAYWRITE(prot)) mode |= S_IWUSR; if (AFFS_UMAYREAD(prot)) mode |= S_IRUSR; if (AFFS_UMAYEXECUTE(prot)) mode |= S_IXUSR; if (AFFS_GMAYWRITE(prot)) mode |= S_IWGRP; if (AFFS_GMAYREAD(prot)) mode |= S_IRGRP; if (AFFS_GMAYEXECUTE(prot)) mode |= S_IXGRP; if (AFFS_OMAYWRITE(prot)) mode |= S_IWOTH; if (AFFS_OMAYREAD(prot)) mode |= S_IROTH; if (AFFS_OMAYEXECUTE(prot)) mode |= S_IXOTH; return mode; } unsigned int mode_to_prot(int mode) { unsigned int prot = 0; if (mode & S_IXUSR) prot |= FIBF_SCRIPT; if (mode & S_IRUSR) prot |= FIBF_READ; if (mode & S_IWUSR) prot |= FIBF_WRITE | FIBF_DELETE; if (mode & S_IRGRP) prot |= FIBF_GRP_READ; if (mode & S_IWGRP) prot |= FIBF_GRP_WRITE; if (mode & S_IROTH) prot |= FIBF_OTR_READ; if (mode & S_IWOTH) prot |= FIBF_OTR_WRITE; return prot; }
Go to most recent revision | Compare with Previous | Blame | View Log