File Index
Files and directories
Sign in
FILE

namei.c

File preview with syntax highlighting.

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