| .. | .. | 
|---|
| 1 | 1 |  /* SPDX-License-Identifier: GPL-2.0 */ | 
|---|
 | 2 | +#include <linux/buffer_head.h>  | 
|---|
| 2 | 3 |  #include <linux/fs.h> | 
|---|
| 3 | 4 |  #include <linux/adfs_fs.h> | 
|---|
| 4 | 5 |   | 
|---|
| .. | .. | 
|---|
| 8 | 9 |  #define ADFS_BAD_FRAG		 1 | 
|---|
| 9 | 10 |  #define ADFS_ROOT_FRAG		 2 | 
|---|
| 10 | 11 |   | 
|---|
 | 12 | +#define ADFS_FILETYPE_NONE	((u16)~0)  | 
|---|
 | 13 | +  | 
|---|
 | 14 | +/* RISC OS 12-bit filetype is stored in load_address[19:8] */  | 
|---|
 | 15 | +static inline u16 adfs_filetype(u32 loadaddr)  | 
|---|
 | 16 | +{  | 
|---|
 | 17 | +	return (loadaddr & 0xfff00000) == 0xfff00000 ?  | 
|---|
 | 18 | +	       (loadaddr >> 8) & 0xfff : ADFS_FILETYPE_NONE;  | 
|---|
 | 19 | +}  | 
|---|
 | 20 | +  | 
|---|
| 11 | 21 |  #define ADFS_NDA_OWNER_READ	(1 << 0) | 
|---|
| 12 | 22 |  #define ADFS_NDA_OWNER_WRITE	(1 << 1) | 
|---|
| 13 | 23 |  #define ADFS_NDA_LOCKED		(1 << 2) | 
|---|
| .. | .. | 
|---|
| 16 | 26 |  #define ADFS_NDA_PUBLIC_READ	(1 << 5) | 
|---|
| 17 | 27 |  #define ADFS_NDA_PUBLIC_WRITE	(1 << 6) | 
|---|
| 18 | 28 |   | 
|---|
| 19 |  | -#include "dir_f.h"  | 
|---|
| 20 |  | -  | 
|---|
| 21 |  | -struct buffer_head;  | 
|---|
| 22 |  | -  | 
|---|
| 23 | 29 |  /* | 
|---|
| 24 | 30 |   * adfs file system inode data in memory | 
|---|
| 25 | 31 |   */ | 
|---|
| 26 | 32 |  struct adfs_inode_info { | 
|---|
| 27 | 33 |  	loff_t		mmu_private; | 
|---|
| 28 |  | -	unsigned long	parent_id;	/* object id of parent		*/  | 
|---|
 | 34 | +	__u32		parent_id;	/* parent indirect disc address	*/  | 
|---|
 | 35 | +	__u32		indaddr;	/* object indirect disc address	*/  | 
|---|
| 29 | 36 |  	__u32		loadaddr;	/* RISC OS load address		*/ | 
|---|
| 30 | 37 |  	__u32		execaddr;	/* RISC OS exec address		*/ | 
|---|
| 31 |  | -	unsigned int	filetype;	/* RISC OS file type		*/  | 
|---|
| 32 | 38 |  	unsigned int	attr;		/* RISC OS permissions		*/ | 
|---|
| 33 |  | -	unsigned int	stamped:1;	/* RISC OS file has date/time	*/  | 
|---|
| 34 | 39 |  	struct inode vfs_inode; | 
|---|
| 35 | 40 |  }; | 
|---|
 | 41 | +  | 
|---|
 | 42 | +static inline struct adfs_inode_info *ADFS_I(struct inode *inode)  | 
|---|
 | 43 | +{  | 
|---|
 | 44 | +	return container_of(inode, struct adfs_inode_info, vfs_inode);  | 
|---|
 | 45 | +}  | 
|---|
 | 46 | +  | 
|---|
 | 47 | +static inline bool adfs_inode_is_stamped(struct inode *inode)  | 
|---|
 | 48 | +{  | 
|---|
 | 49 | +	return (ADFS_I(inode)->loadaddr & 0xfff00000) == 0xfff00000;  | 
|---|
 | 50 | +}  | 
