File: /usr/src/linux/fs/adfs/inode.c

1     /*
2      *  linux/fs/adfs/inode.c
3      *
4      *  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.
9      */
10     #include <linux/version.h>
11     #include <linux/errno.h>
12     #include <linux/fs.h>
13     #include <linux/adfs_fs.h>
14     #include <linux/sched.h>
15     #include <linux/stat.h>
16     #include <linux/string.h>
17     #include <linux/locks.h>
18     #include <linux/mm.h>
19     #include <linux/smp_lock.h>
20     
21     #include "adfs.h"
22     
23     /*
24      * Lookup/Create a block at offset 'block' into 'inode'.  We currently do
25      * not support creation of new blocks, so we return -EIO for this case.
26      */
27     int
28     adfs_get_block(struct inode *inode, long block, struct buffer_head *bh, int create)
29     {
30     	if (block < 0)
31     		goto abort_negative;
32     
33     	if (!create) {
34     		if (block >= inode->i_blocks)
35     			goto abort_toobig;
36     
37     		block = __adfs_block_map(inode->i_sb, inode->i_ino, block);
38     		if (block) {
39     			bh->b_dev = inode->i_dev;
40     			bh->b_blocknr = block;
41     			bh->b_state |= (1UL << BH_Mapped);
42     		}
43     		return 0;
44     	}
45     	/* don't support allocation of blocks yet */
46     	return -EIO;
47     
48     abort_negative:
49     	adfs_error(inode->i_sb, "block %d < 0", block);
50     	return -EIO;
51     
52     abort_toobig:
53     	return 0;
54     }
55     
56     static int adfs_writepage(struct page *page)
57     {
58     	return block_write_full_page(page, adfs_get_block);
59     }
60     
61     static int adfs_readpage(struct file *file, struct page *page)
62     {
63     	return block_read_full_page(page, adfs_get_block);
64     }
65     
66     static int adfs_prepare_write(struct file *file, struct page *page, unsigned int from, unsigned int to)
67     {
68     	return cont_prepare_write(page, from, to, adfs_get_block,
69     		&page->mapping->host->u.adfs_i.mmu_private);
70     }
71     
72     static int _adfs_bmap(struct address_space *mapping, long block)
73     {
74     	return generic_block_bmap(mapping, block, adfs_get_block);
75     }
76     
77     static struct address_space_operations adfs_aops = {
78     	readpage:	adfs_readpage,
79     	writepage:	adfs_writepage,
80     	sync_page:	block_sync_page,
81     	prepare_write:	adfs_prepare_write,
82     	commit_write:	generic_commit_write,
83     	bmap:		_adfs_bmap
84     };
85     
86     static inline unsigned int
87     adfs_filetype(struct inode *inode)
88     {
89     	unsigned int type;
90     
91     	if (inode->u.adfs_i.stamped)
92     		type = (inode->u.adfs_i.loadaddr >> 8) & 0xfff;
93     	else
94     		type = (unsigned int) -1;
95     
96     	return type;
97     }
98     
99     /*
100      * Convert ADFS attributes and filetype to Linux permission.
101      */
102     static umode_t
103     adfs_atts2mode(struct super_block *sb, struct inode *inode)
104     {
105     	unsigned int filetype, attr = inode->u.adfs_i.attr;
106     	umode_t mode, rmask;
107     
108     	if (attr & ADFS_NDA_DIRECTORY) {
109     		mode = S_IRUGO & sb->u.adfs_sb.s_owner_mask;
110     		return S_IFDIR | S_IXUGO | mode;
111     	}
112     
113     	filetype = adfs_filetype(inode);
114     
115     	switch (filetype) {
116     	case 0xfc0:	/* LinkFS */
117     		return S_IFLNK|S_IRWXUGO;
118     
119     	case 0xfe6:	/* UnixExec */
120     		rmask = S_IRUGO | S_IXUGO;
121     		break;
122     
123     	default:
124     		rmask = S_IRUGO;
125     	}
126     
127     	mode = S_IFREG;
128     
129     	if (attr & ADFS_NDA_OWNER_READ)
130     		mode |= rmask & sb->u.adfs_sb.s_owner_mask;
131     
132     	if (attr & ADFS_NDA_OWNER_WRITE)
133     		mode |= S_IWUGO & sb->u.adfs_sb.s_owner_mask;
134     
135     	if (attr & ADFS_NDA_PUBLIC_READ)
136     		mode |= rmask & sb->u.adfs_sb.s_other_mask;
137     
138     	if (attr & ADFS_NDA_PUBLIC_WRITE)
139     		mode |= S_IWUGO & sb->u.adfs_sb.s_other_mask;
140     	return mode;
141     }
142     
143     /*
144      * Convert Linux permission to ADFS attribute.  We try to do the reverse
145      * of atts2mode, but there is not a 1:1 translation.
146      */
147     static int
148     adfs_mode2atts(struct super_block *sb, struct inode *inode)
149     {
150     	umode_t mode;
151     	int attr;
152     
153     	/* FIXME: should we be able to alter a link? */
154     	if (S_ISLNK(inode->i_mode))
155     		return inode->u.adfs_i.attr;
156     
157     	if (S_ISDIR(inode->i_mode))
158     		attr = ADFS_NDA_DIRECTORY;
159     	else
160     		attr = 0;
161     
162     	mode = inode->i_mode & sb->u.adfs_sb.s_owner_mask;
163     	if (mode & S_IRUGO)
164     		attr |= ADFS_NDA_OWNER_READ;
165     	if (mode & S_IWUGO)
166     		attr |= ADFS_NDA_OWNER_WRITE;
167     
168     	mode = inode->i_mode & sb->u.adfs_sb.s_other_mask;
169     	mode &= ~sb->u.adfs_sb.s_owner_mask;
170     	if (mode & S_IRUGO)
171     		attr |= ADFS_NDA_PUBLIC_READ;
172     	if (mode & S_IWUGO)
173     		attr |= ADFS_NDA_PUBLIC_WRITE;
174     
175     	return attr;
176     }
177     
178     /*
179      * Convert an ADFS time to Unix time.  ADFS has a 40-bit centi-second time
180      * referenced to 1 Jan 1900 (til 2248)
181      */
182     static unsigned int
183     adfs_adfs2unix_time(struct inode *inode)
184     {
185     	unsigned int high, low;
186     
187     	if (inode->u.adfs_i.stamped == 0)
188     		return CURRENT_TIME;
189     
190     	high = inode->u.adfs_i.loadaddr << 24;
191     	low  = inode->u.adfs_i.execaddr;
192     
193     	high |= low >> 8;
194     	low  &= 255;
195     
196     	/* Files dated pre  01 Jan 1970 00:00:00. */
197     	if (high < 0x336e996a)
198     		return 0;
199     
200     	/* Files dated post 18 Jan 2038 03:14:05. */
201     	if (high >= 0x656e9969)
202     		return 0x7ffffffd;
203     
204     	/* discard 2208988800 (0x336e996a00) seconds of time */
205     	high -= 0x336e996a;
206     
207     	/* convert 40-bit centi-seconds to 32-bit seconds */
208     	return (((high % 100) << 8) + low) / 100 + (high / 100 << 8);
209     }
210     
211     /*
212      * Convert an Unix time to ADFS time.  We only do this if the entry has a
213      * time/date stamp already.
214      */
215     static void
216     adfs_unix2adfs_time(struct inode *inode, unsigned int secs)
217     {
218     	unsigned int high, low;
219     
220     	if (inode->u.adfs_i.stamped) {
221     		/* convert 32-bit seconds to 40-bit centi-seconds */
222     		low  = (secs & 255) * 100;
223     		high = (secs / 256) * 100 + (low >> 8) + 0x336e996a;
224     
225     		inode->u.adfs_i.loadaddr = (high >> 24) |
226     				(inode->u.adfs_i.loadaddr & ~0xff);
227     		inode->u.adfs_i.execaddr = (low & 255) | (high << 8);
228     	}
229     }
230     
231     /*
232      * Fill in the inode information from the object information.
233      *
234      * Note that this is an inode-less filesystem, so we can't use the inode
235      * number to reference the metadata on the media.  Instead, we use the
236      * inode number to hold the object ID, which in turn will tell us where
237      * the data is held.  We also save the parent object ID, and with these
238      * two, we can locate the metadata.
239      *
240      * This does mean that we rely on an objects parent remaining the same at
241      * all times - we cannot cope with a cross-directory rename (yet).
242      */
243     struct inode *
244     adfs_iget(struct super_block *sb, struct object_info *obj)
245     {
246     	struct inode *inode;
247     
248     	inode = new_inode(sb);
249     	if (!inode)
250     		goto out;
251     
252     	inode->i_version = ++event;
253     	inode->i_uid	 = sb->u.adfs_sb.s_uid;
254     	inode->i_gid	 = sb->u.adfs_sb.s_gid;
255     	inode->i_ino	 = obj->file_id;
256     	inode->i_size	 = obj->size;
257     	inode->i_nlink	 = 2;
258     	inode->i_blksize = PAGE_SIZE;
259     	inode->i_blocks	 = (inode->i_size + sb->s_blocksize - 1) >>
260     			    sb->s_blocksize_bits;
261     
262     	/*
263     	 * we need to save the parent directory ID so that
264     	 * write_inode can update the directory information
265     	 * for this file.  This will need special handling
266     	 * for cross-directory renames.
267     	 */
268     	inode->u.adfs_i.parent_id = obj->parent_id;
269     	inode->u.adfs_i.loadaddr  = obj->loadaddr;
270     	inode->u.adfs_i.execaddr  = obj->execaddr;
271     	inode->u.adfs_i.attr      = obj->attr;
272     	inode->u.adfs_i.stamped	  = ((obj->loadaddr & 0xfff00000) == 0xfff00000);
273     
274     	inode->i_mode	 = adfs_atts2mode(sb, inode);
275     	inode->i_mtime	 =
276     	inode->i_atime	 =
277     	inode->i_ctime	 = adfs_adfs2unix_time(inode);
278     
279     	if (S_ISDIR(inode->i_mode)) {
280     		inode->i_op	= &adfs_dir_inode_operations;
281     		inode->i_fop	= &adfs_dir_operations;
282     	} else if (S_ISREG(inode->i_mode)) {
283     		inode->i_op	= &adfs_file_inode_operations;
284     		inode->i_fop	= &adfs_file_operations;
285     		inode->i_mapping->a_ops = &adfs_aops;
286     		inode->u.adfs_i.mmu_private = inode->i_size;
287     	}
288     
289     	insert_inode_hash(inode);
290     
291     out:
292     	return inode;
293     }
294     
295     /*
296      * Validate and convert a changed access mode/time to their ADFS equivalents.
297      * adfs_write_inode will actually write the information back to the directory
298      * later.
299      */
300     int
301     adfs_notify_change(struct dentry *dentry, struct iattr *attr)
302     {
303     	struct inode *inode = dentry->d_inode;
304     	struct super_block *sb = inode->i_sb;
305     	unsigned int ia_valid = attr->ia_valid;
306     	int error;
307     
308     	error = inode_change_ok(inode, attr);
309     
310     	/*
311     	 * we can't change the UID or GID of any file -
312     	 * we have a global UID/GID in the superblock
313     	 */
314     	if ((ia_valid & ATTR_UID && attr->ia_uid != sb->u.adfs_sb.s_uid) ||
315     	    (ia_valid & ATTR_GID && attr->ia_gid != sb->u.adfs_sb.s_gid))
316     		error = -EPERM;
317     
318     	if (error)
319     		goto out;
320     
321     	if (ia_valid & ATTR_SIZE)
322     		error = vmtruncate(inode, attr->ia_size);
323     
324     	if (error)
325     		goto out;
326     
327     	if (ia_valid & ATTR_MTIME) {
328     		inode->i_mtime = attr->ia_mtime;
329     		adfs_unix2adfs_time(inode, attr->ia_mtime);
330     	}
331     	/*
332     	 * FIXME: should we make these == to i_mtime since we don't
333     	 * have the ability to represent them in our filesystem?
334     	 */
335     	if (ia_valid & ATTR_ATIME)
336     		inode->i_atime = attr->ia_atime;
337     	if (ia_valid & ATTR_CTIME)
338     		inode->i_ctime = attr->ia_ctime;
339     	if (ia_valid & ATTR_MODE) {
340     		inode->u.adfs_i.attr = adfs_mode2atts(sb, inode);
341     		inode->i_mode = adfs_atts2mode(sb, inode);
342     	}
343     
344     	/*
345     	 * FIXME: should we be marking this inode dirty even if
346     	 * we don't have any metadata to write back?
347     	 */
348     	if (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MODE))
349     		mark_inode_dirty(inode);
350     out:
351     	return error;
352     }
353     
354     /*
355      * write an existing inode back to the directory, and therefore the disk.
356      * The adfs-specific inode data has already been updated by
357      * adfs_notify_change()
358      */
359     void adfs_write_inode(struct inode *inode, int unused)
360     {
361     	struct super_block *sb = inode->i_sb;
362     	struct object_info obj;
363     
364     	lock_kernel();
365     	obj.file_id	= inode->i_ino;
366     	obj.name_len	= 0;
367     	obj.parent_id	= inode->u.adfs_i.parent_id;
368     	obj.loadaddr	= inode->u.adfs_i.loadaddr;
369     	obj.execaddr	= inode->u.adfs_i.execaddr;
370     	obj.attr	= inode->u.adfs_i.attr;
371     	obj.size	= inode->i_size;
372     
373     	adfs_dir_update(sb, &obj);
374     	unlock_kernel();
375     }
376