Linux Audio

Check our new training course

Loading...
v4.6
 
  1/*
  2 *  linux/fs/hpfs/namei.c
  3 *
  4 *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
  5 *
  6 *  adding & removing files & directories
  7 */
  8#include <linux/sched.h>
  9#include "hpfs_fn.h"
 10
 11static void hpfs_update_directory_times(struct inode *dir)
 12{
 13	time_t t = get_seconds();
 14	if (t == dir->i_mtime.tv_sec &&
 15	    t == dir->i_ctime.tv_sec)
 16		return;
 17	dir->i_mtime.tv_sec = dir->i_ctime.tv_sec = t;
 18	dir->i_mtime.tv_nsec = dir->i_ctime.tv_nsec = 0;
 19	hpfs_write_inode_nolock(dir);
 20}
 21
 22static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 
 23{
 24	const unsigned char *name = dentry->d_name.name;
 25	unsigned len = dentry->d_name.len;
 26	struct quad_buffer_head qbh0;
 27	struct buffer_head *bh;
 28	struct hpfs_dirent *de;
 29	struct fnode *fnode;
 30	struct dnode *dnode;
 31	struct inode *result;
 32	fnode_secno fno;
 33	dnode_secno dno;
 34	int r;
 35	struct hpfs_dirent dee;
 36	int err;
 37	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
 38	hpfs_lock(dir->i_sb);
 39	err = -ENOSPC;
 40	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
 41	if (!fnode)
 42		goto bail;
 43	dnode = hpfs_alloc_dnode(dir->i_sb, fno, &dno, &qbh0);
 44	if (!dnode)
 45		goto bail1;
 46	memset(&dee, 0, sizeof dee);
 47	dee.directory = 1;
 48	if (!(mode & 0222)) dee.read_only = 1;
 49	/*dee.archive = 0;*/
 50	dee.hidden = name[0] == '.';
 51	dee.fnode = cpu_to_le32(fno);
 52	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
 53	result = new_inode(dir->i_sb);
 54	if (!result)
 55		goto bail2;
 56	hpfs_init_inode(result);
 57	result->i_ino = fno;
 58	hpfs_i(result)->i_parent_dir = dir->i_ino;
 59	hpfs_i(result)->i_dno = dno;
 60	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
 61	result->i_ctime.tv_nsec = 0; 
 62	result->i_mtime.tv_nsec = 0; 
 63	result->i_atime.tv_nsec = 0; 
 64	hpfs_i(result)->i_ea_size = 0;
 65	result->i_mode |= S_IFDIR;
 66	result->i_op = &hpfs_dir_iops;
 67	result->i_fop = &hpfs_dir_ops;
 68	result->i_blocks = 4;
 69	result->i_size = 2048;
 70	set_nlink(result, 2);
 71	if (dee.read_only)
 72		result->i_mode &= ~0222;
 73
 74	r = hpfs_add_dirent(dir, name, len, &dee);
 75	if (r == 1)
 76		goto bail3;
 77	if (r == -1) {
 78		err = -EEXIST;
 79		goto bail3;
 80	}
 81	fnode->len = len;
 82	memcpy(fnode->name, name, len > 15 ? 15 : len);
 83	fnode->up = cpu_to_le32(dir->i_ino);
 84	fnode->flags |= FNODE_dir;
 85	fnode->btree.n_free_nodes = 7;
 86	fnode->btree.n_used_nodes = 1;
 87	fnode->btree.first_free = cpu_to_le16(0x14);
 88	fnode->u.external[0].disk_secno = cpu_to_le32(dno);
 89	fnode->u.external[0].file_secno = cpu_to_le32(-1);
 90	dnode->root_dnode = 1;
 91	dnode->up = cpu_to_le32(fno);
 92	de = hpfs_add_de(dir->i_sb, dnode, "\001\001", 2, 0);
 93	de->creation_date = de->write_date = de->read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
 94	if (!(mode & 0222)) de->read_only = 1;
 95	de->first = de->directory = 1;
 96	/*de->hidden = de->system = 0;*/
 97	de->fnode = cpu_to_le32(fno);
 98	mark_buffer_dirty(bh);
 99	brelse(bh);
100	hpfs_mark_4buffers_dirty(&qbh0);
101	hpfs_brelse4(&qbh0);
102	inc_nlink(dir);
103	insert_inode_hash(result);
104
105	if (!uid_eq(result->i_uid, current_fsuid()) ||
106	    !gid_eq(result->i_gid, current_fsgid()) ||
107	    result->i_mode != (mode | S_IFDIR)) {
108		result->i_uid = current_fsuid();
109		result->i_gid = current_fsgid();
110		result->i_mode = mode | S_IFDIR;
111		hpfs_write_inode_nolock(result);
112	}
113	hpfs_update_directory_times(dir);
114	d_instantiate(dentry, result);
115	hpfs_unlock(dir->i_sb);
116	return 0;
117bail3:
118	iput(result);
119bail2:
120	hpfs_brelse4(&qbh0);
121	hpfs_free_dnode(dir->i_sb, dno);
122bail1:
123	brelse(bh);
124	hpfs_free_sectors(dir->i_sb, fno, 1);
125bail:
126	hpfs_unlock(dir->i_sb);
127	return err;
128}
129
130static int hpfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
 
