diff options
Diffstat (limited to 'fs/adfs')
-rw-r--r-- | fs/adfs/adfs.h | 21 | ||||
-rw-r--r-- | fs/adfs/dir_f.c | 23 | ||||
-rw-r--r-- | fs/adfs/dir_fplus.c | 18 | ||||
-rw-r--r-- | fs/adfs/inode.c | 22 | ||||
-rw-r--r-- | fs/adfs/super.c | 23 |
5 files changed, 81 insertions, 26 deletions
diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index 58588ddb178c..a8a58d864f96 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h | |||
@@ -50,6 +50,7 @@ struct adfs_sb_info { | |||
50 | gid_t s_gid; /* owner gid */ | 50 | gid_t s_gid; /* owner gid */ |
51 | umode_t s_owner_mask; /* ADFS owner perm -> unix perm */ | 51 | umode_t s_owner_mask; /* ADFS owner perm -> unix perm */ |
52 | umode_t s_other_mask; /* ADFS other perm -> unix perm */ | 52 | umode_t s_other_mask; /* ADFS other perm -> unix perm */ |
53 | int s_ftsuffix; /* ,xyz hex filetype suffix option */ | ||
53 | 54 | ||
54 | __u32 s_ids_per_zone; /* max. no ids in one zone */ | 55 | __u32 s_ids_per_zone; /* max. no ids in one zone */ |
55 | __u32 s_idlen; /* length of ID in map */ | 56 | __u32 s_idlen; /* length of ID in map */ |
@@ -93,7 +94,7 @@ struct adfs_dir { | |||
93 | /* | 94 | /* |
94 | * This is the overall maximum name length | 95 | * This is the overall maximum name length |
95 | */ | 96 | */ |
96 | #define ADFS_MAX_NAME_LEN 256 | 97 | #define ADFS_MAX_NAME_LEN (256 + 4) /* +4 for ,xyz hex filetype suffix */ |
97 | struct object_info { | 98 | struct object_info { |
98 | __u32 parent_id; /* parent object id */ | 99 | __u32 parent_id; /* parent object id */ |
99 | __u32 file_id; /* object id */ | 100 | __u32 file_id; /* object id */ |
@@ -101,10 +102,26 @@ struct object_info { | |||
101 | __u32 execaddr; /* execution address */ | 102 | __u32 execaddr; /* execution address */ |
102 | __u32 size; /* size */ | 103 | __u32 size; /* size */ |
103 | __u8 attr; /* RISC OS attributes */ | 104 | __u8 attr; /* RISC OS attributes */ |
104 | unsigned char name_len; /* name length */ | 105 | unsigned int name_len; /* name length */ |
105 | char name[ADFS_MAX_NAME_LEN];/* file name */ | 106 | char name[ADFS_MAX_NAME_LEN];/* file name */ |
107 | |||
108 | /* RISC OS file type (12-bit: derived from loadaddr) */ | ||
109 | __u16 filetype; | ||
106 | }; | 110 | }; |
107 | 111 | ||
112 | /* RISC OS 12-bit filetype converts to ,xyz hex filename suffix */ | ||
113 | static inline int append_filetype_suffix(char *buf, __u16 filetype) | ||
114 | { | ||
115 | if (filetype == -1) | ||
116 | return 0; | ||
117 | |||
118 | *buf++ = ','; | ||
119 | *buf++ = hex_asc_lo(filetype >> 8); | ||
120 | *buf++ = hex_asc_lo(filetype >> 4); | ||
121 | *buf++ = hex_asc_lo(filetype >> 0); | ||
122 | return 4; | ||
123 | } | ||
124 | |||
108 | struct adfs_dir_ops { | 125 | struct adfs_dir_ops { |
109 | 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 id, unsigned int sz, struct adfs_dir *dir); |
110 | int (*setpos)(struct adfs_dir *dir, unsigned int fpos); | 127 | int (*setpos)(struct adfs_dir *dir, unsigned int fpos); |
diff --git a/fs/adfs/dir_f.c b/fs/adfs/dir_f.c index bafc71222e25..4bbe853ee50a 100644 --- a/fs/adfs/dir_f.c +++ b/fs/adfs/dir_f.c | |||
@@ -52,7 +52,6 @@ static inline int adfs_readname(char *buf, char *ptr, int maxlen) | |||
52 | *buf++ = *ptr; | 52 | *buf++ = *ptr; |
53 | ptr++; | 53 | ptr++; |
54 | } | 54 | } |
55 | *buf = '\0'; | ||
56 | 55 | ||
57 | return buf - old_buf; | 56 | return buf - old_buf; |
58 | } | 57 | } |
@@ -208,7 +207,8 @@ release_buffers: | |||
208 | * convert a disk-based directory entry to a Linux ADFS directory entry | 207 | * convert a disk-based directory entry to a Linux ADFS directory entry |
209 | */ | 208 | */ |
210 | static inline void | 209 | static inline void |
211 | adfs_dir2obj(struct object_info *obj, struct adfs_direntry *de) | 210 | adfs_dir2obj(struct adfs_dir *dir, struct object_info *obj, |
211 | struct adfs_direntry *de) | ||
212 | { | 212 | { |
213 | obj->name_len = adfs_readname(obj->name, de->dirobname, ADFS_F_NAME_LEN); | 213 | obj->name_len = adfs_readname(obj->name, de->dirobname, ADFS_F_NAME_LEN); |
214 | obj->file_id = adfs_readval(de->dirinddiscadd, 3); | 214 | obj->file_id = adfs_readval(de->dirinddiscadd, 3); |
@@ -216,6 +216,23 @@ adfs_dir2obj(struct object_info *obj, struct adfs_direntry *de) | |||
216 | obj->execaddr = adfs_readval(de->direxec, 4); | 216 | obj->execaddr = adfs_readval(de->direxec, 4); |
217 | obj->size = adfs_readval(de->dirlen, 4); | 217 | obj->size = adfs_readval(de->dirlen, 4); |
218 | obj->attr = de->newdiratts; | 218 | obj->attr = de->newdiratts; |
219 | obj->filetype = -1; | ||
220 | |||
221 | /* | ||
222 | * object is a file and is filetyped and timestamped? | ||
223 | * RISC OS 12-bit filetype is stored in load_address[19:8] | ||
224 | */ | ||
225 | if ((0 == (obj->attr & ADFS_NDA_DIRECTORY)) && | ||
226 | (0xfff00000 == (0xfff00000 & obj->loadaddr))) { | ||
227 | obj->filetype = (__u16) ((0x000fff00 & obj->loadaddr) >> 8); | ||
228 | |||
229 | /* optionally append the ,xyz hex filetype suffix */ | ||
230 | if (ADFS_SB(dir->sb)->s_ftsuffix) | ||
231 | obj->name_len += | ||
232 | append_filetype_suffix( | ||
233 | &obj->name[obj->name_len], | ||
234 | obj->filetype); | ||
235 | } | ||
219 | } | 236 | } |
220 | 237 | ||
221 | /* | 238 | /* |
@@ -260,7 +277,7 @@ __adfs_dir_get(struct adfs_dir *dir, int pos, struct object_info *obj) | |||
260 | if (!de.dirobname[0]) | 277 | if (!de.dirobname[0]) |
261 | return -ENOENT; | 278 | return -ENOENT; |
262 | 279 | ||
263 | adfs_dir2obj(obj, &de); | 280 | adfs_dir2obj(dir, obj, &de); |
264 | 281 | ||
265 | return 0; | 282 | return 0; |
266 | } | 283 | } |
diff --git a/fs/adfs/dir_fplus.c b/fs/adfs/dir_fplus.c index a7f41da8115b..d9e3bee4e653 100644 --- a/fs/adfs/dir_fplus.c +++ b/fs/adfs/dir_fplus.c | |||
@@ -197,6 +197,24 @@ adfs_fplus_getnext(struct adfs_dir *dir, struct object_info *obj) | |||
197 | if (obj->name[i] == '/') | 197 | if (obj->name[i] == '/') |
198 | obj->name[i] = '.'; | 198 | obj->name[i] = '.'; |
199 | 199 | ||
200 | obj->filetype = -1; | ||
201 | |||
202 | /* | ||
203 | * object is a file and is filetyped and timestamped? | ||
204 | * RISC OS 12-bit filetype is stored in load_address[19:8] | ||
205 | */ | ||
206 | if ((0 == (obj->attr & ADFS_NDA_DIRECTORY)) && | ||
207 | (0xfff00000 == (0xfff00000 & obj->loadaddr))) { | ||
208 | obj->filetype = (__u16) ((0x000fff00 & obj->loadaddr) >> 8); | ||
209 | |||
210 | /* optionally append the ,xyz hex filetype suffix */ | ||
211 | if (ADFS_SB(dir->sb)->s_ftsuffix) | ||
212 | obj->name_len += | ||
213 | append_filetype_suffix( | ||
214 | &obj->name[obj->name_len], | ||
215 | obj->filetype); | ||
216 | } | ||
217 | |||
200 | dir->pos += 1; | 218 | dir->pos += 1; |
201 | ret = 0; | 219 | ret = 0; |
202 | out: | 220 | out: |
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c index 16d7ef2dffe1..92444e94f842 100644 --- a/fs/adfs/inode.c +++ b/fs/adfs/inode.c | |||
@@ -78,26 +78,13 @@ static const struct address_space_operations adfs_aops = { | |||
78 | .bmap = _adfs_bmap | 78 | .bmap = _adfs_bmap |
79 | }; | 79 | }; |
80 | 80 | ||
81 | static inline unsigned int | ||
82 | adfs_filetype(struct inode *inode) | ||
83 | { | ||
84 | unsigned int type; | ||
85 | |||
86 | if (ADFS_I(inode)->stamped) | ||
87 | type = (ADFS_I(inode)->loadaddr >> 8) & 0xfff; | ||
88 | else | ||
89 | type = (unsigned int) -1; | ||
90 | |||
91 | return type; | ||
92 | } | ||
93 | |||
94 | /* | 81 | /* |
95 | * Convert ADFS attributes and filetype to Linux permission. | 82 | * Convert ADFS attributes and filetype to Linux permission. |
96 | */ | 83 | */ |
97 | static umode_t | 84 | static umode_t |
98 | adfs_atts2mode(struct super_block *sb, struct inode *inode) | 85 | adfs_atts2mode(struct super_block *sb, struct inode *inode) |
99 | { | 86 | { |
100 | unsigned int filetype, attr = ADFS_I(inode)->attr; | 87 | unsigned int attr = ADFS_I(inode)->attr; |
101 | umode_t mode, rmask; | 88 | umode_t mode, rmask; |
102 | struct adfs_sb_info *asb = ADFS_SB(sb); | 89 | struct adfs_sb_info *asb = ADFS_SB(sb); |
103 | 90 | ||
@@ -106,9 +93,7 @@ adfs_atts2mode(struct super_block *sb, struct inode *inode) | |||
106 | return S_IFDIR | S_IXUGO | mode; | 93 | return S_IFDIR | S_IXUGO | mode; |
107 | } | 94 | } |
108 | 95 | ||
109 | filetype = adfs_filetype(inode); | 96 | switch (ADFS_I(inode)->filetype) { |
110 | |||
111 | switch (filetype) { | ||
112 | case 0xfc0: /* LinkFS */ | 97 | case 0xfc0: /* LinkFS */ |
113 | return S_IFLNK|S_IRWXUGO; | 98 | return S_IFLNK|S_IRWXUGO; |
114 | 99 | ||
@@ -277,7 +262,8 @@ adfs_iget(struct super_block *sb, struct object_info *obj) | |||
277 | ADFS_I(inode)->loadaddr = obj->loadaddr; | 262 | ADFS_I(inode)->loadaddr = obj->loadaddr; |
278 | ADFS_I(inode)->execaddr = obj->execaddr; | 263 | ADFS_I(inode)->execaddr = obj->execaddr; |
279 | ADFS_I(inode)->attr = obj->attr; | 264 | ADFS_I(inode)->attr = obj->attr; |
280 | ADFS_I(inode)->stamped = ((obj->loadaddr & 0xfff00000) == 0xfff00000); | 265 | ADFS_I(inode)->filetype = obj->filetype; |
266 | ADFS_I(inode)->stamped = ((obj->loadaddr & 0xfff00000) == 0xfff00000); | ||
281 | 267 | ||
282 | inode->i_mode = adfs_atts2mode(sb, inode); | 268 | inode->i_mode = adfs_atts2mode(sb, inode); |
283 | adfs_adfs2unix_time(&inode->i_mtime, inode); | 269 | adfs_adfs2unix_time(&inode->i_mtime, inode); |
diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 06d7388b477b..c8bf36a1996a 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c | |||
@@ -138,17 +138,20 @@ static int adfs_show_options(struct seq_file *seq, struct vfsmount *mnt) | |||
138 | seq_printf(seq, ",ownmask=%o", asb->s_owner_mask); | 138 | seq_printf(seq, ",ownmask=%o", asb->s_owner_mask); |
139 | if (asb->s_other_mask != ADFS_DEFAULT_OTHER_MASK) | 139 | if (asb->s_other_mask != ADFS_DEFAULT_OTHER_MASK) |
140 | seq_printf(seq, ",othmask=%o", asb->s_other_mask); | 140 | seq_printf(seq, ",othmask=%o", asb->s_other_mask); |
141 | if (asb->s_ftsuffix != 0) | ||
142 | seq_printf(seq, ",ftsuffix=%u", asb->s_ftsuffix); | ||
141 | 143 | ||
142 | return 0; | 144 | return 0; |
143 | } | 145 | } |
144 | 146 | ||
145 | enum {Opt_uid, Opt_gid, Opt_ownmask, Opt_othmask, Opt_err}; | 147 | enum {Opt_uid, Opt_gid, Opt_ownmask, Opt_othmask, Opt_ftsuffix, Opt_err}; |
146 | 148 | ||
147 | static const match_table_t tokens = { | 149 | static const match_table_t tokens = { |
148 | {Opt_uid, "uid=%u"}, | 150 | {Opt_uid, "uid=%u"}, |
149 | {Opt_gid, "gid=%u"}, | 151 | {Opt_gid, "gid=%u"}, |
150 | {Opt_ownmask, "ownmask=%o"}, | 152 | {Opt_ownmask, "ownmask=%o"}, |
151 | {Opt_othmask, "othmask=%o"}, | 153 | {Opt_othmask, "othmask=%o"}, |
154 | {Opt_ftsuffix, "ftsuffix=%u"}, | ||
152 | {Opt_err, NULL} | 155 | {Opt_err, NULL} |
153 | }; | 156 | }; |
154 | 157 | ||
@@ -189,6 +192,11 @@ static int parse_options(struct super_block *sb, char *options) | |||
189 | return -EINVAL; | 192 | return -EINVAL; |
190 | asb->s_other_mask = option; | 193 | asb->s_other_mask = option; |
191 | break; | 194 | break; |
195 | case Opt_ftsuffix: | ||
196 | if (match_int(args, &option)) | ||
197 | return -EINVAL; | ||
198 | asb->s_ftsuffix = option; | ||
199 | break; | ||
192 | default: | 200 | default: |
193 | printk("ADFS-fs: unrecognised mount option \"%s\" " | 201 | printk("ADFS-fs: unrecognised mount option \"%s\" " |
194 | "or missing value\n", p); | 202 | "or missing value\n", p); |
@@ -366,6 +374,7 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) | |||
366 | asb->s_gid = 0; | 374 | asb->s_gid = 0; |
367 | asb->s_owner_mask = ADFS_DEFAULT_OWNER_MASK; | 375 | asb->s_owner_mask = ADFS_DEFAULT_OWNER_MASK; |
368 | asb->s_other_mask = ADFS_DEFAULT_OTHER_MASK; | 376 | asb->s_other_mask = ADFS_DEFAULT_OTHER_MASK; |
377 | asb->s_ftsuffix = 0; | ||
369 | 378 | ||
370 | if (parse_options(sb, data)) | 379 | if (parse_options(sb, data)) |
371 | goto error; | 380 | goto error; |
@@ -445,11 +454,13 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) | |||
445 | 454 | ||
446 | root_obj.parent_id = root_obj.file_id = le32_to_cpu(dr->root); | 455 | root_obj.parent_id = root_obj.file_id = le32_to_cpu(dr->root); |
447 | root_obj.name_len = 0; | 456 | root_obj.name_len = 0; |
448 | root_obj.loadaddr = 0; | 457 | /* Set root object date as 01 Jan 1987 00:00:00 */ |
449 | root_obj.execaddr = 0; | 458 | root_obj.loadaddr = 0xfff0003f; |
459 | root_obj.execaddr = 0xec22c000; | ||
450 | root_obj.size = ADFS_NEWDIR_SIZE; | 460 | root_obj.size = ADFS_NEWDIR_SIZE; |
451 | root_obj.attr = ADFS_NDA_DIRECTORY | ADFS_NDA_OWNER_READ | | 461 | root_obj.attr = ADFS_NDA_DIRECTORY | ADFS_NDA_OWNER_READ | |
452 | ADFS_NDA_OWNER_WRITE | ADFS_NDA_PUBLIC_READ; | 462 | ADFS_NDA_OWNER_WRITE | ADFS_NDA_PUBLIC_READ; |
463 | root_obj.filetype = -1; | ||
453 | 464 | ||
454 | /* | 465 | /* |
455 | * If this is a F+ disk with variable length directories, | 466 | * If this is a F+ disk with variable length directories, |
@@ -463,6 +474,12 @@ static int adfs_fill_super(struct super_block *sb, void *data, int silent) | |||
463 | asb->s_dir = &adfs_f_dir_ops; | 474 | asb->s_dir = &adfs_f_dir_ops; |
464 | asb->s_namelen = ADFS_F_NAME_LEN; | 475 | asb->s_namelen = ADFS_F_NAME_LEN; |
465 | } | 476 | } |
477 | /* | ||
478 | * ,xyz hex filetype suffix may be added by driver | ||
479 | * to files that have valid RISC OS filetype | ||
480 | */ | ||
481 | if (asb->s_ftsuffix) | ||
482 | asb->s_namelen += 4; | ||
466 | 483 | ||
467 | sb->s_d_op = &adfs_dentry_operations; | 484 | sb->s_d_op = &adfs_dentry_operations; |
468 | root = adfs_iget(sb, &root_obj); | 485 | root = adfs_iget(sb, &root_obj); |