0001
0002
0003
0004
0005
0006
0007 #include <linux/buffer_head.h>
0008 #include <linux/writeback.h>
0009 #include "adfs.h"
0010
0011
0012
0013
0014
0015 static int
0016 adfs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh,
0017 int create)
0018 {
0019 if (!create) {
0020 if (block >= inode->i_blocks)
0021 goto abort_toobig;
0022
0023 block = __adfs_block_map(inode->i_sb, ADFS_I(inode)->indaddr,
0024 block);
0025 if (block)
0026 map_bh(bh, inode->i_sb, block);
0027 return 0;
0028 }
0029
0030 return -EIO;
0031
0032 abort_toobig:
0033 return 0;
0034 }
0035
0036 static int adfs_writepage(struct page *page, struct writeback_control *wbc)
0037 {
0038 return block_write_full_page(page, adfs_get_block, wbc);
0039 }
0040
0041 static int adfs_read_folio(struct file *file, struct folio *folio)
0042 {
0043 return block_read_full_folio(folio, adfs_get_block);
0044 }
0045
0046 static void adfs_write_failed(struct address_space *mapping, loff_t to)
0047 {
0048 struct inode *inode = mapping->host;
0049
0050 if (to > inode->i_size)
0051 truncate_pagecache(inode, inode->i_size);
0052 }
0053
0054 static int adfs_write_begin(struct file *file, struct address_space *mapping,
0055 loff_t pos, unsigned len,
0056 struct page **pagep, void **fsdata)
0057 {
0058 int ret;
0059
0060 *pagep = NULL;
0061 ret = cont_write_begin(file, mapping, pos, len, pagep, fsdata,
0062 adfs_get_block,
0063 &ADFS_I(mapping->host)->mmu_private);
0064 if (unlikely(ret))
0065 adfs_write_failed(mapping, pos + len);
0066
0067 return ret;
0068 }
0069
0070 static sector_t _adfs_bmap(struct address_space *mapping, sector_t block)
0071 {
0072 return generic_block_bmap(mapping, block, adfs_get_block);
0073 }
0074
0075 static const struct address_space_operations adfs_aops = {
0076 .dirty_folio = block_dirty_folio,
0077 .invalidate_folio = block_invalidate_folio,
0078 .read_folio = adfs_read_folio,
0079 .writepage = adfs_writepage,
0080 .write_begin = adfs_write_begin,
0081 .write_end = generic_write_end,
0082 .bmap = _adfs_bmap
0083 };
0084
0085
0086
0087
0088 static umode_t
0089 adfs_atts2mode(struct super_block *sb, struct inode *inode)
0090 {
0091 unsigned int attr = ADFS_I(inode)->attr;
0092 umode_t mode, rmask;
0093 struct adfs_sb_info *asb = ADFS_SB(sb);
0094
0095 if (attr & ADFS_NDA_DIRECTORY) {
0096 mode = S_IRUGO & asb->s_owner_mask;
0097 return S_IFDIR | S_IXUGO | mode;
0098 }
0099
0100 switch (adfs_filetype(ADFS_I(inode)->loadaddr)) {
0101 case 0xfc0:
0102 return S_IFLNK|S_IRWXUGO;
0103
0104 case 0xfe6:
0105 rmask = S_IRUGO | S_IXUGO;
0106 break;
0107
0108 default:
0109 rmask = S_IRUGO;
0110 }
0111
0112 mode = S_IFREG;
0113
0114 if (attr & ADFS_NDA_OWNER_READ)
0115 mode |= rmask & asb->s_owner_mask;
0116
0117 if (attr & ADFS_NDA_OWNER_WRITE)
0118 mode |= S_IWUGO & asb->s_owner_mask;
0119
0120 if (attr & ADFS_NDA_PUBLIC_READ)
0121 mode |= rmask & asb->s_other_mask;
0122
0123 if (attr & ADFS_NDA_PUBLIC_WRITE)
0124 mode |= S_IWUGO & asb->s_other_mask;
0125 return mode;
0126 }
0127
0128
0129
0130
0131
0132 static int adfs_mode2atts(struct super_block *sb, struct inode *inode,
0133 umode_t ia_mode)
0134 {
0135 struct adfs_sb_info *asb = ADFS_SB(sb);
0136 umode_t mode;
0137 int attr;
0138
0139
0140 if (S_ISLNK(inode->i_mode))
0141 return ADFS_I(inode)->attr;
0142
0143
0144 if (S_ISDIR(inode->i_mode))
0145 return ADFS_NDA_DIRECTORY;
0146
0147 attr = 0;
0148 mode = ia_mode & asb->s_owner_mask;
0149 if (mode & S_IRUGO)
0150 attr |= ADFS_NDA_OWNER_READ;
0151 if (mode & S_IWUGO)
0152 attr |= ADFS_NDA_OWNER_WRITE;
0153
0154 mode = ia_mode & asb->s_other_mask;
0155 mode &= ~asb->s_owner_mask;
0156 if (mode & S_IRUGO)
0157 attr |= ADFS_NDA_PUBLIC_READ;
0158 if (mode & S_IWUGO)
0159 attr |= ADFS_NDA_PUBLIC_WRITE;
0160
0161 return attr;
0162 }
0163
0164 static const s64 nsec_unix_epoch_diff_risc_os_epoch = 2208988800000000000LL;
0165
0166
0167
0168
0169
0170
0171 static void
0172 adfs_adfs2unix_time(struct timespec64 *tv, struct inode *inode)
0173 {
0174 unsigned int high, low;
0175
0176
0177
0178 s64 nsec;
0179
0180 if (!adfs_inode_is_stamped(inode))
0181 goto cur_time;
0182
0183 high = ADFS_I(inode)->loadaddr & 0xFF;
0184 low = ADFS_I(inode)->execaddr;
0185
0186
0187
0188
0189 nsec = (((s64) high << 32) | (s64) low) * 10000000;
0190
0191
0192 if (nsec < nsec_unix_epoch_diff_risc_os_epoch)
0193 goto too_early;
0194
0195
0196 nsec -= nsec_unix_epoch_diff_risc_os_epoch;
0197
0198 *tv = ns_to_timespec64(nsec);
0199 return;
0200
0201 cur_time:
0202 *tv = current_time(inode);
0203 return;
0204
0205 too_early:
0206 tv->tv_sec = tv->tv_nsec = 0;
0207 return;
0208 }
0209
0210
0211 static void adfs_unix2adfs_time(struct inode *inode,
0212 const struct timespec64 *ts)
0213 {
0214 s64 cs, nsec = timespec64_to_ns(ts);
0215
0216
0217 nsec += nsec_unix_epoch_diff_risc_os_epoch;
0218
0219
0220 cs = div_s64(nsec, 10000000);
0221
0222 cs = clamp_t(s64, cs, 0, 0xffffffffff);
0223
0224 ADFS_I(inode)->loadaddr &= ~0xff;
0225 ADFS_I(inode)->loadaddr |= (cs >> 32) & 0xff;
0226 ADFS_I(inode)->execaddr = cs;
0227 }
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241 struct inode *
0242 adfs_iget(struct super_block *sb, struct object_info *obj)
0243 {
0244 struct inode *inode;
0245
0246 inode = new_inode(sb);
0247 if (!inode)
0248 goto out;
0249
0250 inode->i_uid = ADFS_SB(sb)->s_uid;
0251 inode->i_gid = ADFS_SB(sb)->s_gid;
0252 inode->i_ino = obj->indaddr;
0253 inode->i_size = obj->size;
0254 set_nlink(inode, 2);
0255 inode->i_blocks = (inode->i_size + sb->s_blocksize - 1) >>
0256 sb->s_blocksize_bits;
0257
0258
0259
0260
0261
0262
0263
0264 ADFS_I(inode)->parent_id = obj->parent_id;
0265 ADFS_I(inode)->indaddr = obj->indaddr;
0266 ADFS_I(inode)->loadaddr = obj->loadaddr;
0267 ADFS_I(inode)->execaddr = obj->execaddr;
0268 ADFS_I(inode)->attr = obj->attr;
0269
0270 inode->i_mode = adfs_atts2mode(sb, inode);
0271 adfs_adfs2unix_time(&inode->i_mtime, inode);
0272 inode->i_atime = inode->i_mtime;
0273 inode->i_ctime = inode->i_mtime;
0274
0275 if (S_ISDIR(inode->i_mode)) {
0276 inode->i_op = &adfs_dir_inode_operations;
0277 inode->i_fop = &adfs_dir_operations;
0278 } else if (S_ISREG(inode->i_mode)) {
0279 inode->i_op = &adfs_file_inode_operations;
0280 inode->i_fop = &adfs_file_operations;
0281 inode->i_mapping->a_ops = &adfs_aops;
0282 ADFS_I(inode)->mmu_private = inode->i_size;
0283 }
0284
0285 inode_fake_hash(inode);
0286
0287 out:
0288 return inode;
0289 }
0290
0291
0292
0293
0294
0295
0296 int
0297 adfs_notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
0298 struct iattr *attr)
0299 {
0300 struct inode *inode = d_inode(dentry);
0301 struct super_block *sb = inode->i_sb;
0302 unsigned int ia_valid = attr->ia_valid;
0303 int error;
0304
0305 error = setattr_prepare(&init_user_ns, dentry, attr);
0306
0307
0308
0309
0310
0311 if ((ia_valid & ATTR_UID && !uid_eq(attr->ia_uid, ADFS_SB(sb)->s_uid)) ||
0312 (ia_valid & ATTR_GID && !gid_eq(attr->ia_gid, ADFS_SB(sb)->s_gid)))
0313 error = -EPERM;
0314
0315 if (error)
0316 goto out;
0317
0318
0319 if (ia_valid & ATTR_SIZE)
0320 truncate_setsize(inode, attr->ia_size);
0321
0322 if (ia_valid & ATTR_MTIME && adfs_inode_is_stamped(inode)) {
0323 adfs_unix2adfs_time(inode, &attr->ia_mtime);
0324 adfs_adfs2unix_time(&inode->i_mtime, inode);
0325 }
0326
0327
0328
0329
0330
0331 if (ia_valid & ATTR_ATIME)
0332 inode->i_atime = attr->ia_atime;
0333 if (ia_valid & ATTR_CTIME)
0334 inode->i_ctime = attr->ia_ctime;
0335 if (ia_valid & ATTR_MODE) {
0336 ADFS_I(inode)->attr = adfs_mode2atts(sb, inode, attr->ia_mode);
0337 inode->i_mode = adfs_atts2mode(sb, inode);
0338 }
0339
0340
0341
0342
0343
0344 if (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MODE))
0345 mark_inode_dirty(inode);
0346 out:
0347 return error;
0348 }
0349
0350
0351
0352
0353
0354
0355 int adfs_write_inode(struct inode *inode, struct writeback_control *wbc)
0356 {
0357 struct super_block *sb = inode->i_sb;
0358 struct object_info obj;
0359
0360 obj.indaddr = ADFS_I(inode)->indaddr;
0361 obj.name_len = 0;
0362 obj.parent_id = ADFS_I(inode)->parent_id;
0363 obj.loadaddr = ADFS_I(inode)->loadaddr;
0364 obj.execaddr = ADFS_I(inode)->execaddr;
0365 obj.attr = ADFS_I(inode)->attr;
0366 obj.size = inode->i_size;
0367
0368 return adfs_dir_update(sb, &obj, wbc->sync_mode == WB_SYNC_ALL);
0369 }