131{
132	const unsigned char *name = dentry->d_name.name;
133	unsigned len = dentry->d_name.len;
134	struct inode *result = NULL;
135	struct buffer_head *bh;
136	struct fnode *fnode;
137	fnode_secno fno;
138	int r;
139	struct hpfs_dirent dee;
140	int err;
141	if ((err = hpfs_chk_name(name, &len)))
142		return err==-ENOENT ? -EINVAL : err;
143	hpfs_lock(dir->i_sb);
144	err = -ENOSPC;
145	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
146	if (!fnode)
147		goto bail;
148	memset(&dee, 0, sizeof dee);
149	if (!(mode & 0222)) dee.read_only = 1;
150	dee.archive = 1;
151	dee.hidden = name[0] == '.';
152	dee.fnode = cpu_to_le32(fno);
153	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
154
155	result = new_inode(dir->i_sb);
156	if (!result)
157		goto bail1;
158	
159	hpfs_init_inode(result);
160	result->i_ino = fno;
161	result->i_mode |= S_IFREG;
162	result->i_mode &= ~0111;
163	result->i_op = &hpfs_file_iops;
164	result->i_fop = &hpfs_file_ops;
165	set_nlink(result, 1);
166	hpfs_i(result)->i_parent_dir = dir->i_ino;
167	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
168	result->i_ctime.tv_nsec = 0;
169	result->i_mtime.tv_nsec = 0;
170	result->i_atime.tv_nsec = 0;
171	hpfs_i(result)->i_ea_size = 0;
172	if (dee.read_only)
173		result->i_mode &= ~0222;
174	result->i_blocks = 1;
175	result->i_size = 0;
176	result->i_data.a_ops = &hpfs_aops;
177	hpfs_i(result)->mmu_private = 0;
178
179	r = hpfs_add_dirent(dir, name, len, &dee);
180	if (r == 1)
181		goto bail2;
182	if (r == -1) {
183		err = -EEXIST;
184		goto bail2;
185	}
186	fnode->len = len;
187	memcpy(fnode->name, name, len > 15 ? 15 : len);
188	fnode->up = cpu_to_le32(dir->i_ino);
189	mark_buffer_dirty(bh);
190	brelse(bh);
191
192	insert_inode_hash(result);
193
194	if (!uid_eq(result->i_uid, current_fsuid()) ||
195	    !gid_eq(result->i_gid, current_fsgid()) ||
196	    result->i_mode != (mode | S_IFREG)) {
197		result->i_uid = current_fsuid();
198		result->i_gid = current_fsgid();
199		result->i_mode = mode | S_IFREG;
200		hpfs_write_inode_nolock(result);
201	}
202	hpfs_update_directory_times(dir);
203	d_instantiate(dentry, result);
204	hpfs_unlock(dir->i_sb);
205	return 0;
206
207bail2:
208	iput(result);
209bail1:
210	brelse(bh);
211	hpfs_free_sectors(dir->i_sb, fno, 1);
212bail:
213	hpfs_unlock(dir->i_sb);
214	return err;
215}
216
217static int hpfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
 
218{
219	const unsigned char *name = dentry->d_name.name;
220	unsigned len = dentry->d_name.len;
221	struct buffer_head *bh;
222	struct fnode *fnode;
223	fnode_secno fno;
224	int r;
225	struct hpfs_dirent dee;
226	struct inode *result = NULL;
227	int err;
228	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
229	if (hpfs_sb(dir->i_sb)->sb_eas < 2) return -EPERM;
230	hpfs_lock(dir->i_sb);
231	err = -ENOSPC;
232	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
233	if (!fnode)
234		goto bail;
235	memset(&dee, 0, sizeof dee);
236	if (!(mode & 0222)) dee.read_only = 1;
237	dee.archive = 1;
238	dee.hidden = name[0] == '.';
239	dee.fnode = cpu_to_le32(fno);
240	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
241
242	result = new_inode(dir->i_sb);
243	if (!result)
244		goto bail1;
245
246	hpfs_init_inode(result);
247	result->i_ino = fno;
248	hpfs_i(result)->i_parent_dir = dir->i_ino;
249	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
250	result->i_ctime.tv_nsec = 0;
251	result->i_mtime.tv_nsec = 0;
252	result->i_atime.tv_nsec = 0;
253	hpfs_i(result)->i_ea_size = 0;
254	result->i_uid = current_fsuid();
255	result->i_gid = current_fsgid();
256	set_nlink(result, 1);
257	result->i_size = 0;
258	result->i_blocks = 1;
259	init_special_inode(result, mode, rdev);
260
261	r = hpfs_add_dirent(dir, name, len, &dee);
262	if (r == 1)
263		goto bail2;
264	if (r == -1) {
265		err = -EEXIST;
266		goto bail2;
267	}
268	fnode->len = len;
269	memcpy(fnode->name, name, len > 15 ? 15 : len);
270	fnode->up = cpu_to_le32(dir->i_ino);
271	mark_buffer_dirty(bh);
272
273	insert_inode_hash(result);
274
275	hpfs_write_inode_nolock(result);
276	hpfs_update_directory_times(dir);
277	d_instantiate(dentry, result);
278	brelse(bh);
279	hpfs_unlock(dir->i_sb);
280	return 0;
281bail2:
282	iput(result);
283bail1:
284	brelse(bh);
285	hpfs_free_sectors(dir->i_sb, fno, 1);
286bail:
287	hpfs_unlock(dir->i_sb);
288	return err;
289}
290
291static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink)
 
