Merge tag 'for-linus-20161008' of git://git.infradead.org/linux-mtd
[cascardo/linux.git] / fs / sysv / dir.c
1 /*
2  *  linux/fs/sysv/dir.c
3  *
4  *  minix/dir.c
5  *  Copyright (C) 1991, 1992  Linus Torvalds
6  *
7  *  coh/dir.c
8  *  Copyright (C) 1993  Pascal Haible, Bruno Haible
9  *
10  *  sysv/dir.c
11  *  Copyright (C) 1993  Bruno Haible
12  *
13  *  SystemV/Coherent directory handling functions
14  */
15
16 #include <linux/pagemap.h>
17 #include <linux/highmem.h>
18 #include <linux/swap.h>
19 #include "sysv.h"
20
21 static int sysv_readdir(struct file *, struct dir_context *);
22
23 const struct file_operations sysv_dir_operations = {
24         .llseek         = generic_file_llseek,
25         .read           = generic_read_dir,
26         .iterate_shared = sysv_readdir,
27         .fsync          = generic_file_fsync,
28 };
29
30 static inline void dir_put_page(struct page *page)
31 {
32         kunmap(page);
33         put_page(page);
34 }
35
36 static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
37 {
38         struct address_space *mapping = page->mapping;
39         struct inode *dir = mapping->host;
40         int err = 0;
41
42         block_write_end(NULL, mapping, pos, len, len, page, NULL);
43         if (pos+len > dir->i_size) {
44                 i_size_write(dir, pos+len);
45                 mark_inode_dirty(dir);
46         }
47         if (IS_DIRSYNC(dir))
48                 err = write_one_page(page, 1);
49         else
50                 unlock_page(page);
51         return err;
52 }
53
54 static struct page * dir_get_page(struct inode *dir, unsigned long n)
55 {
56         struct address_space *mapping = dir->i_mapping;
57         struct page *page = read_mapping_page(mapping, n, NULL);
58         if (!IS_ERR(page))
59                 kmap(page);
60         return page;
61 }
62
63 static int sysv_readdir(struct file *file, struct dir_context *ctx)
64 {
65         unsigned long pos = ctx->pos;
66         struct inode *inode = file_inode(file);
67         struct super_block *sb = inode->i_sb;
68         unsigned long npages = dir_pages(inode);
69         unsigned offset;
70         unsigned long n;
71
72         ctx->pos = pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1);
73         if (pos >= inode->i_size)
74                 return 0;
75
76         offset = pos & ~PAGE_MASK;
77         n = pos >> PAGE_SHIFT;
78
79         for ( ; n < npages; n++, offset = 0) {
80                 char *kaddr, *limit;
81                 struct sysv_dir_entry *de;
82                 struct page *page = dir_get_page(inode, n);
83
84                 if (IS_ERR(page))
85                         continue;
86                 kaddr = (char *)page_address(page);
87                 de = (struct sysv_dir_entry *)(kaddr+offset);
88                 limit = kaddr + PAGE_SIZE - SYSV_DIRSIZE;
89                 for ( ;(char*)de <= limit; de++, ctx->pos += sizeof(*de)) {
90                         char *name = de->name;
91
92                         if (!de->inode)
93                                 continue;
94
95                         if (!dir_emit(ctx, name, strnlen(name,SYSV_NAMELEN),
96                                         fs16_to_cpu(SYSV_SB(sb), de->inode),
97                                         DT_UNKNOWN)) {
98                                 dir_put_page(page);
99                                 return 0;
100                         }
101                 }
102                 dir_put_page(page);
103         }
104         return 0;
105 }
106
107 /* compare strings: name[0..len-1] (not zero-terminated) and
108  * buffer[0..] (filled with zeroes up to buffer[0..maxlen-1])
109  */
110 static inline int namecompare(int len, int maxlen,
111         const char * name, const char * buffer)
112 {
113         if (len < maxlen && buffer[len])
114                 return 0;
115         return !memcmp(name, buffer, len);
116 }
117
118 /*
119  *      sysv_find_entry()
120  *
121  * finds an entry in the specified directory with the wanted name. It
122  * returns the cache buffer in which the entry was found, and the entry
123  * itself (as a parameter - res_dir). It does NOT read the inode of the
124  * entry - you'll have to do that yourself if you want to.
125  */
126 struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_page)
127 {
128         const char * name = dentry->d_name.name;
129         int namelen = dentry->d_name.len;
130         struct inode * dir = d_inode(dentry->d_parent);
131         unsigned long start, n;
132         unsigned long npages = dir_pages(dir);
133         struct page *page = NULL;
134         struct sysv_dir_entry *de;
135
136         *res_page = NULL;
137
138         start = SYSV_I(dir)->i_dir_start_lookup;
139         if (start >= npages)
140                 start = 0;
141         n = start;
142
143         do {
144                 char *kaddr;
145                 page = dir_get_page(dir, n);
146                 if (!IS_ERR(page)) {
147                         kaddr = (char*)page_address(page);
148                         de = (struct sysv_dir_entry *) kaddr;
149                         kaddr += PAGE_SIZE - SYSV_DIRSIZE;
150                         for ( ; (char *) de <= kaddr ; de++) {
151                                 if (!de->inode)
152                                         continue;
153                                 if (namecompare(namelen, SYSV_NAMELEN,
154                                                         name, de->name))
155                                         goto found;
156                         }
157                         dir_put_page(page);
158                 }
159
160                 if (++n >= npages)
161                         n = 0;
162         } while (n != start);
163
164         return NULL;
165
166 found:
167         SYSV_I(dir)->i_dir_start_lookup = n;
168         *res_page = page;
169         return de;
170 }
171
172 int sysv_add_link(struct dentry *dentry, struct inode *inode)
173 {
174         struct inode *dir = d_inode(dentry->d_parent);
175         const char * name = dentry->d_name.name;
176         int namelen = dentry->d_name.len;
177         struct page *page = NULL;
178         struct sysv_dir_entry * de;
179         unsigned long npages = dir_pages(dir);
180         unsigned long n;
181         char *kaddr;
182         loff_t pos;
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 = (struct sysv_dir_entry *)kaddr;
193                 kaddr += PAGE_SIZE - SYSV_DIRSIZE;
194                 while ((char *)de <= kaddr) {
195                         if (!de->inode)
196                                 goto got_it;
197                         err = -EEXIST;
198                         if (namecompare(namelen, SYSV_NAMELEN, name, de->name)) 
199                                 goto out_page;
200                         de++;
201                 }
202                 dir_put_page(page);
203         }
204         BUG();
205         return -EINVAL;
206
207 got_it:
208         pos = page_offset(page) +
209                         (char*)de - (char*)page_address(page);
210         lock_page(page);
211         err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
212         if (err)
213                 goto out_unlock;
214         memcpy (de->name, name, namelen);
215         memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2);
216         de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
217         err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
218         dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
219         mark_inode_dirty(dir);
220 out_page:
221         dir_put_page(page);
222 out:
223         return err;
224 out_unlock:
225         unlock_page(page);
226         goto out_page;
227 }
228
229 int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page)
230 {
231         struct inode *inode = page->mapping->host;
232         char *kaddr = (char*)page_address(page);
233         loff_t pos = page_offset(page) + (char *)de - kaddr;
234         int err;
235
236         lock_page(page);
237         err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
238         BUG_ON(err);
239         de->inode = 0;
240         err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
241         dir_put_page(page);
242         inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
243         mark_inode_dirty(inode);
244         return err;
245 }
246
247 int sysv_make_empty(struct inode *inode, struct inode *dir)
248 {
249         struct page *page = grab_cache_page(inode->i_mapping, 0);
250         struct sysv_dir_entry * de;
251         char *base;
252         int err;
253
254         if (!page)
255                 return -ENOMEM;
256         err = sysv_prepare_chunk(page, 0, 2 * SYSV_DIRSIZE);
257         if (err) {
258                 unlock_page(page);
259                 goto fail;
260         }
261         kmap(page);
262
263         base = (char*)page_address(page);
264         memset(base, 0, PAGE_SIZE);
265
266         de = (struct sysv_dir_entry *) base;
267         de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
268         strcpy(de->name,".");
269         de++;
270         de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), dir->i_ino);
271         strcpy(de->name,"..");
272
273         kunmap(page);
274         err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE);
275 fail:
276         put_page(page);
277         return err;
278 }
279
280 /*
281  * routine to check that the specified directory is empty (for rmdir)
282  */
283 int sysv_empty_dir(struct inode * inode)
284 {
285         struct super_block *sb = inode->i_sb;
286         struct page *page = NULL;
287         unsigned long i, npages = dir_pages(inode);
288
289         for (i = 0; i < npages; i++) {
290                 char *kaddr;
291                 struct sysv_dir_entry * de;
292                 page = dir_get_page(inode, i);
293
294                 if (IS_ERR(page))
295                         continue;
296
297                 kaddr = (char *)page_address(page);
298                 de = (struct sysv_dir_entry *)kaddr;
299                 kaddr += PAGE_SIZE-SYSV_DIRSIZE;
300
301                 for ( ;(char *)de <= kaddr; de++) {
302                         if (!de->inode)
303                                 continue;
304                         /* check for . and .. */
305                         if (de->name[0] != '.')
306                                 goto not_empty;
307                         if (!de->name[1]) {
308                                 if (de->inode == cpu_to_fs16(SYSV_SB(sb),
309                                                         inode->i_ino))
310                                         continue;
311                                 goto not_empty;
312                         }
313                         if (de->name[1] != '.' || de->name[2])
314                                 goto not_empty;
315                 }
316                 dir_put_page(page);
317         }
318         return 1;
319
320 not_empty:
321         dir_put_page(page);
322         return 0;
323 }
324
325 /* Releases the page */
326 void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
327         struct inode *inode)
328 {
329         struct inode *dir = page->mapping->host;
330         loff_t pos = page_offset(page) +
331                         (char *)de-(char*)page_address(page);
332         int err;
333
334         lock_page(page);
335         err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
336         BUG_ON(err);
337         de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
338         err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
339         dir_put_page(page);
340         dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
341         mark_inode_dirty(dir);
342 }
343
344 struct sysv_dir_entry * sysv_dotdot (struct inode *dir, struct page **p)
345 {
346         struct page *page = dir_get_page(dir, 0);
347         struct sysv_dir_entry *de = NULL;
348
349         if (!IS_ERR(page)) {
350                 de = (struct sysv_dir_entry*) page_address(page) + 1;
351                 *p = page;
352         }
353         return de;
354 }
355
356 ino_t sysv_inode_by_name(struct dentry *dentry)
357 {
358         struct page *page;
359         struct sysv_dir_entry *de = sysv_find_entry (dentry, &page);
360         ino_t res = 0;
361         
362         if (de) {
363                 res = fs16_to_cpu(SYSV_SB(dentry->d_sb), de->inode);
364                 dir_put_page(page);
365         }
366         return res;
367 }