Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #include <linux/buffer_head.h>
0003 #include <linux/fs.h>
0004 #include <linux/adfs_fs.h>
0005 
0006 /* Internal data structures for ADFS */
0007 
0008 #define ADFS_FREE_FRAG       0
0009 #define ADFS_BAD_FRAG        1
0010 #define ADFS_ROOT_FRAG       2
0011 
0012 #define ADFS_FILETYPE_NONE  ((u16)~0)
0013 
0014 /* RISC OS 12-bit filetype is stored in load_address[19:8] */
0015 static inline u16 adfs_filetype(u32 loadaddr)
0016 {
0017     return (loadaddr & 0xfff00000) == 0xfff00000 ?
0018            (loadaddr >> 8) & 0xfff : ADFS_FILETYPE_NONE;
0019 }
0020 
0021 #define ADFS_NDA_OWNER_READ (1 << 0)
0022 #define ADFS_NDA_OWNER_WRITE    (1 << 1)
0023 #define ADFS_NDA_LOCKED     (1 << 2)
0024 #define ADFS_NDA_DIRECTORY  (1 << 3)
0025 #define ADFS_NDA_EXECUTE    (1 << 4)
0026 #define ADFS_NDA_PUBLIC_READ    (1 << 5)
0027 #define ADFS_NDA_PUBLIC_WRITE   (1 << 6)
0028 
0029 /*
0030  * adfs file system inode data in memory
0031  */
0032 struct adfs_inode_info {
0033     loff_t      mmu_private;
0034     __u32       parent_id;  /* parent indirect disc address */
0035     __u32       indaddr;    /* object indirect disc address */
0036     __u32       loadaddr;   /* RISC OS load address     */
0037     __u32       execaddr;   /* RISC OS exec address     */
0038     unsigned int    attr;       /* RISC OS permissions      */
0039     struct inode vfs_inode;
0040 };
0041 
0042 static inline struct adfs_inode_info *ADFS_I(struct inode *inode)
0043 {
0044     return container_of(inode, struct adfs_inode_info, vfs_inode);
0045 }
0046 
0047 static inline bool adfs_inode_is_stamped(struct inode *inode)
0048 {
0049     return (ADFS_I(inode)->loadaddr & 0xfff00000) == 0xfff00000;
0050 }
0051 
0052 /*
0053  * Forward-declare this
0054  */
0055 struct adfs_discmap;
0056 struct adfs_dir_ops;
0057 
0058 /*
0059  * ADFS file system superblock data in memory
0060  */
0061 struct adfs_sb_info {
0062     union { struct {
0063         struct adfs_discmap *s_map; /* bh list containing map */
0064         const struct adfs_dir_ops *s_dir; /* directory operations */
0065         };
0066         struct rcu_head rcu;    /* used only at shutdown time    */
0067     };
0068     kuid_t      s_uid;      /* owner uid */
0069     kgid_t      s_gid;      /* owner gid */
0070     umode_t     s_owner_mask;   /* ADFS owner perm -> unix perm */
0071     umode_t     s_other_mask;   /* ADFS other perm -> unix perm */
0072     int     s_ftsuffix; /* ,xyz hex filetype suffix option */
0073 
0074     __u32       s_ids_per_zone; /* max. no ids in one zone */
0075     __u32       s_idlen;    /* length of ID in map */
0076     __u32       s_map_size; /* sector size of a map */
0077     signed int  s_map2blk;  /* shift left by this for map->sector*/
0078     unsigned int    s_log2sharesize;/* log2 share size */
0079     unsigned int    s_namelen;  /* maximum number of characters in name  */
0080 };
0081 
0082 static inline struct adfs_sb_info *ADFS_SB(struct super_block *sb)
0083 {
0084     return sb->s_fs_info;
0085 }
0086 
0087 /*
0088  * Directory handling
0089  */
0090 struct adfs_dir {
0091     struct super_block  *sb;
0092 
0093     int         nr_buffers;
0094     struct buffer_head  *bh[4];
0095     struct buffer_head  **bhs;
0096 
0097     unsigned int        pos;
0098     __u32           parent_id;
0099 
0100     union {
0101         struct adfs_dirheader   *dirhead;
0102         struct adfs_bigdirheader *bighead;
0103     };
0104     union {
0105         struct adfs_newdirtail  *newtail;
0106         struct adfs_bigdirtail  *bigtail;
0107     };
0108 };
0109 
0110 /*
0111  * This is the overall maximum name length
0112  */
0113 #define ADFS_MAX_NAME_LEN   (256 + 4) /* +4 for ,xyz hex filetype suffix */
0114 struct object_info {
0115     __u32       parent_id;      /* parent object id */
0116     __u32       indaddr;        /* indirect disc addr   */
0117     __u32       loadaddr;       /* load address     */
0118     __u32       execaddr;       /* execution address    */
0119     __u32       size;           /* size         */
0120     __u8        attr;           /* RISC OS attributes   */
0121     unsigned int    name_len;       /* name length      */
0122     char        name[ADFS_MAX_NAME_LEN];/* file name        */
0123 };
0124 
0125 struct adfs_dir_ops {
0126     int (*read)(struct super_block *sb, unsigned int indaddr,
0127             unsigned int size, struct adfs_dir *dir);
0128     int (*iterate)(struct adfs_dir *dir, struct dir_context *ctx);
0129     int (*setpos)(struct adfs_dir *dir, unsigned int fpos);
0130     int (*getnext)(struct adfs_dir *dir, struct object_info *obj);
0131     int (*update)(struct adfs_dir *dir, struct object_info *obj);
0132     int (*create)(struct adfs_dir *dir, struct object_info *obj);
0133     int (*remove)(struct adfs_dir *dir, struct object_info *obj);
0134     int (*commit)(struct adfs_dir *dir);
0135 };
0136 
0137 struct adfs_discmap {
0138     struct buffer_head  *dm_bh;
0139     __u32           dm_startblk;
0140     unsigned int        dm_startbit;
0141     unsigned int        dm_endbit;
0142 };
0143 
0144 /* Inode stuff */
0145 struct inode *adfs_iget(struct super_block *sb, struct object_info *obj);
0146 int adfs_write_inode(struct inode *inode, struct writeback_control *wbc);
0147 int adfs_notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
0148                struct iattr *attr);
0149 
0150 /* map.c */
0151 int adfs_map_lookup(struct super_block *sb, u32 frag_id, unsigned int offset);
0152 void adfs_map_statfs(struct super_block *sb, struct kstatfs *buf);
0153 struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_discrecord *dr);
0154 void adfs_free_map(struct super_block *sb);
0155 
0156 /* Misc */
0157 __printf(3, 4)
0158 void __adfs_error(struct super_block *sb, const char *function,
0159           const char *fmt, ...);
0160 #define adfs_error(sb, fmt...) __adfs_error(sb, __func__, fmt)
0161 void adfs_msg(struct super_block *sb, const char *pfx, const char *fmt, ...);
0162 
0163 /* super.c */
0164 
0165 /*
0166  * Inodes and file operations
0167  */
0168 
0169 /* dir_*.c */
0170 extern const struct inode_operations adfs_dir_inode_operations;
0171 extern const struct file_operations adfs_dir_operations;
0172 extern const struct dentry_operations adfs_dentry_operations;
0173 extern const struct adfs_dir_ops adfs_f_dir_ops;
0174 extern const struct adfs_dir_ops adfs_fplus_dir_ops;
0175 
0176 int adfs_dir_copyfrom(void *dst, struct adfs_dir *dir, unsigned int offset,
0177               size_t len);
0178 int adfs_dir_copyto(struct adfs_dir *dir, unsigned int offset, const void *src,
0179             size_t len);
0180 void adfs_dir_relse(struct adfs_dir *dir);
0181 int adfs_dir_read_buffers(struct super_block *sb, u32 indaddr,
0182               unsigned int size, struct adfs_dir *dir);
0183 void adfs_object_fixup(struct adfs_dir *dir, struct object_info *obj);
0184 extern int adfs_dir_update(struct super_block *sb, struct object_info *obj,
0185                int wait);
0186 
0187 /* file.c */
0188 extern const struct inode_operations adfs_file_inode_operations;
0189 extern const struct file_operations adfs_file_operations;
0190 
0191 static inline __u32 signed_asl(__u32 val, signed int shift)
0192 {
0193     if (shift >= 0)
0194         val <<= shift;
0195     else
0196         val >>= -shift;
0197     return val;
0198 }
0199 
0200 /*
0201  * Calculate the address of a block in an object given the block offset
0202  * and the object identity.
0203  *
0204  * The root directory ID should always be looked up in the map [3.4]
0205  */
0206 static inline int __adfs_block_map(struct super_block *sb, u32 indaddr,
0207                    unsigned int block)
0208 {
0209     if (indaddr & 255) {
0210         unsigned int off;
0211 
0212         off = (indaddr & 255) - 1;
0213         block += off << ADFS_SB(sb)->s_log2sharesize;
0214     }
0215 
0216     return adfs_map_lookup(sb, indaddr >> 8, block);
0217 }
0218 
0219 /* Return the disc record from the map */
0220 static inline
0221 struct adfs_discrecord *adfs_map_discrecord(struct adfs_discmap *dm)
0222 {
0223     return (void *)(dm[0].dm_bh->b_data + 4);
0224 }
0225 
0226 static inline u64 adfs_disc_size(const struct adfs_discrecord *dr)
0227 {
0228     return (u64)le32_to_cpu(dr->disc_size_high) << 32 |
0229             le32_to_cpu(dr->disc_size);
0230 }