1
2
3#include "hfs.h"
4#include <linux/hfs_fs_sb.h>
5#include <linux/hfs_fs_i.h>
6#include <linux/hfs_fs.h>
7#include <linux/smp_lock.h>
8
9/*================ Variable-like macros ================*/
10
11#define HFS_VALID_MODE_BITS  (S_IFREG | S_IFDIR | S_IRWXUGO)
12
13/*================ File-local functions ================*/
14
15/*
16 * init_file_inode()
17 *
18 * Given an HFS catalog entry initialize an inode for a file.
19 */
20static void init_file_inode(struct inode *inode, hfs_u8 fork)
21{
22	struct hfs_fork *fk;
23	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
24
25	if (fork == HFS_FK_DATA) {
26		inode->i_mode = S_IRWXUGO | S_IFREG;
27	} else {
28		inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
29	}
30
31	if (fork == HFS_FK_DATA) {
32		HFS_I(inode)->convert = 0;
33		fk = &entry->u.file.data_fork;
34	} else {
35		fk = &entry->u.file.rsrc_fork;
36		HFS_I(inode)->convert = 0;
37	}
38	HFS_I(inode)->fork = fk;
39	inode->i_size = fk->lsize;
40	inode->i_blocks = fk->psize;
41	inode->i_nlink = 1;
42}
43
44/*================ Global functions ================*/
45
46/*
47 * hfs_put_inode()
48 *
49 * This is the put_inode() entry in the super_operations for HFS
50 * filesystems.  The purpose is to perform any filesystem-dependent
51 * cleanup necessary when the use-count of an inode falls to zero.
52 */
53void hfs_put_inode(struct inode * inode)
54{
55	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
56
57	lock_kernel();
58	hfs_cat_put(entry);
59	if (atomic_read(&inode->i_count) == 1) {
60	  struct hfs_hdr_layout *tmp = HFS_I(inode)->layout;
61
62	  if (tmp) {
63		HFS_I(inode)->layout = NULL;
64		HFS_DELETE(tmp);
65	  }
66	}
67	unlock_kernel();
68}
69
70/*
71 * hfs_notify_change()
72 *
73 * Based very closely on fs/msdos/inode.c by Werner Almesberger
74 *
75 * This is the notify_change() field in the super_operations structure
76 * for HFS file systems.  The purpose is to take that changes made to
77 * an inode and apply then in a filesystem-dependent manner.  In this
78 * case the process has a few of tasks to do:
79 *  1) prevent changes to the i_uid and i_gid fields.
80 *  2) map file permissions to the closest allowable permissions
81 *  3) Since multiple Linux files can share the same on-disk inode under
82 *     HFS (for instance the data and resource forks of a file) a change
83 *     to permissions must be applied to all other in-core inodes which
84 *     correspond to the same HFS file.
85 */
86enum {HFS_NORM, HFS_HDR, HFS_CAP};
87
88static int __hfs_notify_change(struct dentry *dentry, struct iattr * attr, int kind)
89{
90	struct inode *inode = dentry->d_inode;
91	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
92	struct dentry **de = entry->sys_entry;
93	struct hfs_sb_info *hsb = HFS_SB(inode->i_sb);
94	int error, i;
95
96	error = inode_change_ok(inode, attr); /* basic permission checks */
97	if (error) {
98		/* Let netatalk's afpd think chmod() always succeeds */
99		if (hsb->s_afpd &&
100		    (attr->ia_valid == (ATTR_MODE | ATTR_CTIME))) {
101			return 0;
102		} else {
103			return error;
104		}
105	}
106
107	/* no uig/gid changes and limit which mode bits can be set */
108	if (((attr->ia_valid & ATTR_UID) &&
109	     (attr->ia_uid != hsb->s_uid)) ||
110	    ((attr->ia_valid & ATTR_GID) &&
111	     (attr->ia_gid != hsb->s_gid)) ||
112	    ((attr->ia_valid & ATTR_MODE) &&
113	     (((entry->type == HFS_CDR_DIR) &&
114	       (attr->ia_mode != inode->i_mode))||
115	      (attr->ia_mode & ~HFS_VALID_MODE_BITS)))) {
116		return hsb->s_quiet ? 0 : error;
117	}
118
119	if (entry->type == HFS_CDR_DIR) {
120		attr->ia_valid &= ~ATTR_MODE;
121	} else if (attr->ia_valid & ATTR_MODE) {
122		/* Only the 'w' bits can ever change and only all together. */
123		if (attr->ia_mode & S_IWUSR) {
124			attr->ia_mode = inode->i_mode | S_IWUGO;
125		} else {
126			attr->ia_mode = inode->i_mode & ~S_IWUGO;
127		}
128		attr->ia_mode &= ~hsb->s_umask;
129	}
130	/*
131	 * Normal files handle size change in normal way.
132	 * Oddballs are served here.
133	 */
134	if (attr->ia_valid & ATTR_SIZE) {
135		if (kind == HFS_CAP) {
136			inode->i_size = attr->ia_size;
137			if (inode->i_size > HFS_FORK_MAX)
138				inode->i_size = HFS_FORK_MAX;
139			mark_inode_dirty(inode);
140			attr->ia_valid &= ~ATTR_SIZE;
141		} else if (kind == HFS_HDR) {
142			hdr_truncate(inode, attr->ia_size);
143			attr->ia_valid &= ~ATTR_SIZE;
144		}
145	}
146	error = inode_setattr(inode, attr);
147	if (error)
148		return error;
149
150	/* We wouldn't want to mess with the sizes of the other fork */
151	attr->ia_valid &= ~ATTR_SIZE;
152
153	/* We must change all in-core inodes corresponding to this file. */
154	for (i = 0; i < 4; ++i) {
155	  if (de[i] && (de[i] != dentry)) {
156		inode_setattr(de[i]->d_inode, attr);
157	  }
158	}
159
160	/* Change the catalog entry if needed */
161	if (attr->ia_valid & ATTR_MTIME) {
162		entry->modify_date = hfs_u_to_mtime(inode->i_mtime);
163		hfs_cat_mark_dirty(entry);
164	}
165	if (attr->ia_valid & ATTR_MODE) {
166		hfs_u8 new_flags;
167
168		if (inode->i_mode & S_IWUSR) {
169			new_flags = entry->u.file.flags & ~HFS_FIL_LOCK;
170		} else {
171			new_flags = entry->u.file.flags | HFS_FIL_LOCK;
172		}
173
174		if (new_flags != entry->u.file.flags) {
175			entry->u.file.flags = new_flags;
176			hfs_cat_mark_dirty(entry);
177		}
178	}
179	/* size changes handled in hfs_extent_adj() */
180
181	return 0;
182}
183
184int hfs_notify_change(struct dentry *dentry, struct iattr * attr)
185{
186	return __hfs_notify_change(dentry, attr, HFS_NORM);
187}
188
189int hfs_notify_change_cap(struct dentry *dentry, struct iattr * attr)
190{
191	return __hfs_notify_change(dentry, attr, HFS_CAP);
192}
193
194int hfs_notify_change_hdr(struct dentry *dentry, struct iattr * attr)
195{
196	return __hfs_notify_change(dentry, attr, HFS_HDR);
197}
198
199static int hfs_writepage(struct page *page)
200{
201	return block_write_full_page(page,hfs_get_block);
202}
203static int hfs_readpage(struct file *file, struct page *page)
204{
205	return block_read_full_page(page,hfs_get_block);
206}
207static int hfs_prepare_write(struct file *file, struct page *page, unsigned from, unsigned to)
208{
209	return cont_prepare_write(page,from,to,hfs_get_block,
210		&page->mapping->host->u.hfs_i.mmu_private);
211}
212static int hfs_bmap(struct address_space *mapping, long block)
213{
214	return generic_block_bmap(mapping,block,hfs_get_block);
215}
216struct address_space_operations hfs_aops = {
217	readpage: hfs_readpage,
218	writepage: hfs_writepage,
219	sync_page: block_sync_page,
220	prepare_write: hfs_prepare_write,
221	commit_write: generic_commit_write,
222	bmap: hfs_bmap
223};
224
225struct inode *hfs_iget(struct hfs_cat_entry *entry, ino_t type,
226		       struct dentry *dentry)
227{
228	struct dentry **sys_entry;
229	struct super_block *sb;
230	struct inode *inode;
231
232	if (!entry) {
233		return NULL;
234	}
235
236	/* If there are several processes all calling __iget() for
237	   the same inode then they will all get the same one back.
238	   The first one to return from __iget() will notice that the
239	   i_mode field of the inode is blank and KNOW that it is
240	   the first to return.  Therefore, it will set the appropriate
241	   'sys_entry' field in the entry and initialize the inode.
242	   All the initialization must be done without sleeping,
243	   or else other processes could end up using a partially
244	   initialized inode.				*/
245
246	sb = entry->mdb->sys_mdb;
247	sys_entry = &entry->sys_entry[HFS_ITYPE_TO_INT(type)];
248
249	if (!(inode = iget(sb, ntohl(entry->cnid) | type))) {
250	        hfs_cat_put(entry);
251	        return NULL;
252	}
253
254	if (inode->i_dev != sb->s_dev) {
255	        iput(inode); /* automatically does an hfs_cat_put */
256		inode = NULL;
257	} else if (!inode->i_mode || (*sys_entry == NULL)) {
258		/* Initialize the inode */
259		struct hfs_sb_info *hsb = HFS_SB(sb);
260
261		inode->i_rdev = 0;
262		inode->i_ctime = inode->i_atime = inode->i_mtime =
263					hfs_m_to_utime(entry->modify_date);
264		inode->i_blksize = HFS_SECTOR_SIZE;
265		inode->i_uid = hsb->s_uid;
266		inode->i_gid = hsb->s_gid;
267
268		memset(HFS_I(inode), 0, sizeof(struct hfs_inode_info));
269		HFS_I(inode)->magic = HFS_INO_MAGIC;
270		HFS_I(inode)->entry = entry;
271		HFS_I(inode)->tz_secondswest = hfs_to_utc(0);
272
273		hsb->s_ifill(inode, type, hsb->s_version);
274		if (!hsb->s_afpd && (entry->type == HFS_CDR_FIL) &&
275		    (entry->u.file.flags & HFS_FIL_LOCK)) {
276			inode->i_mode &= ~S_IWUGO;
277		}
278		inode->i_mode &= ~hsb->s_umask;
279
280		if (!inode->i_mode) {
281			iput(inode); /* does an hfs_cat_put */
282			inode = NULL;
283		} else
284			*sys_entry = dentry; /* cache dentry */
285
286	}
287
288	return inode;
289}
290
291/*================ Scheme-specific functions ================*/
292
293/*
294 * hfs_cap_ifill()
295 *
296 * This function serves the same purpose as a read_inode() function does
297 * in other filesystems.  It is called by __hfs_iget() to fill in
298 * the missing fields of an uninitialized inode under the CAP scheme.
299 */
300void hfs_cap_ifill(struct inode * inode, ino_t type, const int version)
301{
302	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
303
304	HFS_I(inode)->d_drop_op = hfs_cap_drop_dentry;
305	if (type == HFS_CAP_FNDR) {
306		inode->i_size = sizeof(struct hfs_cap_info);
307		inode->i_blocks = 0;
308		inode->i_nlink = 1;
309		inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
310		inode->i_op = &hfs_cap_info_inode_operations;
311		inode->i_fop = &hfs_cap_info_operations;
312	} else if (entry->type == HFS_CDR_FIL) {
313		init_file_inode(inode, (type == HFS_CAP_DATA) ?
314						HFS_FK_DATA : HFS_FK_RSRC);
315		inode->i_op = &hfs_file_inode_operations;
316		inode->i_fop = &hfs_file_operations;
317		inode->i_mapping->a_ops = &hfs_aops;
318		inode->u.hfs_i.mmu_private = inode->i_size;
319	} else { /* Directory */
320		struct hfs_dir *hdir = &entry->u.dir;
321
322		inode->i_blocks = 0;
323		inode->i_size = hdir->files + hdir->dirs + 5;
324		HFS_I(inode)->dir_size = 1;
325		if (type == HFS_CAP_NDIR) {
326			inode->i_mode = S_IRWXUGO | S_IFDIR;
327			inode->i_nlink = hdir->dirs + 4;
328			inode->i_op = &hfs_cap_ndir_inode_operations;
329			inode->i_fop = &hfs_cap_dir_operations;
330			HFS_I(inode)->file_type = HFS_CAP_NORM;
331		} else if (type == HFS_CAP_FDIR) {
332			inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
333			inode->i_nlink = 2;
334			inode->i_op = &hfs_cap_fdir_inode_operations;
335			inode->i_fop = &hfs_cap_dir_operations;
336			HFS_I(inode)->file_type = HFS_CAP_FNDR;
337		} else if (type == HFS_CAP_RDIR) {
338			inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR;
339			inode->i_nlink = 2;
340			inode->i_op = &hfs_cap_rdir_inode_operations;
341			inode->i_fop = &hfs_cap_dir_operations;
342			HFS_I(inode)->file_type = HFS_CAP_RSRC;
343		}
344	}
345}
346
347/*
348 * hfs_dbl_ifill()
349 *
350 * This function serves the same purpose as a read_inode() function does
351 * in other filesystems.  It is called by __hfs_iget() to fill in
352 * the missing fields of an uninitialized inode under the AppleDouble
353 * scheme.
354 */
355void hfs_dbl_ifill(struct inode * inode, ino_t type, const int version)
356{
357	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
358
359	HFS_I(inode)->d_drop_op = hfs_dbl_drop_dentry;
360	if (type == HFS_DBL_HDR) {
361		if (entry->type == HFS_CDR_FIL) {
362			init_file_inode(inode, HFS_FK_RSRC);
363			inode->i_size += HFS_DBL_HDR_LEN;
364			HFS_I(inode)->default_layout = &hfs_dbl_fil_hdr_layout;
365		} else {
366			inode->i_size = HFS_DBL_HDR_LEN;
367			inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
368			inode->i_nlink = 1;
369			HFS_I(inode)->default_layout = &hfs_dbl_dir_hdr_layout;
370		}
371		inode->i_op = &hfs_hdr_inode_operations;
372		inode->i_fop = &hfs_hdr_operations;
373	} else if (entry->type == HFS_CDR_FIL) {
374		init_file_inode(inode, HFS_FK_DATA);
375		inode->i_op = &hfs_file_inode_operations;
376		inode->i_fop = &hfs_file_operations;
377		inode->i_mapping->a_ops = &hfs_aops;
378		inode->u.hfs_i.mmu_private = inode->i_size;
379	} else { /* Directory */
380		struct hfs_dir *hdir = &entry->u.dir;
381
382		inode->i_blocks = 0;
383		inode->i_nlink = hdir->dirs + 2;
384		inode->i_size = 3 + 2 * (hdir->dirs + hdir->files);
385		inode->i_mode = S_IRWXUGO | S_IFDIR;
386		inode->i_op = &hfs_dbl_dir_inode_operations;
387		inode->i_fop = &hfs_dbl_dir_operations;
388		HFS_I(inode)->file_type = HFS_DBL_NORM;
389		HFS_I(inode)->dir_size = 2;
390	}
391}
392
393/*
394 * hfs_nat_ifill()
395 *
396 * This function serves the same purpose as a read_inode() function does
397 * in other filesystems.  It is called by __hfs_iget() to fill in
398 * the missing fields of an uninitialized inode under the Netatalk
399 * scheme.
400 */
401void hfs_nat_ifill(struct inode * inode, ino_t type, const int version)
402{
403	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
404
405	HFS_I(inode)->d_drop_op = hfs_nat_drop_dentry;
406	if (type == HFS_NAT_HDR) {
407		if (entry->type == HFS_CDR_FIL) {
408			init_file_inode(inode, HFS_FK_RSRC);
409			inode->i_size += HFS_NAT_HDR_LEN;
410		} else {
411			inode->i_size = HFS_NAT_HDR_LEN;
412			inode->i_mode = S_IRUGO | S_IWUGO | S_IFREG;
413			inode->i_nlink = 1;
414		}
415		inode->i_op = &hfs_hdr_inode_operations;
416		inode->i_fop = &hfs_hdr_operations;
417		HFS_I(inode)->default_layout = (version == 2) ?
418			&hfs_nat2_hdr_layout : &hfs_nat_hdr_layout;
419	} else if (entry->type == HFS_CDR_FIL) {
420		init_file_inode(inode, HFS_FK_DATA);
421		inode->i_op = &hfs_file_inode_operations;
422		inode->i_fop = &hfs_file_operations;
423		inode->i_mapping->a_ops = &hfs_aops;
424		inode->u.hfs_i.mmu_private = inode->i_size;
425	} else { /* Directory */
426		struct hfs_dir *hdir = &entry->u.dir;
427
428		inode->i_blocks = 0;
429		inode->i_size = hdir->files + hdir->dirs + 4;
430		inode->i_mode = S_IRWXUGO | S_IFDIR;
431		HFS_I(inode)->dir_size = 1;
432		if (type == HFS_NAT_NDIR) {
433			inode->i_nlink = hdir->dirs + 3;
434			inode->i_op = &hfs_nat_ndir_inode_operations;
435			HFS_I(inode)->file_type = HFS_NAT_NORM;
436		} else if (type == HFS_NAT_HDIR) {
437			inode->i_nlink = 2;
438			inode->i_op = &hfs_nat_hdir_inode_operations;
439			HFS_I(inode)->file_type = HFS_NAT_HDR;
440		}
441		inode->i_fop = &hfs_nat_dir_operations;
442	}
443}
444