|---|
| 36 | 51 |   | 
|---|
| 37 | 52 |  /* | 
|---|
| 38 | 53 |   * Forward-declare this | 
|---|
| .. | .. | 
|---|
| 59 | 74 |  	__u32		s_ids_per_zone;	/* max. no ids in one zone */ | 
|---|
| 60 | 75 |  	__u32		s_idlen;	/* length of ID in map */ | 
|---|
| 61 | 76 |  	__u32		s_map_size;	/* sector size of a map	*/ | 
|---|
| 62 |  | -	unsigned long	s_size;		/* total size (in blocks) of this fs */  | 
|---|
| 63 | 77 |  	signed int	s_map2blk;	/* shift left by this for map->sector*/ | 
|---|
| 64 | 78 |  	unsigned int	s_log2sharesize;/* log2 share size */ | 
|---|
| 65 |  | -	__le32		s_version;	/* disc format version */  | 
|---|
| 66 | 79 |  	unsigned int	s_namelen;	/* maximum number of characters in name	 */ | 
|---|
| 67 | 80 |  }; | 
|---|
| 68 | 81 |   | 
|---|
| 69 | 82 |  static inline struct adfs_sb_info *ADFS_SB(struct super_block *sb) | 
|---|
| 70 | 83 |  { | 
|---|
| 71 | 84 |  	return sb->s_fs_info; | 
|---|
| 72 |  | -}  | 
|---|
| 73 |  | -  | 
|---|
| 74 |  | -static inline struct adfs_inode_info *ADFS_I(struct inode *inode)  | 
|---|
| 75 |  | -{  | 
|---|
| 76 |  | -	return container_of(inode, struct adfs_inode_info, vfs_inode);  | 
|---|
| 77 | 85 |  } | 
|---|
| 78 | 86 |   | 
|---|
| 79 | 87 |  /* | 
|---|
| .. | .. | 
|---|
| 84 | 92 |   | 
|---|
| 85 | 93 |  	int			nr_buffers; | 
|---|
| 86 | 94 |  	struct buffer_head	*bh[4]; | 
|---|
| 87 |  | -  | 
|---|
| 88 |  | -	/* big directories need allocated buffers */  | 
|---|
| 89 |  | -	struct buffer_head	**bh_fplus;  | 
|---|
 | 95 | +	struct buffer_head	**bhs;  | 
|---|
| 90 | 96 |   | 
|---|
| 91 | 97 |  	unsigned int		pos; | 
|---|
| 92 |  | -	unsigned int		parent_id;  | 
|---|
 | 98 | +	__u32			parent_id;  | 
|---|
| 93 | 99 |   | 
|---|
| 94 |  | -	struct adfs_dirheader	dirhead;  | 
|---|
| 95 |  | -	union  adfs_dirtail	dirtail;  | 
|---|
 | 100 | +	union {  | 
|---|
 | 101 | +		struct adfs_dirheader	*dirhead;  | 
|---|
 | 102 | +		struct adfs_bigdirheader *bighead;  | 
|---|
 | 103 | +	};  | 
|---|
 | 104 | +	union {  | 
|---|
 | 105 | +		struct adfs_newdirtail	*newtail;  | 
|---|
 | 106 | +		struct adfs_bigdirtail	*bigtail;  | 
|---|
 | 107 | +	};  | 
