1/*
2 *  linux/fs/affs/amigaffs.c
3 *
4 *  (c) 1996  Hans-Joachim Widmaier - Rewritten
5 *
6 *  (C) 1993  Ray Burr - Amiga FFS filesystem.
7 *
8 *  Please send bug reports to: hjw@zvw.de
9 */
10
11#include "affs.h"
12
13/*
14 * Functions for accessing Amiga-FFS structures.
15 */
16
17
18/* Insert a header block bh into the directory dir
19 * caller must hold AFFS_DIR->i_hash_lock!
20 */
21
22int
23affs_insert_hash(struct inode *dir, struct buffer_head *bh)
24{
25	struct super_block *sb = dir->i_sb;
26	struct buffer_head *dir_bh;
27	u32 ino, hash_ino;
28	int offset;
29
30	ino = bh->b_blocknr;
31	offset = affs_hash_name(sb, AFFS_TAIL(sb, bh)->name + 1, AFFS_TAIL(sb, bh)->name[0]);
32
33	pr_debug("%s(dir=%lu, ino=%d)\n", __func__, dir->i_ino, ino);
34
35	dir_bh = affs_bread(sb, dir->i_ino);
36	if (!dir_bh)
37		return -EIO;
38
39	hash_ino = be32_to_cpu(AFFS_HEAD(dir_bh)->table[offset]);
40	while (hash_ino) {
41		affs_brelse(dir_bh);
42		dir_bh = affs_bread(sb, hash_ino);
43		if (!dir_bh)
44			return -EIO;
45		hash_ino = be32_to_cpu(AFFS_TAIL(sb, dir_bh)->hash_chain);
46	}
47	AFFS_TAIL(sb, bh)->parent = cpu_to_be32(dir->i_ino);
48	AFFS_TAIL(sb, bh)->hash_chain = 0;
49	affs_fix_checksum(sb, bh);
50
51	if (dir->i_ino == dir_bh->b_blocknr)
52		AFFS_HEAD(dir_bh)->table[offset] = cpu_to_be32(ino);
53	else
54		AFFS_TAIL(sb, dir_bh)->hash_chain = cpu_to_be32(ino);
55
56	affs_adjust_checksum(dir_bh, ino);
57	mark_buffer_dirty_inode(dir_bh, dir);
58	affs_brelse(dir_bh);
59
60	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
61	dir->i_version++;
62	mark_inode_dirty(dir);
63
64	return 0;
65}
66
67/* Remove a header block from its directory.
68 * caller must hold AFFS_DIR->i_hash_lock!
69 */
70
71int
72affs_remove_hash(struct inode *dir, struct buffer_head *rem_bh)
73{
74	struct super_block *sb;
75	struct buffer_head *bh;
76	u32 rem_ino, hash_ino;
77	__be32 ino;
78	int offset, retval;
79
80	sb = dir->i_sb;
81	rem_ino = rem_bh->b_blocknr;
82	offset = affs_hash_name(sb, AFFS_TAIL(sb, rem_bh)->name+1, AFFS_TAIL(sb, rem_bh)->name[0]);
83	pr_debug("%s(dir=%lu, ino=%d, hashval=%d)\n", __func__, dir->i_ino,
84		 rem_ino, offset);
85
86	bh = affs_bread(sb, dir->i_ino);
87	if (!bh)
88		return -EIO;
89
90	retval = -ENOENT;
91	hash_ino = be32_to_cpu(AFFS_HEAD(bh)->table[offset]);
92	while (hash_ino) {
93		if (hash_ino == rem_ino) {
94			ino = AFFS_TAIL(sb, rem_bh)->hash_chain;
95			if (dir->i_ino == bh->b_blocknr)
96				AFFS_HEAD(bh)->table[offset] = ino;
97			else
98				AFFS_TAIL(sb, bh)->hash_chain = ino;
99			affs_adjust_checksum(bh, be32_to_cpu(ino) - hash_ino);
100			mark_buffer_dirty_inode(bh, dir);
101			AFFS_TAIL(sb, rem_bh)->parent = 0;
102			retval = 0;
103			break;
104		}
105		affs_brelse(bh);
106		bh = affs_bread(sb, hash_ino);
107		if (!bh)
108			return -EIO;
109		hash_ino = be32_to_cpu(AFFS_TAIL(sb, bh)->hash_chain);
110	}
111
112	affs_brelse(bh);
113
114	dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
115	dir->i_version++;
116	mark_inode_dirty(dir);
117
118	return retval;
119}
120
121static void
122affs_fix_dcache(struct inode *inode, u32 entry_ino)
123{
124	struct dentry *dentry;
125	spin_lock(&inode->i_lock);
126	hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
127		if (entry_ino == (u32)(long)dentry->d_fsdata) {
128			dentry->d_fsdata = (void *)inode->i_ino;
129			break;
130		}
131	}
132	spin_unlock(&inode->i_lock);
133}
134
135
136/* Remove header from link chain */
137
138static int
139affs_remove_link(struct dentry *dentry)
140{
141	struct inode *dir, *inode = d_inode(dentry);
142	struct super_block *sb = inode->i_sb;
143	struct buffer_head *bh = NULL, *link_bh = NULL;
144	u32 link_ino, ino;
145	int retval;
146
147	pr_debug("%s(key=%ld)\n", __func__, inode->i_ino);
148	retval = -EIO;
149	bh = affs_bread(sb, inode->i_ino);
150	if (!bh)
151		goto done;
152
153	link_ino = (u32)(long)dentry->d_fsdata;
154	if (inode->i_ino == link_ino) {
155		/* we can't remove the head of the link, as its blocknr is still used as ino,
156		 * so we remove the block of the first link instead.
157		 */
158		link_ino = be32_to_cpu(AFFS_TAIL(sb, bh)->link_chain);
159		link_bh = affs_bread(sb, link_ino);
160		if (!link_bh)
161			goto done;
162
163		dir = affs_iget(sb, be32_to_cpu(AFFS_TAIL(sb, link_bh)->parent));
164		if (IS_ERR(dir)) {
165			retval = PTR_ERR(dir);
166			goto done;
167		}
168
169		affs_lock_dir(dir);
170		/*
171		 * if there's a dentry for that block, make it
172		 * refer to inode itself.
173		 */
174		affs_fix_dcache(inode, link_ino);
175		retval = affs_remove_hash(dir, link_bh);
176		if (retval) {
177			affs_unlock_dir(dir);
178			goto done;
179		}
180		mark_buffer_dirty_inode(link_bh, inode);
181
182		memcpy(AFFS_TAIL(sb, bh)->name, AFFS_TAIL(sb, link_bh)->name, 32);
183		retval = affs_insert_hash(dir, bh);
184		if (retval) {
185			affs_unlock_dir(dir);
186			goto done;
187		}
188		mark_buffer_dirty_inode(bh, inode);
189
190		affs_unlock_dir(dir);
191		iput(dir);
192	} else {
193		link_bh = affs_bread(sb, link_ino);
194		if (!link_bh)
195			goto done;
196	}
197
198	while ((ino = be32_to_cpu(AFFS_TAIL(sb, bh)->link_chain)) != 0) {
199		if (ino == link_ino) {
200			__be32 ino2 = AFFS_TAIL(sb, link_bh)->link_chain;
201			AFFS_TAIL(sb, bh)->link_chain = ino2;
202			affs_adjust_checksum(bh, be32_to_cpu(ino2) - link_ino);
203			mark_buffer_dirty_inode(bh, inode);
204			retval = 0;
205			/* Fix the link count, if bh is a normal header block without links */
206			switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) {
207			case ST_LINKDIR:
208			case ST_LINKFILE:
209				break;
210			default:
211				if (!AFFS_TAIL(sb, bh)->link_chain)
212					set_nlink(inode, 1);
213			}
214			affs_free_block(sb, link_ino);
215			goto done;
216		}
217		affs_brelse(bh);
218		bh = affs_bread(sb, ino);
219		if (!bh)
220			goto done;
221	}
222	retval = -ENOENT;
223done:
224	affs_brelse(link_bh);
225	affs_brelse(bh);
226	return retval;
227}
228
229
230static int
231affs_empty_dir(struct inode *inode)
232{
233	struct super_block *sb = inode->i_sb;
234	struct buffer_head *bh;
235	int retval, size;
236
237	retval = -EIO;
238	bh = affs_bread(sb, inode->i_ino);
239	if (!bh)
240		goto done;
241
242	retval = -ENOTEMPTY;
243	for (size = AFFS_SB(sb)->s_hashsize - 1; size >= 0; size--)
244		if (AFFS_HEAD(bh)->table[size])
245			goto not_empty;
246	retval = 0;
247not_empty:
248	affs_brelse(bh);
249done:
250	return retval;
251}
252
253
254/* Remove a filesystem object. If the object to be removed has
255 * links to it, one of the links must be changed to inherit
256 * the file or directory. As above, any inode will do.
257 * The buffer will not be freed. If the header is a link, the
258 * block will be marked as free.
259 * This function returns a negative error number in case of
260 * an error, else 0 if the inode is to be deleted or 1 if not.
261 */
262
263int
264affs_remove_header(struct dentry *dentry)
265{
266	struct super_block *sb;
267	struct inode *inode, *dir;
268	struct buffer_head *bh = NULL;
269	int retval;
270
271	dir = d_inode(dentry->d_parent);
272	sb = dir->i_sb;
273
274	retval = -ENOENT;
275	inode = d_inode(dentry);
276	if (!inode)
277		goto done;
278
279	pr_debug("%s(key=%ld)\n", __func__, inode->i_ino);
280	retval = -EIO;
281	bh = affs_bread(sb, (u32)(long)dentry->d_fsdata);
282	if (!bh)
283		goto done;
284
285	affs_lock_link(inode);
286	affs_lock_dir(dir);
287	switch (be32_to_cpu(AFFS_TAIL(sb, bh)->stype)) {
288	case ST_USERDIR:
289		/* if we ever want to support links to dirs
290		 * i_hash_lock of the inode must only be
291		 * taken after some checks
292		 */
293		affs_lock_dir(inode);
294		retval = affs_empty_dir(inode);
295		affs_unlock_dir(inode);
296		if (retval)
297			goto done_unlock;
298		break;
299	default:
300		break;
301	}
302
303	retval = affs_remove_hash(dir, bh);
304	if (retval)
305		goto done_unlock;
306	mark_buffer_dirty_inode(bh, inode);
307
308	affs_unlock_dir(dir);
309
310	if (inode->i_nlink > 1)
311		retval = affs_remove_link(dentry);
312	else
313		clear_nlink(inode);
314	affs_unlock_link(inode);
315	inode->i_ctime = CURRENT_TIME_SEC;
316	mark_inode_dirty(inode);
317
318done:
319	affs_brelse(bh);
320	return retval;
321
322done_unlock:
323	affs_unlock_dir(dir);
324	affs_unlock_link(inode);
325	goto done;
326}
327
328/* Checksum a block, do various consistency checks and optionally return
329   the blocks type number.  DATA points to the block.  If their pointers
330   are non-null, *PTYPE and *STYPE are set to the primary and secondary
331   block types respectively, *HASHSIZE is set to the size of the hashtable
332   (which lets us calculate the block size).
333   Returns non-zero if the block is not consistent. */
334
335u32
336affs_checksum_block(struct super_block *sb, struct buffer_head *bh)
337{
338	__be32 *ptr = (__be32 *)bh->b_data;
339	u32 sum;
340	int bsize;
341
342	sum = 0;
343	for (bsize = sb->s_blocksize / sizeof(__be32); bsize > 0; bsize--)
344		sum += be32_to_cpu(*ptr++);
345	return sum;
346}
347
348/*
349 * Calculate the checksum of a disk block and store it
350 * at the indicated position.
351 */
352
353void
354affs_fix_checksum(struct super_block *sb, struct buffer_head *bh)
355{
356	int cnt = sb->s_blocksize / sizeof(__be32);
357	__be32 *ptr = (__be32 *)bh->b_data;
358	u32 checksum;
359	__be32 *checksumptr;
360
361	checksumptr = ptr + 5;
362	*checksumptr = 0;
363	for (checksum = 0; cnt > 0; ptr++, cnt--)
364		checksum += be32_to_cpu(*ptr);
365	*checksumptr = cpu_to_be32(-checksum);
366}
367
368void
369secs_to_datestamp(time_t secs, struct affs_date *ds)
370{
371	u32	 days;
372	u32	 minute;
373
374	secs -= sys_tz.tz_minuteswest * 60 + ((8 * 365 + 2) * 24 * 60 * 60);
375	if (secs < 0)
376		secs = 0;
377	days    = secs / 86400;
378	secs   -= days * 86400;
379	minute  = secs / 60;
380	secs   -= minute * 60;
381
382	ds->days = cpu_to_be32(days);
383	ds->mins = cpu_to_be32(minute);
384	ds->ticks = cpu_to_be32(secs * 50);
385}
386
387umode_t
388prot_to_mode(u32 prot)
389{
390	umode_t mode = 0;
391
392	if (!(prot & FIBF_NOWRITE))
393		mode |= S_IWUSR;
394	if (!(prot & FIBF_NOREAD))
395		mode |= S_IRUSR;
396	if (!(prot & FIBF_NOEXECUTE))
397		mode |= S_IXUSR;
398	if (prot & FIBF_GRP_WRITE)
399		mode |= S_IWGRP;
400	if (prot & FIBF_GRP_READ)
401		mode |= S_IRGRP;
402	if (prot & FIBF_GRP_EXECUTE)
403		mode |= S_IXGRP;
404	if (prot & FIBF_OTR_WRITE)
405		mode |= S_IWOTH;
406	if (prot & FIBF_OTR_READ)
407		mode |= S_IROTH;
408	if (prot & FIBF_OTR_EXECUTE)
409		mode |= S_IXOTH;
410
411	return mode;
412}
413
414void
415mode_to_prot(struct inode *inode)
416{
417	u32 prot = AFFS_I(inode)->i_protect;
418	umode_t mode = inode->i_mode;
419
420	if (!(mode & S_IXUSR))
421		prot |= FIBF_NOEXECUTE;
422	if (!(mode & S_IRUSR))
423		prot |= FIBF_NOREAD;
424	if (!(mode & S_IWUSR))
425		prot |= FIBF_NOWRITE;
426	if (mode & S_IXGRP)
427		prot |= FIBF_GRP_EXECUTE;
428	if (mode & S_IRGRP)
429		prot |= FIBF_GRP_READ;
430	if (mode & S_IWGRP)
431		prot |= FIBF_GRP_WRITE;
432	if (mode & S_IXOTH)
433		prot |= FIBF_OTR_EXECUTE;
434	if (mode & S_IROTH)
435		prot |= FIBF_OTR_READ;
436	if (mode & S_IWOTH)
437		prot |= FIBF_OTR_WRITE;
438
439	AFFS_I(inode)->i_protect = prot;
440}
441
442void
443affs_error(struct super_block *sb, const char *function, const char *fmt, ...)
444{
445	struct va_format vaf;
446	va_list args;
447
448	va_start(args, fmt);
449	vaf.fmt = fmt;
450	vaf.va = &args;
451	pr_crit("error (device %s): %s(): %pV\n", sb->s_id, function, &vaf);
452	if (!(sb->s_flags & MS_RDONLY))
453		pr_warn("Remounting filesystem read-only\n");
454	sb->s_flags |= MS_RDONLY;
455	va_end(args);
456}
457
458void
459affs_warning(struct super_block *sb, const char *function, const char *fmt, ...)
460{
461	struct va_format vaf;
462	va_list args;
463
464	va_start(args, fmt);
465	vaf.fmt = fmt;
466	vaf.va = &args;
467	pr_warn("(device %s): %s(): %pV\n", sb->s_id, function, &vaf);
468	va_end(args);
469}
470
471bool
472affs_nofilenametruncate(const struct dentry *dentry)
473{
474	struct inode *inode = d_inode(dentry);
475
476	return affs_test_opt(AFFS_SB(inode->i_sb)->s_flags, SF_NO_TRUNCATE);
477}
478
479/* Check if the name is valid for a affs object. */
480
481int
482affs_check_name(const unsigned char *name, int len, bool notruncate)
483{
484	int	 i;
485
486	if (len > AFFSNAMEMAX) {
487		if (notruncate)
488			return -ENAMETOOLONG;
489		len = AFFSNAMEMAX;
490	}
491	for (i = 0; i < len; i++) {
492		if (name[i] < ' ' || name[i] == ':'
493		    || (name[i] > 0x7e && name[i] < 0xa0))
494			return -EINVAL;
495	}
496
497	return 0;
498}
499
500/* This function copies name to bstr, with at most 30
501 * characters length. The bstr will be prepended by
502 * a length byte.
503 * NOTE: The name will must be already checked by
504 *       affs_check_name()!
505 */
506
507int
508affs_copy_name(unsigned char *bstr, struct dentry *dentry)
509{
510	u32 len = min(dentry->d_name.len, AFFSNAMEMAX);
511
512	*bstr++ = len;
513	memcpy(bstr, dentry->d_name.name, len);
514	return len;
515}
516