292{
293	const unsigned char *name = dentry->d_name.name;
294	unsigned len = dentry->d_name.len;
295	struct buffer_head *bh;
296	struct fnode *fnode;
297	fnode_secno fno;
298	int r;
299	struct hpfs_dirent dee;
300	struct inode *result;
301	int err;
302	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
303	hpfs_lock(dir->i_sb);
304	if (hpfs_sb(dir->i_sb)->sb_eas < 2) {
305		hpfs_unlock(dir->i_sb);
306		return -EPERM;
307	}
308	err = -ENOSPC;
309	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
310	if (!fnode)
311		goto bail;
312	memset(&dee, 0, sizeof dee);
313	dee.archive = 1;
314	dee.hidden = name[0] == '.';
315	dee.fnode = cpu_to_le32(fno);
316	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
317
318	result = new_inode(dir->i_sb);
319	if (!result)
320		goto bail1;
321	result->i_ino = fno;
322	hpfs_init_inode(result);
323	hpfs_i(result)->i_parent_dir = dir->i_ino;
324	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
325	result->i_ctime.tv_nsec = 0;
326	result->i_mtime.tv_nsec = 0;
327	result->i_atime.tv_nsec = 0;
328	hpfs_i(result)->i_ea_size = 0;
329	result->i_mode = S_IFLNK | 0777;
330	result->i_uid = current_fsuid();
331	result->i_gid = current_fsgid();
332	result->i_blocks = 1;
333	set_nlink(result, 1);
334	result->i_size = strlen(symlink);
335	inode_nohighmem(result);
336	result->i_op = &page_symlink_inode_operations;
337	result->i_data.a_ops = &hpfs_symlink_aops;
338
339	r = hpfs_add_dirent(dir, name, len, &dee);
340	if (r == 1)
341		goto bail2;
342	if (r == -1) {
343		err = -EEXIST;
344		goto bail2;
345	}
346	fnode->len = len;
347	memcpy(fnode->name, name, len > 15 ? 15 : len);
348	fnode->up = cpu_to_le32(dir->i_ino);
349	hpfs_set_ea(result, fnode, "SYMLINK", symlink, strlen(symlink));
350	mark_buffer_dirty(bh);
351	brelse(bh);
352
353	insert_inode_hash(result);
354
355	hpfs_write_inode_nolock(result);
356	hpfs_update_directory_times(dir);
357	d_instantiate(dentry, result);
358	hpfs_unlock(dir->i_sb);
359	return 0;
360bail2:
361	iput(result);
362bail1:
363	brelse(bh);
364	hpfs_free_sectors(dir->i_sb, fno, 1);
365bail:
366	hpfs_unlock(dir->i_sb);
367	return err;
368}
369
370static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
371{
372	const unsigned char *name = dentry->d_name.name;
373	unsigned len = dentry->d_name.len;
374	struct quad_buffer_head qbh;
375	struct hpfs_dirent *de;
376	struct inode *inode = d_inode(dentry);
377	dnode_secno dno;
378	int r;
379	int err;
380
381	hpfs_lock(dir->i_sb);
382	hpfs_adjust_length(name, &len);
383
384	err = -ENOENT;
385	de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
386	if (!de)
387		goto out;
388
389	err = -EPERM;
390	if (de->first)
391		goto out1;
392
393	err = -EISDIR;
394	if (de->directory)
395		goto out1;
396
397	r = hpfs_remove_dirent(dir, dno, de, &qbh, 1);
398	switch (r) {
399	case 1:
400		hpfs_error(dir->i_sb, "there was error when removing dirent");
401		err = -EFSERROR;
402		break;
403	case 2:		/* no space for deleting */
404		err = -ENOSPC;
405		break;
406	default:
407		drop_nlink(inode);
408		err = 0;
409	}
410	goto out;
411
412out1:
413	hpfs_brelse4(&qbh);
414out:
415	if (!err)
416		hpfs_update_directory_times(dir);
417	hpfs_unlock(dir->i_sb);
418	return err;
419}
420
421static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
422{
423	const unsigned char *name = dentry->d_name.name;
424	unsigned len = dentry->d_name.len;
425	struct quad_buffer_head qbh;
426	struct hpfs_dirent *de;
427	struct inode *inode = d_inode(dentry);
428	dnode_secno dno;
429	int n_items = 0;
430	int err;
431	int r;
432
433	hpfs_adjust_length(name, &len);
434	hpfs_lock(dir->i_sb);
435	err = -ENOENT;
436	de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
437	if (!de)
438		goto out;
439
440	err = -EPERM;
441	if (de->first)
442		goto out1;
443
444	err = -ENOTDIR;
445	if (!de->directory)
446		goto out1;
447
448	hpfs_count_dnodes(dir->i_sb, hpfs_i(inode)->i_dno, NULL, NULL, &n_items);
449	err = -ENOTEMPTY;
450	if (n_items)
451		goto out1;
452
453	r = hpfs_remove_dirent(dir, dno, de, &qbh, 1);
454	switch (r) {
455	case 1:
456		hpfs_error(dir->i_sb, "there was error when removing dirent");
457		err = -EFSERROR;
458		break;
459	case 2:
460		err = -ENOSPC;
461		break;
462	default:
463		drop_nlink(dir);
464		clear_nlink(inode);
465		err = 0;
466	}
467	goto out;
468out1:
469	hpfs_brelse4(&qbh);
470out:
471	if (!err)
472		hpfs_update_directory_times(dir);
473	hpfs_unlock(dir->i_sb);
474	return err;
475}
476
477static int hpfs_symlink_readpage(struct file *file, struct page *page)
478{
 
479	char *link = page_address(page);
480	struct inode *i = page->mapping->host;
481	struct fnode *fnode;
482	struct buffer_head *bh;
483	int err;
484
485	err = -EIO;
486	hpfs_lock(i->i_sb);
487	if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh)))
488		goto fail;
489	err = hpfs_read_ea(i->i_sb, fnode, "SYMLINK", link, PAGE_SIZE);
490	brelse(bh);
491	if (err)
492		goto fail;
493	hpfs_unlock(i->i_sb);
494	SetPageUptodate(page);
495	unlock_page(page);
496	return 0;
497
498fail:
499	hpfs_unlock(i->i_sb);
500	SetPageError(page);
501	unlock_page(page);
502	return err;
503}
504
505const struct address_space_operations hpfs_symlink_aops = {
506	.readpage	= hpfs_symlink_readpage
507};
508	
509static int hpfs_rename(struct inode *old_dir, struct dentry *old_dentry,
510		struct inode *new_dir, struct dentry *new_dentry)
 