|---|
| 96 | 108 |  }; | 
|---|
| 97 | 109 |   | 
|---|
| 98 | 110 |  /* | 
|---|
| .. | .. | 
|---|
| 101 | 113 |  #define ADFS_MAX_NAME_LEN	(256 + 4) /* +4 for ,xyz hex filetype suffix */ | 
|---|
| 102 | 114 |  struct object_info { | 
|---|
| 103 | 115 |  	__u32		parent_id;		/* parent object id	*/ | 
|---|
| 104 |  | -	__u32		file_id;		/* object id		*/  | 
|---|
 | 116 | +	__u32		indaddr;		/* indirect disc addr	*/  | 
|---|
| 105 | 117 |  	__u32		loadaddr;		/* load address		*/ | 
|---|
| 106 | 118 |  	__u32		execaddr;		/* execution address	*/ | 
|---|
| 107 | 119 |  	__u32		size;			/* size			*/ | 
|---|
| 108 | 120 |  	__u8		attr;			/* RISC OS attributes	*/ | 
|---|
| 109 | 121 |  	unsigned int	name_len;		/* name length		*/ | 
|---|
| 110 | 122 |  	char		name[ADFS_MAX_NAME_LEN];/* file name		*/ | 
|---|
| 111 |  | -  | 
|---|
| 112 |  | -	/* RISC OS file type (12-bit: derived from loadaddr) */  | 
|---|
| 113 |  | -	__u16		filetype;  | 
|---|
| 114 | 123 |  }; | 
|---|
| 115 | 124 |   | 
|---|
| 116 |  | -/* RISC OS 12-bit filetype converts to ,xyz hex filename suffix */  | 
|---|
| 117 |  | -static inline int append_filetype_suffix(char *buf, __u16 filetype)  | 
|---|
| 118 |  | -{  | 
|---|
| 119 |  | -	if (filetype == 0xffff)	/* no explicit 12-bit file type was set */  | 
|---|
| 120 |  | -		return 0;  | 
|---|
| 121 |  | -  | 
|---|
| 122 |  | -	*buf++ = ',';  | 
|---|
| 123 |  | -	*buf++ = hex_asc_lo(filetype >> 8);  | 
|---|
| 124 |  | -	*buf++ = hex_asc_lo(filetype >> 4);  | 
|---|
| 125 |  | -	*buf++ = hex_asc_lo(filetype >> 0);  | 
|---|
| 126 |  | -	return 4;  | 
|---|
| 127 |  | -}  | 
|---|
| 128 |  | -  | 
|---|
| 129 | 125 |  struct adfs_dir_ops { | 
|---|
| 130 |  | -	int	(*read)(struct super_block *sb, unsigned int id, unsigned int sz, struct adfs_dir *dir);  | 
|---|
 | 126 | +	int	(*read)(struct super_block *sb, unsigned int indaddr,  | 
|---|
 | 127 | +			unsigned int size, struct adfs_dir *dir);  | 
|---|
 | 128 | +	int	(*iterate)(struct adfs_dir *dir, struct dir_context *ctx);  | 
|---|
| 131 | 129 |  	int	(*setpos)(struct adfs_dir *dir, unsigned int fpos); | 
|---|
| 132 | 130 |  	int	(*getnext)(struct adfs_dir *dir, struct object_info *obj); | 
|---|
| 133 | 131 |  	int	(*update)(struct adfs_dir *dir, struct object_info *obj); | 
|---|
| 134 | 132 |  	int	(*create)(struct adfs_dir *dir, struct object_info *obj); | 
|---|
| 135 | 133 |  	int	(*remove)(struct adfs_dir *dir, struct object_info *obj); | 
|---|
| 136 |  | -	int	(*sync)(struct adfs_dir *dir);  | 
|---|
| 137 |  | -	void	(*free)(struct adfs_dir *dir);  | 
|---|
 | 134 | +	int	(*commit)(struct adfs_dir *dir);  | 
|---|
| 138 | 135 |  }; | 
|---|
| 139 | 136 |   | 
|---|
| 140 | 137 |  struct adfs_discmap { | 
|---|
| .. | .. | 
|---|
| 150 | 147 |  int adfs_notify_change(struct dentry *dentry, struct iattr *attr); | 
|---|
| 151 | 148 |   | 
|---|
| 152 | 149 |  /* map.c */ | 
|---|
| 153 |  | -extern int adfs_map_lookup(struct super_block *sb, unsigned int frag_id, unsigned int offset);  | 
|---|
| 154 |  | -extern unsigned int adfs_map_free(struct super_block *sb);  | 
|---|
 | 150 | +int adfs_map_lookup(struct super_block *sb, u32 frag_id, unsigned int offset);  | 
|---|
 | 151 | +void adfs_map_statfs(struct super_block *sb, struct kstatfs *buf);  | 
|---|
 | 152 | +struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_discrecord *dr);  | 
|---|
 | 153 | +void adfs_free_map(struct super_block *sb);  | 
