root/fs/affs/amigaffs.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. affs_find_next_hash_entry
  2. affs_get_file_name
  3. affs_fix_hash_pred
  4. affs_fix_link_pred
  5. affs_checksum_block
  6. affs_fix_checksum
  7. secs_to_datestamp
  8. prot_to_mode
  9. mode_to_prot

   1 /*
   2  *  linux/fs/affs/amigaffs.c
   3  *
   4  *  (c) 1996  Hans-Joachim Widmaier - Modified for larger blocks.
   5  *
   6  *  (C) 1993  Ray Burr - Amiga FFS filesystem.
   7  *
   8  */
   9 
  10 #include <linux/stat.h>
  11 #include <linux/sched.h>
  12 #include <linux/affs_fs.h>
  13 #include <linux/string.h>
  14 #include <linux/locks.h>
  15 #include <linux/mm.h>
  16 #include <linux/amigaffs.h>
  17 
  18 extern struct timezone sys_tz;
  19 
  20 /*
  21  * Functions for accessing Amiga-FFS structures.
  22  *
  23  */
  24 
  25 /* Find the next used hash entry at or after *HASH_POS in a directory's hash
  26    table.  *HASH_POS is assigned that entry's number.  DIR_DATA points to
  27    the directory header block in memory.  If there are no more entries,
  28    0 is returned.  Otherwise, the key number in the next used hash slot
  29    is returned. */
  30 
  31 int
  32 affs_find_next_hash_entry(int hsize, void *dir_data, ULONG *hash_pos)
     /* [previous][next][first][last][top][bottom][index][help] */
  33 {
  34         struct dir_front *dir_front = dir_data;
  35         ULONG i;
  36 
  37         for (i = *hash_pos; i < hsize; i++)
  38                 if (dir_front->hashtable[i] != 0)
  39                         break;
  40         if (i >= hsize)
  41                 return 0;
  42         *hash_pos = i;
  43         return htonl(dir_front->hashtable[i]);
  44 }
  45 
  46 /* Set *NAME to point to the file name in a file header block in memory
  47    pointed to by FH_DATA.  The length of the name is returned. */
  48 
  49 int
  50 affs_get_file_name(int bsize, void *fh_data, char **name)
     /* [previous][next][first][last][top][bottom][index][help] */
  51 {
  52         struct file_end *file_end;
  53 
  54         file_end = GET_END_PTR(struct file_end, fh_data, bsize);
  55         if (file_end->file_name[0] == 0
  56             || file_end->file_name[0] > 30) {
  57                 printk ("affs_get_file_name: OOPS! bad filename\n");
  58                 printk ("  file_end->file_name[0] = %d\n",
  59                         file_end->file_name[0]);
  60                 *name = "***BAD_FILE***";
  61                 return 14;
  62         }
  63         *name = (char *) &file_end->file_name[1];
  64         return file_end->file_name[0];
  65 }
  66 
  67 /* Find the predecessor in the hash chain */
  68 
  69 int
  70 affs_fix_hash_pred(struct inode *startino, int startoffset, LONG key, LONG newkey)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72         struct buffer_head      *bh = NULL;
  73         ULONG                    nextkey;
  74         LONG                     ptype, stype;
  75         int                      retval;
  76 
  77         nextkey = startino->i_ino;
  78         retval  = -ENOENT;
  79         lock_super(startino->i_sb);
  80         while (1) {
  81                 pr_debug("AFFS: fix_hash_pred(): next key=%d, offset=%d\n", nextkey, startoffset);
  82                 if (nextkey == 0)
  83                         break;
  84                 if (!(bh = affs_bread(startino->i_dev,nextkey,AFFS_I2BSIZE(startino))))
  85                         break;
  86                 if (affs_checksum_block(AFFS_I2BSIZE(startino),bh->b_data,&ptype,&stype)
  87                     || ptype != T_SHORT || (stype != ST_FILE && stype != ST_USERDIR &&
  88                                             stype != ST_LINKFILE && stype != ST_LINKDIR &&
  89                                             stype != ST_ROOT && stype != ST_SOFTLINK)) {
  90                         printk("AFFS: bad block found in link chain (ptype=%d, stype=%d)\n",
  91                                ptype,stype);
  92                         affs_brelse(bh);
  93                         break;
  94                 }
  95                 nextkey = htonl(((ULONG *)bh->b_data)[startoffset]);
  96                 if (nextkey == key) {
  97                         ((ULONG *)bh->b_data)[startoffset] = newkey;
  98                         affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5);
  99                         mark_buffer_dirty(bh,1);
 100                         affs_brelse(bh);
 101                         retval = 0;
 102                         break;
 103                 }
 104                 affs_brelse(bh);
 105                 startoffset = AFFS_I2BSIZE(startino) / 4 - 4;
 106         }
 107         unlock_super(startino->i_sb);
 108 
 109         return retval;
 110 }
 111 
 112 /* Remove inode from link chain */
 113 
 114 int
 115 affs_fix_link_pred(struct inode *startino, LONG key, LONG newkey)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117         struct buffer_head      *bh = NULL;
 118         ULONG                    nextkey;
 119         ULONG                    offset;
 120         LONG                     etype = 0;
 121         LONG                     ptype, stype;
 122         int                      retval;
 123 
 124         offset  = AFFS_I2BSIZE(startino) / 4 - 10;
 125         nextkey = startino->i_ino;
 126         retval  = -ENOENT;
 127         lock_super(startino->i_sb);
 128         while (1) {
 129                 if (nextkey == 0)
 130                         break;
 131                 pr_debug("AFFS: find_link_pred(): next key=%d\n", nextkey));
 132                 if (!(bh = affs_bread(startino->i_dev,nextkey,AFFS_I2BSIZE(startino))))
 133                         break;
 134                 if (affs_checksum_block(AFFS_I2BSIZE(startino),bh->b_data,&ptype,&stype)
 135                     || ptype != T_SHORT) {
 136                         affs_brelse(bh);
 137                         break;
 138                 }
 139                 if (!etype) {
 140                         if (stype != ST_FILE && stype != ST_USERDIR) {
 141                                 affs_brelse(bh);
 142                                 break;
 143                         }
 144                         if (stype == ST_FILE)
 145                                 etype = ST_LINKFILE;
 146                         else
 147                                 etype = ST_LINKDIR;
 148                 } else if (stype != etype) {
 149                         affs_brelse(bh);
 150                         retval = -EPERM;
 151                         break;
 152                 }
 153                 nextkey = htonl(((ULONG *)bh->b_data)[offset]);
 154                 if (nextkey == key) {
 155                         FILE_END(bh->b_data,startino)->link_chain = newkey;
 156                         affs_fix_checksum(AFFS_I2BSIZE(startino),bh->b_data,5);
 157                         mark_buffer_dirty(bh,1);
 158                         affs_brelse(bh);
 159                         retval = 0;
 160                         break;
 161                 }
 162                 affs_brelse(bh);
 163         }
 164         unlock_super(startino->i_sb);
 165         return retval;
 166 }
 167 
 168 /* Checksum a block, do various consistency checks and optionally return
 169    the blocks type number.  DATA points to the block.  If their pointers
 170    are non-null, *PTYPE and *STYPE are set to the primary and secondary
 171    block types respectively, *HASHSIZE is set to the size of the hashtable
 172    (which lets us calculate the block size).
 173    Returns non-zero if the block is not consistent. */
 174 
 175 ULONG
 176 affs_checksum_block(int bsize, void *data, LONG *ptype, LONG *stype)
     /* [previous][next][first][last][top][bottom][index][help] */
 177 {
 178         ULONG sum;
 179         ULONG *p;
 180 
 181         bsize /= 4;
 182         if (ptype)
 183                 *ptype = htonl(((LONG *)data)[0]);
 184         if (stype)
 185                 *stype = htonl(((LONG *)data)[bsize - 1]);
 186 
 187         sum    = 0;
 188         p      = data;
 189         while (bsize--)
 190                 sum += htonl(*p++);
 191         return sum;
 192 }
 193 
 194 void
 195 affs_fix_checksum(int bsize, void *data, int cspos)
     /* [previous][next][first][last][top][bottom][index][help] */
 196 {
 197         ULONG    ocs;
 198         ULONG    cs;
 199 
 200         cs   = affs_checksum_block(bsize,data,NULL,NULL);
 201         ocs  = htonl (((ULONG *)data)[cspos]);
 202         ocs -= cs;
 203         ((ULONG *)data)[cspos] = htonl(ocs);
 204 }
 205 
 206 void
 207 secs_to_datestamp(int secs, struct DateStamp *ds)
     /* [previous][next][first][last][top][bottom][index][help] */
 208 {
 209         ULONG    days;
 210         ULONG    minute;
 211 
 212         secs -= sys_tz.tz_minuteswest * 60 +((8 * 365 + 2) * 24 * 60 * 60);
 213         if (secs < 0)
 214                 secs = 0;
 215         days    = secs / 86400;
 216         secs   -= days * 86400;
 217         minute  = secs / 60;
 218         secs   -= minute * 60;
 219 
 220         ds->ds_Days   = htonl(days);
 221         ds->ds_Minute = htonl(minute);
 222         ds->ds_Tick   = htonl(secs * 50);
 223 }
 224 
 225 int
 226 prot_to_mode(ULONG prot)
     /* [previous][next][first][last][top][bottom][index][help] */
 227 {
 228         int      mode = 0;
 229 
 230         if (AFFS_UMAYWRITE(prot))
 231                 mode |= S_IWUSR;
 232         if (AFFS_UMAYREAD(prot))
 233                 mode |= S_IRUSR;
 234         if (AFFS_UMAYEXECUTE(prot))
 235                 mode |= S_IXUSR;
 236         if (AFFS_GMAYWRITE(prot))
 237                 mode |= S_IWGRP;
 238         if (AFFS_GMAYREAD(prot))
 239                 mode |= S_IRGRP;
 240         if (AFFS_GMAYEXECUTE(prot))
 241                 mode |= S_IXGRP;
 242         if (AFFS_OMAYWRITE(prot))
 243                 mode |= S_IWOTH;
 244         if (AFFS_OMAYREAD(prot))
 245                 mode |= S_IROTH;
 246         if (AFFS_OMAYEXECUTE(prot))
 247                 mode |= S_IXOTH;
 248         
 249         return mode;
 250 }
 251 
 252 ULONG
 253 mode_to_prot(int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 254 {
 255         ULONG    prot = 0;
 256 
 257         if (mode & S_IXUSR)
 258                 prot |= FIBF_SCRIPT;
 259         if (mode & S_IRUSR)
 260                 prot |= FIBF_READ;
 261         if (mode & S_IWUSR)
 262                 prot |= FIBF_WRITE | FIBF_DELETE;
 263         if (mode & S_IRGRP)
 264                 prot |= FIBF_GRP_READ;
 265         if (mode & S_IWGRP)
 266                 prot |= FIBF_GRP_WRITE;
 267         if (mode & S_IROTH)
 268                 prot |= FIBF_OTR_READ;
 269         if (mode & S_IWOTH)
 270                 prot |= FIBF_OTR_WRITE;
 271         
 272         return prot;
 273 }

/* [previous][next][first][last][top][bottom][index][help] */