511{
512	const unsigned char *old_name = old_dentry->d_name.name;
513	unsigned old_len = old_dentry->d_name.len;
514	const unsigned char *new_name = new_dentry->d_name.name;
515	unsigned new_len = new_dentry->d_name.len;
516	struct inode *i = d_inode(old_dentry);
517	struct inode *new_inode = d_inode(new_dentry);
518	struct quad_buffer_head qbh, qbh1;
519	struct hpfs_dirent *dep, *nde;
520	struct hpfs_dirent de;
521	dnode_secno dno;
522	int r;
523	struct buffer_head *bh;
524	struct fnode *fnode;
525	int err;
526
 
 
 
527	if ((err = hpfs_chk_name(new_name, &new_len))) return err;
528	err = 0;
529	hpfs_adjust_length(old_name, &old_len);
530
531	hpfs_lock(i->i_sb);
532	/* order doesn't matter, due to VFS exclusion */
533	
534	/* Erm? Moving over the empty non-busy directory is perfectly legal */
535	if (new_inode && S_ISDIR(new_inode->i_mode)) {
536		err = -EINVAL;
537		goto end1;
538	}
539
540	if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) {
541		hpfs_error(i->i_sb, "lookup succeeded but map dirent failed");
542		err = -ENOENT;
543		goto end1;
544	}
545	copy_de(&de, dep);
546	de.hidden = new_name[0] == '.';
547
548	if (new_inode) {
549		int r;
550		if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 1)) != 2) {
551			if ((nde = map_dirent(new_dir, hpfs_i(new_dir)->i_dno, new_name, new_len, NULL, &qbh1))) {
552				clear_nlink(new_inode);
553				copy_de(nde, &de);
554				memcpy(nde->name, new_name, new_len);
555				hpfs_mark_4buffers_dirty(&qbh1);
556				hpfs_brelse4(&qbh1);
557				goto end;
558			}
559			hpfs_error(new_dir->i_sb, "hpfs_rename: could not find dirent");
560			err = -EFSERROR;
561			goto end1;
562		}
563		err = r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
564		goto end1;
565	}
566
567	if (new_dir == old_dir) hpfs_brelse4(&qbh);
568
569	if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de))) {
570		if (r == -1) hpfs_error(new_dir->i_sb, "hpfs_rename: dirent already exists!");
571		err = r == 1 ? -ENOSPC : -EFSERROR;
572		if (new_dir != old_dir) hpfs_brelse4(&qbh);
573		goto end1;
574	}
575	
576	if (new_dir == old_dir)
577		if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) {
578			hpfs_error(i->i_sb, "lookup succeeded but map dirent failed at #2");
579			err = -ENOENT;
580			goto end1;
581		}
582
583	if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 0))) {
584		hpfs_error(i->i_sb, "hpfs_rename: could not remove dirent");
585		err = r == 2 ? -ENOSPC : -EFSERROR;
586		goto end1;
587	}
588
589end:
590	hpfs_i(i)->i_parent_dir = new_dir->i_ino;
591	if (S_ISDIR(i->i_mode)) {
592		inc_nlink(new_dir);
593		drop_nlink(old_dir);
594	}
595	if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
596		fnode->up = cpu_to_le32(new_dir->i_ino);
597		fnode->len = new_len;
598		memcpy(fnode->name, new_name, new_len>15?15:new_len);
599		if (new_len < 15) memset(&fnode->name[new_len], 0, 15 - new_len);
600		mark_buffer_dirty(bh);
601		brelse(bh);
602	}
603end1:
604	if (!err) {
605		hpfs_update_directory_times(old_dir);
606		hpfs_update_directory_times(new_dir);
607	}
608	hpfs_unlock(i->i_sb);
609	return err;
610}
611
612const struct inode_operations hpfs_dir_iops =
613{
614	.create		= hpfs_create,
615	.lookup		= hpfs_lookup,
616	.unlink		= hpfs_unlink,
617	.symlink	= hpfs_symlink,
618	.mkdir		= hpfs_mkdir,
619	.rmdir		= hpfs_rmdir,
620	.mknod		= hpfs_mknod,
621	.rename		= hpfs_rename,
622	.setattr	= hpfs_setattr,
623};
v6.8
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 *  linux/fs/hpfs/namei.c
  4 *
  5 *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
  6 *
  7 *  adding & removing files & directories
  8 */
  9#include <linux/sched.h>
 10#include "hpfs_fn.h"
 11
 12static void hpfs_update_directory_times(struct inode *dir)
 13{
 14	time64_t t = local_to_gmt(dir->i_sb, local_get_seconds(dir->i_sb));
 15	if (t == inode_get_mtime_sec(dir) &&
 16	    t == inode_get_ctime_sec(dir))
 17		return;
 18	inode_set_mtime_to_ts(dir, inode_set_ctime(dir, t, 0));
 
 19	hpfs_write_inode_nolock(dir);
 20}
 21
 22static int hpfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
 23		      struct dentry *dentry, umode_t mode)
 24{
 25	const unsigned char *name = dentry->d_name.name;
 26	unsigned len = dentry->d_name.len;
 27	struct quad_buffer_head qbh0;
 28	struct buffer_head *bh;
 29	struct hpfs_dirent *de;
 30	struct fnode *fnode;
 31	struct dnode *dnode;
 32	struct inode *result;
 33	fnode_secno fno;
 34	dnode_secno dno;
 35	int r;
 36	struct hpfs_dirent dee;
 37	int err;
 38	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
 39	hpfs_lock(dir->i_sb);
 40	err = -ENOSPC;
 41	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
 42	if (!fnode)
 43		goto bail;
 44	dnode = hpfs_alloc_dnode(dir->i_sb, fno, &dno, &qbh0);
 45	if (!dnode)
 46		goto bail1;
 47	memset(&dee, 0, sizeof dee);
 48	dee.directory = 1;
 49	if (!(mode & 0222)) dee.read_only = 1;
 50	/*dee.archive = 0;*/
 51	dee.hidden = name[0] == '.';
 52	dee.fnode = cpu_to_le32(fno);
 53	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(local_get_seconds(dir->i_sb));
 54	result = new_inode(dir->i_sb);
 55	if (!result)
 56		goto bail2;
 57	hpfs_init_inode(result);
 58	result->i_ino = fno;
 59	hpfs_i(result)->i_parent_dir = dir->i_ino;
 60	hpfs_i(result)->i_dno = dno;
 61	inode_set_mtime_to_ts(result,
 62			      inode_set_atime_to_ts(result, inode_set_ctime(result, local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date)), 0)));
 
 
 63	hpfs_i(result)->i_ea_size = 0;
 64	result->i_mode |= S_IFDIR;
 65	result->i_op = &hpfs_dir_iops;
 66	result->i_fop = &hpfs_dir_ops;
 67	result->i_blocks = 4;
 68	result->i_size = 2048;
 69	set_nlink(result, 2);
 70	if (dee.read_only)
 71		result->i_mode &= ~0222;
 72
 73	r = hpfs_add_dirent(dir, name, len, &dee);
 74	if (r == 1)
 75		goto bail3;
 76	if (r == -1) {
 77		err = -EEXIST;
 78		goto bail3;
 79	}
 80	fnode->len = len;
 81	memcpy(fnode->name, name, len > 15 ? 15 : len);
 82	fnode->up = cpu_to_le32(dir->i_ino);
 83	fnode->flags |= FNODE_dir;
 84	fnode->btree.n_free_nodes = 7;
 85	fnode->btree.n_used_nodes = 1;
 86	fnode->btree.first_free = cpu_to_le16(0x14);
 87	fnode->u.external[0].disk_secno = cpu_to_le32(dno);
 88	fnode->u.external[0].file_secno = cpu_to_le32(-1);
 89	dnode->root_dnode = 1;
 90	dnode->up = cpu_to_le32(fno);
 91	de = hpfs_add_de(dir->i_sb, dnode, "\001\001", 2, 0);
 92	de->creation_date = de->write_date = de->read_date = cpu_to_le32(local_get_seconds(dir->i_sb));
 93	if (!(mode & 0222)) de->read_only = 1;
 94	de->first = de->directory = 1;
 95	/*de->hidden = de->system = 0;*/
 96	de->fnode = cpu_to_le32(fno);
 97	mark_buffer_dirty(bh);
 98	brelse(bh);
 99	hpfs_mark_4buffers_dirty(&qbh0);
