hc
2024-05-10 748e4f3d702def1a4bff191e0cf93b6a05340f01
kernel/fs/adfs/inode.c
....@@ -1,11 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * linux/fs/adfs/inode.c
34 *
45 * Copyright (C) 1997-1999 Russell King
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 as
8
- * published by the Free Software Foundation.
96 */
107 #include <linux/buffer_head.h>
118 #include <linux/writeback.h>
....@@ -23,7 +20,8 @@
2320 if (block >= inode->i_blocks)
2421 goto abort_toobig;
2522
26
- block = __adfs_block_map(inode->i_sb, inode->i_ino, block);
23
+ block = __adfs_block_map(inode->i_sb, ADFS_I(inode)->indaddr,
24
+ block);
2725 if (block)
2826 map_bh(bh, inode->i_sb, block);
2927 return 0;
....@@ -97,7 +95,7 @@
9795 return S_IFDIR | S_IXUGO | mode;
9896 }
9997
100
- switch (ADFS_I(inode)->filetype) {
98
+ switch (adfs_filetype(ADFS_I(inode)->loadaddr)) {
10199 case 0xfc0: /* LinkFS */
102100 return S_IFLNK|S_IRWXUGO;
103101
....@@ -129,29 +127,29 @@
129127 * Convert Linux permission to ADFS attribute. We try to do the reverse
130128 * of atts2mode, but there is not a 1:1 translation.
131129 */
132
-static int
133
-adfs_mode2atts(struct super_block *sb, struct inode *inode)
130
+static int adfs_mode2atts(struct super_block *sb, struct inode *inode,
131
+ umode_t ia_mode)
134132 {
133
+ struct adfs_sb_info *asb = ADFS_SB(sb);
135134 umode_t mode;
136135 int attr;
137
- struct adfs_sb_info *asb = ADFS_SB(sb);
138136
139137 /* FIXME: should we be able to alter a link? */
140138 if (S_ISLNK(inode->i_mode))
141139 return ADFS_I(inode)->attr;
142140
141
+ /* Directories do not have read/write permissions on the media */
143142 if (S_ISDIR(inode->i_mode))
144
- attr = ADFS_NDA_DIRECTORY;
145
- else
146
- attr = 0;
143
+ return ADFS_NDA_DIRECTORY;
147144
148
- mode = inode->i_mode & asb->s_owner_mask;
145
+ attr = 0;
146
+ mode = ia_mode & asb->s_owner_mask;
149147 if (mode & S_IRUGO)
150148 attr |= ADFS_NDA_OWNER_READ;
151149 if (mode & S_IWUGO)
152150 attr |= ADFS_NDA_OWNER_WRITE;
153151
154
- mode = inode->i_mode & asb->s_other_mask;
152
+ mode = ia_mode & asb->s_other_mask;
155153 mode &= ~asb->s_owner_mask;
156154 if (mode & S_IRUGO)
157155 attr |= ADFS_NDA_PUBLIC_READ;
....@@ -160,6 +158,8 @@
160158
161159 return attr;
162160 }
161
+
162
+static const s64 nsec_unix_epoch_diff_risc_os_epoch = 2208988800000000000LL;
163163
164164 /*
165165 * Convert an ADFS time to Unix time. ADFS has a 40-bit centi-second time
....@@ -173,11 +173,9 @@
173173 /* 01 Jan 1970 00:00:00 (Unix epoch) as nanoseconds since
174174 * 01 Jan 1900 00:00:00 (RISC OS epoch)
175175 */
176
- static const s64 nsec_unix_epoch_diff_risc_os_epoch =
177
- 2208988800000000000LL;
178176 s64 nsec;
179177
180
- if (ADFS_I(inode)->stamped == 0)
178
+ if (!adfs_inode_is_stamped(inode))
181179 goto cur_time;
182180
183181 high = ADFS_I(inode)->loadaddr & 0xFF; /* top 8 bits of timestamp */
....@@ -207,24 +205,23 @@
207205 return;
208206 }
209207
210
-/*
211
- * Convert an Unix time to ADFS time. We only do this if the entry has a
212
- * time/date stamp already.
213
- */
214
-static void
215
-adfs_unix2adfs_time(struct inode *inode, unsigned int secs)
208
+/* Convert an Unix time to ADFS time for an entry that is already stamped. */
209
+static void adfs_unix2adfs_time(struct inode *inode,
210
+ const struct timespec64 *ts)
216211 {
217
- unsigned int high, low;
212
+ s64 cs, nsec = timespec64_to_ns(ts);
218213
219
- if (ADFS_I(inode)->stamped) {
220
- /* convert 32-bit seconds to 40-bit centi-seconds */
221
- low = (secs & 255) * 100;
222
- high = (secs / 256) * 100 + (low >> 8) + 0x336e996a;
214
+ /* convert from Unix to RISC OS epoch */
215
+ nsec += nsec_unix_epoch_diff_risc_os_epoch;
223216
224
- ADFS_I(inode)->loadaddr = (high >> 24) |
225
- (ADFS_I(inode)->loadaddr & ~0xff);
226
- ADFS_I(inode)->execaddr = (low & 255) | (high << 8);
227
- }
217
+ /* convert from nanoseconds to centiseconds */
218
+ cs = div_s64(nsec, 10000000);
219
+
220
+ cs = clamp_t(s64, cs, 0, 0xffffffffff);
221
+
222
+ ADFS_I(inode)->loadaddr &= ~0xff;
223
+ ADFS_I(inode)->loadaddr |= (cs >> 32) & 0xff;
224
+ ADFS_I(inode)->execaddr = cs;
228225 }
229226
230227 /*
....@@ -250,7 +247,7 @@
250247
251248 inode->i_uid = ADFS_SB(sb)->s_uid;
252249 inode->i_gid = ADFS_SB(sb)->s_gid;
253
- inode->i_ino = obj->file_id;
250
+ inode->i_ino = obj->indaddr;
254251 inode->i_size = obj->size;
255252 set_nlink(inode, 2);
256253 inode->i_blocks = (inode->i_size + sb->s_blocksize - 1) >>
....@@ -263,11 +260,10 @@
263260 * for cross-directory renames.
264261 */
265262 ADFS_I(inode)->parent_id = obj->parent_id;
263
+ ADFS_I(inode)->indaddr = obj->indaddr;
266264 ADFS_I(inode)->loadaddr = obj->loadaddr;
267265 ADFS_I(inode)->execaddr = obj->execaddr;
268266 ADFS_I(inode)->attr = obj->attr;
269
- ADFS_I(inode)->filetype = obj->filetype;
270
- ADFS_I(inode)->stamped = ((obj->loadaddr & 0xfff00000) == 0xfff00000);
271267
272268 inode->i_mode = adfs_atts2mode(sb, inode);
273269 adfs_adfs2unix_time(&inode->i_mtime, inode);
....@@ -320,10 +316,11 @@
320316 if (ia_valid & ATTR_SIZE)
321317 truncate_setsize(inode, attr->ia_size);
322318
323
- if (ia_valid & ATTR_MTIME) {
324
- inode->i_mtime = attr->ia_mtime;
325
- adfs_unix2adfs_time(inode, attr->ia_mtime.tv_sec);
319
+ if (ia_valid & ATTR_MTIME && adfs_inode_is_stamped(inode)) {
320
+ adfs_unix2adfs_time(inode, &attr->ia_mtime);
321
+ adfs_adfs2unix_time(&inode->i_mtime, inode);
326322 }
323
+
327324 /*
328325 * FIXME: should we make these == to i_mtime since we don't
329326 * have the ability to represent them in our filesystem?
....@@ -333,7 +330,7 @@
333330 if (ia_valid & ATTR_CTIME)
334331 inode->i_ctime = attr->ia_ctime;
335332 if (ia_valid & ATTR_MODE) {
336
- ADFS_I(inode)->attr = adfs_mode2atts(sb, inode);
333
+ ADFS_I(inode)->attr = adfs_mode2atts(sb, inode, attr->ia_mode);
337334 inode->i_mode = adfs_atts2mode(sb, inode);
338335 }
339336
....@@ -358,7 +355,7 @@
358355 struct object_info obj;
359356 int ret;
360357
361
- obj.file_id = inode->i_ino;
358
+ obj.indaddr = ADFS_I(inode)->indaddr;
362359 obj.name_len = 0;
363360 obj.parent_id = ADFS_I(inode)->parent_id;
364361 obj.loadaddr = ADFS_I(inode)->loadaddr;