File: /usr/src/linux/fs/minix/namei.c

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