xref: /OK3568_Linux_fs/kernel/fs/minix/namei.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  linux/fs/minix/namei.c
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *  Copyright (C) 1991, 1992  Linus Torvalds
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include "minix.h"
9*4882a593Smuzhiyun 
add_nondir(struct dentry * dentry,struct inode * inode)10*4882a593Smuzhiyun static int add_nondir(struct dentry *dentry, struct inode *inode)
11*4882a593Smuzhiyun {
12*4882a593Smuzhiyun 	int err = minix_add_link(dentry, inode);
13*4882a593Smuzhiyun 	if (!err) {
14*4882a593Smuzhiyun 		d_instantiate(dentry, inode);
15*4882a593Smuzhiyun 		return 0;
16*4882a593Smuzhiyun 	}
17*4882a593Smuzhiyun 	inode_dec_link_count(inode);
18*4882a593Smuzhiyun 	iput(inode);
19*4882a593Smuzhiyun 	return err;
20*4882a593Smuzhiyun }
21*4882a593Smuzhiyun 
minix_lookup(struct inode * dir,struct dentry * dentry,unsigned int flags)22*4882a593Smuzhiyun static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun 	struct inode * inode = NULL;
25*4882a593Smuzhiyun 	ino_t ino;
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun 	if (dentry->d_name.len > minix_sb(dir->i_sb)->s_namelen)
28*4882a593Smuzhiyun 		return ERR_PTR(-ENAMETOOLONG);
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	ino = minix_inode_by_name(dentry);
31*4882a593Smuzhiyun 	if (ino)
32*4882a593Smuzhiyun 		inode = minix_iget(dir->i_sb, ino);
33*4882a593Smuzhiyun 	return d_splice_alias(inode, dentry);
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun 
minix_mknod(struct inode * dir,struct dentry * dentry,umode_t mode,dev_t rdev)36*4882a593Smuzhiyun static int minix_mknod(struct inode * dir, struct dentry *dentry, umode_t mode, dev_t rdev)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	int error;
39*4882a593Smuzhiyun 	struct inode *inode;
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun 	if (!old_valid_dev(rdev))
42*4882a593Smuzhiyun 		return -EINVAL;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	inode = minix_new_inode(dir, mode, &error);
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	if (inode) {
47*4882a593Smuzhiyun 		minix_set_inode(inode, rdev);
48*4882a593Smuzhiyun 		mark_inode_dirty(inode);
49*4882a593Smuzhiyun 		error = add_nondir(dentry, inode);
50*4882a593Smuzhiyun 	}
51*4882a593Smuzhiyun 	return error;
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun 
minix_tmpfile(struct inode * dir,struct dentry * dentry,umode_t mode)54*4882a593Smuzhiyun static int minix_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	int error;
57*4882a593Smuzhiyun 	struct inode *inode = minix_new_inode(dir, mode, &error);
58*4882a593Smuzhiyun 	if (inode) {
59*4882a593Smuzhiyun 		minix_set_inode(inode, 0);
60*4882a593Smuzhiyun 		mark_inode_dirty(inode);
61*4882a593Smuzhiyun 		d_tmpfile(dentry, inode);
62*4882a593Smuzhiyun 	}
63*4882a593Smuzhiyun 	return error;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun 
minix_create(struct inode * dir,struct dentry * dentry,umode_t mode,bool excl)66*4882a593Smuzhiyun static int minix_create(struct inode *dir, struct dentry *dentry, umode_t mode,
67*4882a593Smuzhiyun 		bool excl)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun 	return minix_mknod(dir, dentry, mode, 0);
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun 
minix_symlink(struct inode * dir,struct dentry * dentry,const char * symname)72*4882a593Smuzhiyun static int minix_symlink(struct inode * dir, struct dentry *dentry,
73*4882a593Smuzhiyun 	  const char * symname)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	int err = -ENAMETOOLONG;
76*4882a593Smuzhiyun 	int i = strlen(symname)+1;
77*4882a593Smuzhiyun 	struct inode * inode;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	if (i > dir->i_sb->s_blocksize)
80*4882a593Smuzhiyun 		goto out;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	inode = minix_new_inode(dir, S_IFLNK | 0777, &err);
83*4882a593Smuzhiyun 	if (!inode)
84*4882a593Smuzhiyun 		goto out;
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	minix_set_inode(inode, 0);
87*4882a593Smuzhiyun 	err = page_symlink(inode, symname, i);
88*4882a593Smuzhiyun 	if (err)
89*4882a593Smuzhiyun 		goto out_fail;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	err = add_nondir(dentry, inode);
92*4882a593Smuzhiyun out:
93*4882a593Smuzhiyun 	return err;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun out_fail:
96*4882a593Smuzhiyun 	inode_dec_link_count(inode);
97*4882a593Smuzhiyun 	iput(inode);
98*4882a593Smuzhiyun 	goto out;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun 
minix_link(struct dentry * old_dentry,struct inode * dir,struct dentry * dentry)101*4882a593Smuzhiyun static int minix_link(struct dentry * old_dentry, struct inode * dir,
102*4882a593Smuzhiyun 	struct dentry *dentry)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	struct inode *inode = d_inode(old_dentry);
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	inode->i_ctime = current_time(inode);
107*4882a593Smuzhiyun 	inode_inc_link_count(inode);
108*4882a593Smuzhiyun 	ihold(inode);
109*4882a593Smuzhiyun 	return add_nondir(dentry, inode);
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun 
minix_mkdir(struct inode * dir,struct dentry * dentry,umode_t mode)112*4882a593Smuzhiyun static int minix_mkdir(struct inode * dir, struct dentry *dentry, umode_t mode)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun 	struct inode * inode;
115*4882a593Smuzhiyun 	int err;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	inode_inc_link_count(dir);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	inode = minix_new_inode(dir, S_IFDIR | mode, &err);
120*4882a593Smuzhiyun 	if (!inode)
121*4882a593Smuzhiyun 		goto out_dir;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	minix_set_inode(inode, 0);
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	inode_inc_link_count(inode);
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun 	err = minix_make_empty(inode, dir);
128*4882a593Smuzhiyun 	if (err)
129*4882a593Smuzhiyun 		goto out_fail;
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	err = minix_add_link(dentry, inode);
132*4882a593Smuzhiyun 	if (err)
133*4882a593Smuzhiyun 		goto out_fail;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	d_instantiate(dentry, inode);
136*4882a593Smuzhiyun out:
137*4882a593Smuzhiyun 	return err;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun out_fail:
140*4882a593Smuzhiyun 	inode_dec_link_count(inode);
141*4882a593Smuzhiyun 	inode_dec_link_count(inode);
142*4882a593Smuzhiyun 	iput(inode);
143*4882a593Smuzhiyun out_dir:
144*4882a593Smuzhiyun 	inode_dec_link_count(dir);
145*4882a593Smuzhiyun 	goto out;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun 
minix_unlink(struct inode * dir,struct dentry * dentry)148*4882a593Smuzhiyun static int minix_unlink(struct inode * dir, struct dentry *dentry)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun 	int err = -ENOENT;
151*4882a593Smuzhiyun 	struct inode * inode = d_inode(dentry);
152*4882a593Smuzhiyun 	struct page * page;
153*4882a593Smuzhiyun 	struct minix_dir_entry * de;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	de = minix_find_entry(dentry, &page);
156*4882a593Smuzhiyun 	if (!de)
157*4882a593Smuzhiyun 		goto end_unlink;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 	err = minix_delete_entry(de, page);
160*4882a593Smuzhiyun 	if (err)
161*4882a593Smuzhiyun 		goto end_unlink;
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	inode->i_ctime = dir->i_ctime;
164*4882a593Smuzhiyun 	inode_dec_link_count(inode);
165*4882a593Smuzhiyun end_unlink:
166*4882a593Smuzhiyun 	return err;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun 
minix_rmdir(struct inode * dir,struct dentry * dentry)169*4882a593Smuzhiyun static int minix_rmdir(struct inode * dir, struct dentry *dentry)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	struct inode * inode = d_inode(dentry);
172*4882a593Smuzhiyun 	int err = -ENOTEMPTY;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	if (minix_empty_dir(inode)) {
175*4882a593Smuzhiyun 		err = minix_unlink(dir, dentry);
176*4882a593Smuzhiyun 		if (!err) {
177*4882a593Smuzhiyun 			inode_dec_link_count(dir);
178*4882a593Smuzhiyun 			inode_dec_link_count(inode);
179*4882a593Smuzhiyun 		}
180*4882a593Smuzhiyun 	}
181*4882a593Smuzhiyun 	return err;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun 
minix_rename(struct inode * old_dir,struct dentry * old_dentry,struct inode * new_dir,struct dentry * new_dentry,unsigned int flags)184*4882a593Smuzhiyun static int minix_rename(struct inode * old_dir, struct dentry *old_dentry,
185*4882a593Smuzhiyun 			struct inode * new_dir, struct dentry *new_dentry,
186*4882a593Smuzhiyun 			unsigned int flags)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	struct inode * old_inode = d_inode(old_dentry);
189*4882a593Smuzhiyun 	struct inode * new_inode = d_inode(new_dentry);
190*4882a593Smuzhiyun 	struct page * dir_page = NULL;
191*4882a593Smuzhiyun 	struct minix_dir_entry * dir_de = NULL;
192*4882a593Smuzhiyun 	struct page * old_page;
193*4882a593Smuzhiyun 	struct minix_dir_entry * old_de;
194*4882a593Smuzhiyun 	int err = -ENOENT;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	if (flags & ~RENAME_NOREPLACE)
197*4882a593Smuzhiyun 		return -EINVAL;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	old_de = minix_find_entry(old_dentry, &old_page);
200*4882a593Smuzhiyun 	if (!old_de)
201*4882a593Smuzhiyun 		goto out;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	if (S_ISDIR(old_inode->i_mode)) {
204*4882a593Smuzhiyun 		err = -EIO;
205*4882a593Smuzhiyun 		dir_de = minix_dotdot(old_inode, &dir_page);
206*4882a593Smuzhiyun 		if (!dir_de)
207*4882a593Smuzhiyun 			goto out_old;
208*4882a593Smuzhiyun 	}
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	if (new_inode) {
211*4882a593Smuzhiyun 		struct page * new_page;
212*4882a593Smuzhiyun 		struct minix_dir_entry * new_de;
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 		err = -ENOTEMPTY;
215*4882a593Smuzhiyun 		if (dir_de && !minix_empty_dir(new_inode))
216*4882a593Smuzhiyun 			goto out_dir;
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 		err = -ENOENT;
219*4882a593Smuzhiyun 		new_de = minix_find_entry(new_dentry, &new_page);
220*4882a593Smuzhiyun 		if (!new_de)
221*4882a593Smuzhiyun 			goto out_dir;
222*4882a593Smuzhiyun 		minix_set_link(new_de, new_page, old_inode);
223*4882a593Smuzhiyun 		new_inode->i_ctime = current_time(new_inode);
224*4882a593Smuzhiyun 		if (dir_de)
225*4882a593Smuzhiyun 			drop_nlink(new_inode);
226*4882a593Smuzhiyun 		inode_dec_link_count(new_inode);
227*4882a593Smuzhiyun 	} else {
228*4882a593Smuzhiyun 		err = minix_add_link(new_dentry, old_inode);
229*4882a593Smuzhiyun 		if (err)
230*4882a593Smuzhiyun 			goto out_dir;
231*4882a593Smuzhiyun 		if (dir_de)
232*4882a593Smuzhiyun 			inode_inc_link_count(new_dir);
233*4882a593Smuzhiyun 	}
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	minix_delete_entry(old_de, old_page);
236*4882a593Smuzhiyun 	mark_inode_dirty(old_inode);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	if (dir_de) {
239*4882a593Smuzhiyun 		minix_set_link(dir_de, dir_page, new_dir);
240*4882a593Smuzhiyun 		inode_dec_link_count(old_dir);
241*4882a593Smuzhiyun 	}
242*4882a593Smuzhiyun 	return 0;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun out_dir:
245*4882a593Smuzhiyun 	if (dir_de) {
246*4882a593Smuzhiyun 		kunmap(dir_page);
247*4882a593Smuzhiyun 		put_page(dir_page);
248*4882a593Smuzhiyun 	}
249*4882a593Smuzhiyun out_old:
250*4882a593Smuzhiyun 	kunmap(old_page);
251*4882a593Smuzhiyun 	put_page(old_page);
252*4882a593Smuzhiyun out:
253*4882a593Smuzhiyun 	return err;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun /*
257*4882a593Smuzhiyun  * directories can handle most operations...
258*4882a593Smuzhiyun  */
259*4882a593Smuzhiyun const struct inode_operations minix_dir_inode_operations = {
260*4882a593Smuzhiyun 	.create		= minix_create,
261*4882a593Smuzhiyun 	.lookup		= minix_lookup,
262*4882a593Smuzhiyun 	.link		= minix_link,
263*4882a593Smuzhiyun 	.unlink		= minix_unlink,
264*4882a593Smuzhiyun 	.symlink	= minix_symlink,
265*4882a593Smuzhiyun 	.mkdir		= minix_mkdir,
266*4882a593Smuzhiyun 	.rmdir		= minix_rmdir,
267*4882a593Smuzhiyun 	.mknod		= minix_mknod,
268*4882a593Smuzhiyun 	.rename		= minix_rename,
269*4882a593Smuzhiyun 	.getattr	= minix_getattr,
270*4882a593Smuzhiyun 	.tmpfile	= minix_tmpfile,
271*4882a593Smuzhiyun };
272