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