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