|---|
| 155 | 154 |   | 
|---|
| 156 | 155 |  /* Misc */ | 
|---|
| 157 | 156 |  __printf(3, 4) | 
|---|
| 158 | 157 |  void __adfs_error(struct super_block *sb, const char *function, | 
|---|
| 159 | 158 |  		  const char *fmt, ...); | 
|---|
| 160 | 159 |  #define adfs_error(sb, fmt...) __adfs_error(sb, __func__, fmt) | 
|---|
 | 160 | +void adfs_msg(struct super_block *sb, const char *pfx, const char *fmt, ...);  | 
|---|
| 161 | 161 |   | 
|---|
| 162 | 162 |  /* super.c */ | 
|---|
| 163 | 163 |   | 
|---|
| .. | .. | 
|---|
| 172 | 172 |  extern const struct adfs_dir_ops adfs_f_dir_ops; | 
|---|
| 173 | 173 |  extern const struct adfs_dir_ops adfs_fplus_dir_ops; | 
|---|
| 174 | 174 |   | 
|---|
 | 175 | +int adfs_dir_copyfrom(void *dst, struct adfs_dir *dir, unsigned int offset,  | 
|---|
 | 176 | +		      size_t len);  | 
|---|
 | 177 | +int adfs_dir_copyto(struct adfs_dir *dir, unsigned int offset, const void *src,  | 
|---|
 | 178 | +		    size_t len);  | 
|---|
 | 179 | +void adfs_dir_relse(struct adfs_dir *dir);  | 
|---|
 | 180 | +int adfs_dir_read_buffers(struct super_block *sb, u32 indaddr,  | 
|---|
 | 181 | +			  unsigned int size, struct adfs_dir *dir);  | 
|---|
 | 182 | +void adfs_object_fixup(struct adfs_dir *dir, struct object_info *obj);  | 
|---|
| 175 | 183 |  extern int adfs_dir_update(struct super_block *sb, struct object_info *obj, | 
|---|
| 176 | 184 |  			   int wait); | 
|---|
| 177 | 185 |   | 
|---|
| .. | .. | 
|---|
| 194 | 202 |   * | 
|---|
| 195 | 203 |   * The root directory ID should always be looked up in the map [3.4] | 
|---|
| 196 | 204 |   */ | 
|---|
| 197 |  | -static inline int  | 
|---|
| 198 |  | -__adfs_block_map(struct super_block *sb, unsigned int object_id,  | 
|---|
| 199 |  | -		 unsigned int block)  | 
|---|
 | 205 | +static inline int __adfs_block_map(struct super_block *sb, u32 indaddr,  | 
|---|
 | 206 | +				   unsigned int block)  | 
|---|
| 200 | 207 |  { | 
|---|
| 201 |  | -	if (object_id & 255) {  | 
|---|
 | 208 | +	if (indaddr & 255) {  | 
|---|
| 202 | 209 |  		unsigned int off; | 
|---|
| 203 | 210 |   | 
|---|
| 204 |  | -		off = (object_id & 255) - 1;  | 
|---|
 | 211 | +		off = (indaddr & 255) - 1;  | 
|---|
| 205 | 212 |  		block += off << ADFS_SB(sb)->s_log2sharesize; | 
|---|
| 206 | 213 |  	} | 
|---|
| 207 | 214 |   | 
|---|
| 208 |  | -	return adfs_map_lookup(sb, object_id >> 8, block);  | 
|---|
 | 215 | +	return adfs_map_lookup(sb, indaddr >> 8, block);  | 
|---|
 | 216 | +}  | 
|---|
 | 217 | +  | 
|---|
 | 218 | +/* Return the disc record from the map */  | 
|---|
 | 219 | +static inline  | 
|---|
 | 220 | +struct adfs_discrecord *adfs_map_discrecord(struct adfs_discmap *dm)  | 
|---|
 | 221 | +{  | 
|---|
 | 222 | +	return (void *)(dm[0].dm_bh->b_data + 4);  | 
|---|
 | 223 | +}  | 
|---|
 | 224 | +  | 
|---|
 | 225 | +static inline u64 adfs_disc_size(const struct adfs_discrecord *dr)  | 
|---|
 | 226 | +{  | 
|---|
 | 227 | +	return (u64)le32_to_cpu(dr->disc_size_high) << 32 |  | 
|---|
 | 228 | +		    le32_to_cpu(dr->disc_size);  | 
|---|
| 209 | 229 |  } | 
|---|