100	hpfs_brelse4(&qbh0);
101	inc_nlink(dir);
102	insert_inode_hash(result);
103
104	if (!uid_eq(result->i_uid, current_fsuid()) ||
105	    !gid_eq(result->i_gid, current_fsgid()) ||
106	    result->i_mode != (mode | S_IFDIR)) {
107		result->i_uid = current_fsuid();
108		result->i_gid = current_fsgid();
109		result->i_mode = mode | S_IFDIR;
110		hpfs_write_inode_nolock(result);
111	}
112	hpfs_update_directory_times(dir);
113	d_instantiate(dentry, result);
114	hpfs_unlock(dir->i_sb);
115	return 0;
116bail3:
117	iput(result);
118bail2:
119	hpfs_brelse4(&qbh0);
120	hpfs_free_dnode(dir->i_sb, dno);
121bail1:
122	brelse(bh);
123	hpfs_free_sectors(dir->i_sb, fno, 1);
124bail:
125	hpfs_unlock(dir->i_sb);
126	return err;
127}
128
129static int hpfs_create(struct mnt_idmap *idmap, struct inode *dir,
130		       struct dentry *dentry, umode_t mode, bool excl)
131{
132	const unsigned char *name = dentry->d_name.name;
133	unsigned len = dentry->d_name.len;
134	struct inode *result = NULL;
135	struct buffer_head *bh;
136	struct fnode *fnode;
137	fnode_secno fno;
138	int r;
139	struct hpfs_dirent dee;
140	int err;
141	if ((err = hpfs_chk_name(name, &len)))
142		return err==-ENOENT ? -EINVAL : err;
143	hpfs_lock(dir->i_sb);
144	err = -ENOSPC;
145	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
146	if (!fnode)
147		goto bail;
148	memset(&dee, 0, sizeof dee);
149	if (!(mode & 0222)) dee.read_only = 1;
150	dee.archive = 1;
151	dee.hidden = name[0] == '.';
152	dee.fnode = cpu_to_le32(fno);
153	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(local_get_seconds(dir->i_sb));
154
155	result = new_inode(dir->i_sb);
156	if (!result)
157		goto bail1;
158	
159	hpfs_init_inode(result);
160	result->i_ino = fno;
161	result->i_mode |= S_IFREG;
162	result->i_mode &= ~0111;
163	result->i_op = &hpfs_file_iops;
164	result->i_fop = &hpfs_file_ops;
165	set_nlink(result, 1);
166	hpfs_i(result)->i_parent_dir = dir->i_ino;
167	inode_set_mtime_to_ts(result,
168			      inode_set_atime_to_ts(result, inode_set_ctime(result, local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date)), 0)));
 
 
169	hpfs_i(result)->i_ea_size = 0;
170	if (dee.read_only)
171		result->i_mode &= ~0222;
172	result->i_blocks = 1;
173	result->i_size = 0;
174	result->i_data.a_ops = &hpfs_aops;
175	hpfs_i(result)->mmu_private = 0;
176
177	r = hpfs_add_dirent(dir, name, len, &dee);
178	if (r == 1)
179		goto bail2;
180	if (r == -1) {
181		err = -EEXIST;
182		goto bail2;
183	}
184	fnode->len = len;
185	memcpy(fnode->name, name, len > 15 ? 15 : len);
186	fnode->up = cpu_to_le32(dir->i_ino);
187	mark_buffer_dirty(bh);
188	brelse(bh);
189
190	insert_inode_hash(result);
191
192	if (!uid_eq(result->i_uid, current_fsuid()) ||
193	    !gid_eq(result->i_gid, current_fsgid()) ||
194	    result->i_mode != (mode | S_IFREG)) {
195		result->i_uid = current_fsuid();
196		result->i_gid = current_fsgid();
197		result->i_mode = mode | S_IFREG;
198		hpfs_write_inode_nolock(result);
199	}
200	hpfs_update_directory_times(dir);
201	d_instantiate(dentry, result);
202	hpfs_unlock(dir->i_sb);
203	return 0;
204
205bail2:
206	iput(result);
207bail1:
208	brelse(bh);
209	hpfs_free_sectors(dir->i_sb, fno, 1);
210bail:
211	hpfs_unlock(dir->i_sb);
212	return err;
213}
214
215static int hpfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
216		      struct dentry *dentry, umode_t mode, dev_t rdev)
217{
218	const unsigned char *name = dentry->d_name.name;
219	unsigned len = dentry->d_name.len;
220	struct buffer_head *bh;
221	struct fnode *fnode;
222	fnode_secno fno;
223	int r;
224	struct hpfs_dirent dee;
225	struct inode *result = NULL;
226	int err;
227	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
228	if (hpfs_sb(dir->i_sb)->sb_eas < 2) return -EPERM;
229	hpfs_lock(dir->i_sb);
230	err = -ENOSPC;
231	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
232	if (!fnode)
233		goto bail;
234	memset(&dee, 0, sizeof dee);
235	if (!(mode & 0222)) dee.read_only = 1;
236	dee.archive = 1;
237	dee.hidden = name[0] == '.';
238	dee.fnode = cpu_to_le32(fno);
239	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(local_get_seconds(dir->i_sb));
240
241	result = new_inode(dir->i_sb);
242	if (!result)
243		goto bail1;
244
245	hpfs_init_inode(result);
246	result->i_ino = fno;
247	hpfs_i(result)->i_parent_dir = dir->i_ino;
248	inode_set_mtime_to_ts(result,
249			      inode_set_atime_to_ts(result, inode_set_ctime(result, local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date)), 0)));
 
 
250	hpfs_i(result)->i_ea_size = 0;
251	result->i_uid = current_fsuid();
252	result->i_gid = current_fsgid();
253	set_nlink(result, 1);
254	result->i_size = 0;
255	result->i_blocks = 1;
256	init_special_inode(result, mode, rdev);
257
258	r = hpfs_add_dirent(dir, name, len, &dee);
259	if (r == 1)
260		goto bail2;
261	if (r == -1) {
262		err = -EEXIST;
263		goto bail2;
264	}
265	fnode->len = len;
266	memcpy(fnode->name, name, len > 15 ? 15 : len);
267	fnode->up = cpu_to_le32(dir->i_ino);
268	mark_buffer_dirty(bh);
269
270	insert_inode_hash(result);
271
272	hpfs_write_inode_nolock(result);
273	hpfs_update_directory_times(dir);
274	d_instantiate(dentry, result);
275	brelse(bh);
276	hpfs_unlock(dir->i_sb);
277	return 0;
278bail2:
279	iput(result);
280bail1:
281	brelse(bh);
282	hpfs_free_sectors(dir->i_sb, fno, 1);
283bail:
284	hpfs_unlock(dir->i_sb);
285	return err;
286}
287
288static int hpfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
289			struct dentry *dentry, const char *symlink)
290{
291	const unsigned char *name = dentry->d_name.name;
292	unsigned len = dentry->d_name.len;
293	struct buffer_head *bh;
294	struct fnode *fnode;
295	fnode_secno fno;
296	int r;
297	struct hpfs_dirent dee;
298	struct inode *result;
299	int err;
300	if ((err = hpfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
301	hpfs_lock(dir->i_sb);
302	if (hpfs_sb(dir->i_sb)->sb_eas < 2) {
303		hpfs_unlock(dir->i_sb);
304		return -EPERM;
305	}
306	err = -ENOSPC;
307	fnode = hpfs_alloc_fnode(dir->i_sb, hpfs_i(dir)->i_dno, &fno, &bh);
308	if (!fnode)
309		goto bail;
310	memset(&dee, 0, sizeof dee);
311	dee.archive = 1;
312	dee.hidden = name[0] == '.';
313	dee.fnode = cpu_to_le32(fno);
314	dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(local_get_seconds(dir->i_sb));
315
316	result = new_inode(dir->i_sb);
317	if (!result)
318		goto bail1;
319	result->i_ino = fno;
320	hpfs_init_inode(result);
321	hpfs_i(result)->i_parent_dir = dir->i_ino;
322	inode_set_mtime_to_ts(result,
323			      inode_set_atime_to_ts(result, inode_set_ctime(result, local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date)), 0)));
 
 
324	hpfs_i(result)->i_ea_size = 0;
325	result->i_mode = S_IFLNK | 0777;
326	result->i_uid = current_fsuid();
327	result->i_gid = current_fsgid();
328	result->i_blocks = 1;
329	set_nlink(result, 1);
330	result->i_size = strlen(symlink);
331	inode_nohighmem(result);
332	result->i_op = &page_symlink_inode_operations;
333	result->i_data.a_ops = &hpfs_symlink_aops;
334
335	r = hpfs_add_dirent(dir, name, len, &dee);
336	if (r == 1)
337		goto bail2;
338	if (r == -1) {
339		err = -EEXIST;
340		goto bail2;
341	}
342	fnode->len = len;
343	memcpy(fnode->name, name, len > 15 ? 15 : len);
344	fnode->up = cpu_to_le32(dir->i_ino);
345	hpfs_set_ea(result, fnode, "SYMLINK", symlink, strlen(symlink));
346	mark_buffer_dirty(bh);
347	brelse(bh);
348
349	insert_inode_hash(result);
350
351	hpfs_write_inode_nolock(result);
352	hpfs_update_directory_times(dir);
353	d_instantiate(dentry, result);
354	hpfs_unlock(dir->i_sb);
355	return 0;
356bail2:
357	iput(result);
358bail1:
359	brelse(bh);
360	hpfs_free_sectors(dir->i_sb, fno, 1);
361bail:
362	hpfs_unlock(dir->i_sb);
363	return err;
364}
365
366static int hpfs_unlink(struct inode *dir, struct dentry *dentry)
367{
368	const unsigned char *name = dentry->d_name.name;
369	unsigned len = dentry->d_name.len;
370	struct quad_buffer_head qbh;
371	struct hpfs_dirent *de;
372	struct inode *inode = d_inode(dentry);
373	dnode_secno dno;
374	int r;
375	int err;
376
377	hpfs_lock(dir->i_sb);
378	hpfs_adjust_length(name, &len);
379
380	err = -ENOENT;
381	de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
382	if (!de)
383		goto out;
384
385	err = -EPERM;
386	if (de->first)
387		goto out1;
388
389	err = -EISDIR;
390	if (de->directory)
391		goto out1;
392
393	r = hpfs_remove_dirent(dir, dno, de, &qbh, 1);
394	switch (r) {
395	case 1:
396		hpfs_error(dir->i_sb, "there was error when removing dirent");
397		err = -EFSERROR;
398		break;
399	case 2:		/* no space for deleting */
400		err = -ENOSPC;
401		break;
402	default:
403		drop_nlink(inode);
404		err = 0;
405	}
406	goto out;
407
408out1:
409	hpfs_brelse4(&qbh);
410out:
411	if (!err)
412		hpfs_update_directory_times(dir);
413	hpfs_unlock(dir->i_sb);
414	return err;
415}
416
417static int hpfs_rmdir(struct inode *dir, struct dentry *dentry)
418{
419	const unsigned char *name = dentry->d_name.name;
420	unsigned len = dentry->d_name.len;
421	struct quad_buffer_head qbh;
422	struct hpfs_dirent *de;
423	struct inode *inode = d_inode(dentry);
424	dnode_secno dno;
425	int n_items = 0;
426	int err;
427	int r;
428
429	hpfs_adjust_length(name, &len);
430	hpfs_lock(dir->i_sb);
431	err = -ENOENT;
432	de = map_dirent(dir, hpfs_i(dir)->i_dno, name, len, &dno, &qbh);
433	if (!de)
434		goto out;
435
436	err = -EPERM;
437	if (de->first)
438		goto out1;
439
440	err = -ENOTDIR;
441	if (!de->directory)
442		goto out1;
443
444	hpfs_count_dnodes(dir->i_sb, hpfs_i(inode)->i_dno, NULL, NULL, &n_items);
445	err = -ENOTEMPTY;
446	if (n_items)
447		goto out1;
448
449	r = hpfs_remove_dirent(dir, dno, de, &qbh, 1);
450	switch (r) {
451	case 1:
452		hpfs_error(dir->i_sb, "there was error when removing dirent");
453		err = -EFSERROR;
454		break;
455	case 2:
456		err = -ENOSPC;
457		break;
458	default:
459		drop_nlink(dir);
460		clear_nlink(inode);
461		err = 0;
462	}
463	goto out;
464out1:
465	hpfs_brelse4(&qbh);
466out:
467	if (!err)
468		hpfs_update_directory_times(dir);
469	hpfs_unlock(dir->i_sb);
470	return err;
471}
472
473static int hpfs_symlink_read_folio(struct file *file, struct folio *folio)
474{
475	struct page *page = &folio->page;
476	char *link = page_address(page);
477	struct inode *i = page->mapping->host;
478	struct fnode *fnode;
479	struct buffer_head *bh;
480	int err;
481
482	err = -EIO;
483	hpfs_lock(i->i_sb);
484	if (!(fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh)))
485		goto fail;
486	err = hpfs_read_ea(i->i_sb, fnode, "SYMLINK", link, PAGE_SIZE);
487	brelse(bh);
488	if (err)
489		goto fail;
490	hpfs_unlock(i->i_sb);
491	SetPageUptodate(page);
492	unlock_page(page);
493	return 0;
494
495fail:
496	hpfs_unlock(i->i_sb);
497	SetPageError(page);
498	unlock_page(page);
499	return err;
500}
501
502const struct address_space_operations hpfs_symlink_aops = {
503	.read_folio	= hpfs_symlink_read_folio
504};
505
506static int hpfs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
507		       struct dentry *old_dentry, struct inode *new_dir,
508		       struct dentry *new_dentry, unsigned int flags)
509{
510	const unsigned char *old_name = old_dentry->d_name.name;
511	unsigned old_len = old_dentry->d_name.len;
512	const unsigned char *new_name = new_dentry->d_name.name;
513	unsigned new_len = new_dentry->d_name.len;
514	struct inode *i = d_inode(old_dentry);
515	struct inode *new_inode = d_inode(new_dentry);
516	struct quad_buffer_head qbh, qbh1;
517	struct hpfs_dirent *dep, *nde;
518	struct hpfs_dirent de;
519	dnode_secno dno;
520	int r;
521	struct buffer_head *bh;
522	struct fnode *fnode;
523	int err;
524
525	if (flags & ~RENAME_NOREPLACE)
526		return -EINVAL;
527
528	if ((err = hpfs_chk_name(new_name, &new_len))) return err;
529	err = 0;
530	hpfs_adjust_length(old_name, &old_len);
531
532	hpfs_lock(i->i_sb);
533	/* order doesn't matter, due to VFS exclusion */
534	
535	/* Erm? Moving over the empty non-busy directory is perfectly legal */
536	if (new_inode && S_ISDIR(new_inode->i_mode)) {
537		err = -EINVAL;
538		goto end1;
539	}
540
541	if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) {
542		hpfs_error(i->i_sb, "lookup succeeded but map dirent failed");
543		err = -ENOENT;
544		goto end1;
545	}
546	copy_de(&de, dep);
547	de.hidden = new_name[0] == '.';
548
549	if (new_inode) {
550		int r;
551		if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 1)) != 2) {
552			if ((nde = map_dirent(new_dir, hpfs_i(new_dir)->i_dno, new_name, new_len, NULL, &qbh1))) {
553				clear_nlink(new_inode);
554				copy_de(nde, &de);
555				memcpy(nde->name, new_name, new_len);
556				hpfs_mark_4buffers_dirty(&qbh1);
557				hpfs_brelse4(&qbh1);
558				goto end;
559			}
560			hpfs_error(new_dir->i_sb, "hpfs_rename: could not find dirent");
561			err = -EFSERROR;
562			goto end1;
563		}
564		err = -ENOSPC;
565		goto end1;
566	}
567
568	if (new_dir == old_dir) hpfs_brelse4(&qbh);
569
570	if ((r = hpfs_add_dirent(new_dir, new_name, new_len, &de))) {
571		if (r == -1) hpfs_error(new_dir->i_sb, "hpfs_rename: dirent already exists!");
572		err = r == 1 ? -ENOSPC : -EFSERROR;
573		if (new_dir != old_dir) hpfs_brelse4(&qbh);
574		goto end1;
575	}
576	
577	if (new_dir == old_dir)
578		if (!(dep = map_dirent(old_dir, hpfs_i(old_dir)->i_dno, old_name, old_len, &dno, &qbh))) {
579			hpfs_error(i->i_sb, "lookup succeeded but map dirent failed at #2");
580			err = -ENOENT;
581			goto end1;
582		}
583
584	if ((r = hpfs_remove_dirent(old_dir, dno, dep, &qbh, 0))) {
585		hpfs_error(i->i_sb, "hpfs_rename: could not remove dirent");
586		err = r == 2 ? -ENOSPC : -EFSERROR;
587		goto end1;
588	}
589
590end:
591	hpfs_i(i)->i_parent_dir = new_dir->i_ino;
592	if (S_ISDIR(i->i_mode)) {
593		inc_nlink(new_dir);
594		drop_nlink(old_dir);
595	}
596	if ((fnode = hpfs_map_fnode(i->i_sb, i->i_ino, &bh))) {
597		fnode->up = cpu_to_le32(new_dir->i_ino);
598		fnode->len = new_len;
599		memcpy(fnode->name, new_name, new_len>15?15:new_len);
600		if (new_len < 15) memset(&fnode->name[new_len], 0, 15 - new_len);
601		mark_buffer_dirty(bh);
602		brelse(bh);
603	}
604end1:
605	if (!err) {
606		hpfs_update_directory_times(old_dir);
607		hpfs_update_directory_times(new_dir);
608	}
609	hpfs_unlock(i->i_sb);
610	return err;
611}
612
613const struct inode_operations hpfs_dir_iops =
614{
615	.create		= hpfs_create,
616	.lookup		= hpfs_lookup,
617	.unlink		= hpfs_unlink,
618	.symlink	= hpfs_symlink,
619	.mkdir		= hpfs_mkdir,
620	.rmdir		= hpfs_rmdir,
621	.mknod		= hpfs_mknod,
622	.rename		= hpfs_rename,
623	.setattr	= hpfs_setattr,
624};