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

1     /*
2      *  linux/fs/minix/dir.c
3      *
4      *  Copyright (C) 1991, 1992 Linus Torvalds
5      *
6      *  minix directory handling functions
7      */
8     
9     #include <linux/fs.h>
10     #include <linux/minix_fs.h>
11     #include <linux/pagemap.h>
12     
13     typedef struct minix_dir_entry minix_dirent;
14     
15     static int minix_readdir(struct file *, void *, filldir_t);
16     
17     struct file_operations minix_dir_operations = {
18     	read:		generic_read_dir,
19     	readdir:	minix_readdir,
20     	fsync:		minix_sync_file,
21     };
22     
23     static inline void dir_put_page(struct page *page)
24     {
25     	kunmap(page);
26     	page_cache_release(page);
27     }
28     
29     static inline unsigned long dir_pages(struct inode *inode)
30     {
31     	return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
32     }
33     
34     static int dir_commit_chunk(struct page *page, unsigned from, unsigned to)
35     {
36     	struct inode *dir = (struct inode *)page->mapping->host;
37     	int err = 0;
38     	page->mapping->a_ops->commit_write(NULL, page, from, to);
39     	if (IS_SYNC(dir))
40     		err = waitfor_one_page(page);
41     	return err;
42     }
43     
44     static struct page * dir_get_page(struct inode *dir, unsigned long n)
45     {
46     	struct address_space *mapping = dir->i_mapping;
47     	struct page *page = read_cache_page(mapping, n,
48     				(filler_t*)mapping->a_ops->readpage, NULL);
49     	if (!IS_ERR(page)) {
50     		wait_on_page(page);
51     		kmap(page);
52     		if (!Page_Uptodate(page))
53     			goto fail;
54     	}
55     	return page;
56     
57     fail:
58     	dir_put_page(page);
59     	return ERR_PTR(-EIO);
60     }
61     
62     static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi)
63     {
64     	return (void*)((char*)de + sbi->s_dirsize);
65     }
66     
67     static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
68     {
69     	unsigned long pos = filp->f_pos;
70     	struct inode *inode = filp->f_dentry->d_inode;
71     	struct super_block *sb = inode->i_sb;
72     	unsigned offset = pos & ~PAGE_CACHE_MASK;
73     	unsigned long n = pos >> PAGE_CACHE_SHIFT;
74     	unsigned long npages = dir_pages(inode);
75     	struct minix_sb_info *sbi = &sb->u.minix_sb;
76     	unsigned chunk_size = sbi->s_dirsize;
77     
78     	pos = (pos + chunk_size-1) & ~(chunk_size-1);
79     	if (pos >= inode->i_size)
80     		goto done;
81     
82     	for ( ; n < npages; n++, offset = 0) {
83     		char *p, *kaddr, *limit;
84     		struct page *page = dir_get_page(inode, n);
85     
86     		if (IS_ERR(page))
87     			continue;
88     		kaddr = (char *)page_address(page);
89     		p = kaddr+offset;
90     		limit = kaddr + PAGE_CACHE_SIZE - chunk_size;
91     		for ( ; p <= limit ; p = minix_next_entry(p, sbi)) {
92     			minix_dirent *de = (minix_dirent *)p;
93     			if (de->inode) {
94     				int over;
95     				unsigned l = strnlen(de->name,sbi->s_namelen);
96     
97     				offset = p - kaddr;
98     				over = filldir(dirent, de->name, l,
99     						(n<<PAGE_CACHE_SHIFT) | offset,
100     						de->inode, DT_UNKNOWN);
101     				if (over) {
102     					dir_put_page(page);
103     					goto done;
104     				}
105     			}
106     		}
107     		dir_put_page(page);
108     	}
109     
110     done:
111     	filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
112     	UPDATE_ATIME(inode);
113     	return 0;
114     }
115     
116     static inline int namecompare(int len, int maxlen,
117     	const char * name, const char * buffer)
118     {
119     	if (len < maxlen && buffer[len])
120     		return 0;
121     	return !memcmp(name, buffer, len);
122     }
123     
124     /*
125      *	minix_find_entry()
126      *
127      * finds an entry in the specified directory with the wanted name. It
128      * returns the cache buffer in which the entry was found, and the entry
129      * itself (as a parameter - res_dir). It does NOT read the inode of the
130      * entry - you'll have to do that yourself if you want to.
131      */
132     minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page)
133     {
134     	const char * name = dentry->d_name.name;
135     	int namelen = dentry->d_name.len;
136     	struct inode * dir = dentry->d_parent->d_inode;
137     	struct super_block * sb = dir->i_sb;
138     	struct minix_sb_info * sbi = &sb->u.minix_sb;
139     	unsigned long n;
140     	unsigned long npages = dir_pages(dir);
141     	struct page *page = NULL;
142     	struct minix_dir_entry *de;
143     
144     	*res_page = NULL;
145     
146     	for (n = 0; n < npages; n++) {
147     		char *kaddr;
148     		page = dir_get_page(dir, n);
149     		if (IS_ERR(page))
150     			continue;
151     
152     		kaddr = (char*)page_address(page);
153     		de = (struct minix_dir_entry *) kaddr;
154     		kaddr += PAGE_CACHE_SIZE - sbi->s_dirsize;
155     		for ( ; (char *) de <= kaddr ; de = minix_next_entry(de,sbi)) {
156     			if (!de->inode)
157     				continue;
158     			if (namecompare(namelen,sbi->s_namelen,name,de->name))
159     				goto found;
160     		}
161     		dir_put_page(page);
162     	}
163     	return NULL;
164     
165     found:
166     	*res_page = page;
167     	return de;
168     }
169     
170     int minix_add_link(struct dentry *dentry, struct inode *inode)
171     {
172     	struct inode *dir = dentry->d_parent->d_inode;
173     	const char * name = dentry->d_name.name;
174     	int namelen = dentry->d_name.len;
175     	struct super_block * sb = dir->i_sb;
176     	struct minix_sb_info * sbi = &sb->u.minix_sb;
177     	struct page *page = NULL;
178     	struct minix_dir_entry * de;
179     	unsigned long npages = dir_pages(dir);
180     	unsigned long n;
181     	char *kaddr;
182     	unsigned from, to;
183     	int err;
184     
185     	/* We take care of directory expansion in the same loop */
186     	for (n = 0; n <= npages; n++) {
187     		page = dir_get_page(dir, n);
188     		err = PTR_ERR(page);
189     		if (IS_ERR(page))
190     			goto out;
191     		kaddr = (char*)page_address(page);
192     		de = (minix_dirent *)kaddr;
193     		kaddr += PAGE_CACHE_SIZE - sbi->s_dirsize;
194     		while ((char *)de <= kaddr) {
195     			if (!de->inode)
196     				goto got_it;
197     			err = -EEXIST;
198     			if (namecompare(namelen,sbi->s_namelen,name,de->name))
199     				goto out_page;
200     			de = minix_next_entry(de, sbi);
201     		}
202     		dir_put_page(page);
203     	}
204     	BUG();
205     	return -EINVAL;
206     
207     got_it:
208     	from = (char*)de - (char*)page_address(page);
209     	to = from + sbi->s_dirsize;
210     	lock_page(page);
211     	err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
212     	if (err)
213     		goto out_unlock;
214     	memcpy (de->name, name, namelen);
215     	memset (de->name + namelen, 0, sbi->s_dirsize - namelen - 2);
216     	de->inode = inode->i_ino;
217     	err = dir_commit_chunk(page, from, to);
218     	dir->i_mtime = dir->i_ctime = CURRENT_TIME;
219     	mark_inode_dirty(dir);
220     out_unlock:
221     	UnlockPage(page);
222     out_page:
223     	dir_put_page(page);
224     out:
225     	return err;
226     }
227     
228     int minix_delete_entry(struct minix_dir_entry *de, struct page *page)
229     {
230     	struct address_space *mapping = page->mapping;
231     	struct inode *inode = (struct inode*)mapping->host;
232     	char *kaddr = (char*)page_address(page);
233     	unsigned from = (char*)de - kaddr;
234     	unsigned to = from + inode->i_sb->u.minix_sb.s_dirsize;
235     	int err;
236     
237     	lock_page(page);
238     	err = mapping->a_ops->prepare_write(NULL, page, from, to);
239     	if (err)
240     		BUG();
241     	de->inode = 0;
242     	err = dir_commit_chunk(page, from, to);
243     	UnlockPage(page);
244     	dir_put_page(page);
245     	inode->i_ctime = inode->i_mtime = CURRENT_TIME;
246     	mark_inode_dirty(inode);
247     	return err;
248     }
249     
250     int minix_make_empty(struct inode *inode, struct inode *dir)
251     {
252     	struct address_space *mapping = inode->i_mapping;
253     	struct page *page = grab_cache_page(mapping, 0);
254     	struct minix_sb_info * sbi = &inode->i_sb->u.minix_sb;
255     	struct minix_dir_entry * de;
256     	char *base;
257     	int err;
258     
259     	if (!page)
260     		return -ENOMEM;
261     	err = mapping->a_ops->prepare_write(NULL, page, 0, 2 * sbi->s_dirsize);
262     	if (err)
263     		goto fail;
264     
265     	base = (char*)page_address(page);
266     	memset(base, 0, PAGE_CACHE_SIZE);
267     
268     	de = (struct minix_dir_entry *) base;
269     	de->inode = inode->i_ino;
270     	strcpy(de->name,".");
271     	de = minix_next_entry(de, sbi);
272     	de->inode = dir->i_ino;
273     	strcpy(de->name,"..");
274     
275     	err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize);
276     fail:
277     	UnlockPage(page);
278     	page_cache_release(page);
279     	return err;
280     }
281     
282     /*
283      * routine to check that the specified directory is empty (for rmdir)
284      */
285     int minix_empty_dir(struct inode * inode)
286     {
287     	struct page *page = NULL;
288     	unsigned long i, npages = dir_pages(inode);
289     	struct minix_sb_info *sbi = &inode->i_sb->u.minix_sb;
290     
291     	for (i = 0; i < npages; i++) {
292     		char *kaddr;
293     		minix_dirent * de;
294     		page = dir_get_page(inode, i);
295     
296     		if (IS_ERR(page))
297     			continue;
298     
299     		kaddr = (char *)page_address(page);
300     		de = (minix_dirent *)kaddr;
301     		kaddr += PAGE_CACHE_SIZE - sbi->s_dirsize;
302     
303     		while ((char *)de <= kaddr) {
304     			if (de->inode != 0) {
305     				/* check for . and .. */
306     				if (de->name[0] != '.')
307     					goto not_empty;
308     				if (!de->name[1]) {
309     					if (de->inode != inode->i_ino)
310     						goto not_empty;
311     				} else if (de->name[1] != '.')
312     					goto not_empty;
313     				else if (de->name[2])
314     					goto not_empty;
315     			}
316     			de = minix_next_entry(de, sbi);
317     		}
318     		dir_put_page(page);
319     	}
320     	return 1;
321     
322     not_empty:
323     	dir_put_page(page);
324     	return 0;
325     }
326     
327     /* Releases the page */
328     void minix_set_link(struct minix_dir_entry *de, struct page *page,
329     	struct inode *inode)
330     {
331     	struct inode *dir = (struct inode*)page->mapping->host;
332     	struct minix_sb_info *sbi = &dir->i_sb->u.minix_sb;
333     	unsigned from = (char *)de-(char*)page_address(page);
334     	unsigned to = from + sbi->s_dirsize;
335     	int err;
336     
337     	lock_page(page);
338     	err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
339     	if (err)
340     		BUG();
341     	de->inode = inode->i_ino;
342     	err = dir_commit_chunk(page, from, to);
343     	UnlockPage(page);
344     	dir_put_page(page);
345     	dir->i_mtime = dir->i_ctime = CURRENT_TIME;
346     	mark_inode_dirty(dir);
347     }
348     
349     struct minix_dir_entry * minix_dotdot (struct inode *dir, struct page **p)
350     {
351     	struct page *page = dir_get_page(dir, 0);
352     	struct minix_sb_info *sbi = &dir->i_sb->u.minix_sb;
353     	struct minix_dir_entry *de = NULL;
354     
355     	if (!IS_ERR(page)) {
356     		de = minix_next_entry(page_address(page), sbi);
357     		*p = page;
358     	}
359     	return de;
360     }
361     
362     ino_t minix_inode_by_name(struct dentry *dentry)
363     {
364     	struct page *page;
365     	struct minix_dir_entry *de = minix_find_entry(dentry, &page);
366     	ino_t res = 0;
367     
368     	if (de) {
369     		res = de->inode;
370     		dir_put_page(page);
371     	}
372     	return res;
373     }
374