diff options
Diffstat (limited to 'fs/minix/dir.c')
-rw-r--r-- | fs/minix/dir.c | 162 |
1 files changed, 111 insertions, 51 deletions
diff --git a/fs/minix/dir.c b/fs/minix/dir.c index ab782c4086f5..cb4cb571fddf 100644 --- a/fs/minix/dir.c +++ b/fs/minix/dir.c | |||
@@ -4,6 +4,8 @@ | |||
4 | * Copyright (C) 1991, 1992 Linus Torvalds | 4 | * Copyright (C) 1991, 1992 Linus Torvalds |
5 | * | 5 | * |
6 | * minix directory handling functions | 6 | * minix directory handling functions |
7 | * | ||
8 | * Updated to filesystem version 3 by Daniel Aragones | ||
7 | */ | 9 | */ |
8 | 10 | ||
9 | #include "minix.h" | 11 | #include "minix.h" |
@@ -11,6 +13,7 @@ | |||
11 | #include <linux/smp_lock.h> | 13 | #include <linux/smp_lock.h> |
12 | 14 | ||
13 | typedef struct minix_dir_entry minix_dirent; | 15 | typedef struct minix_dir_entry minix_dirent; |
16 | typedef struct minix3_dir_entry minix3_dirent; | ||
14 | 17 | ||
15 | static int minix_readdir(struct file *, void *, filldir_t); | 18 | static int minix_readdir(struct file *, void *, filldir_t); |
16 | 19 | ||
@@ -89,6 +92,8 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
89 | unsigned long npages = dir_pages(inode); | 92 | unsigned long npages = dir_pages(inode); |
90 | struct minix_sb_info *sbi = minix_sb(sb); | 93 | struct minix_sb_info *sbi = minix_sb(sb); |
91 | unsigned chunk_size = sbi->s_dirsize; | 94 | unsigned chunk_size = sbi->s_dirsize; |
95 | char *name; | ||
96 | __u32 inumber; | ||
92 | 97 | ||
93 | lock_kernel(); | 98 | lock_kernel(); |
94 | 99 | ||
@@ -105,16 +110,24 @@ static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
105 | kaddr = (char *)page_address(page); | 110 | kaddr = (char *)page_address(page); |
106 | p = kaddr+offset; | 111 | p = kaddr+offset; |
107 | limit = kaddr + minix_last_byte(inode, n) - chunk_size; | 112 | limit = kaddr + minix_last_byte(inode, n) - chunk_size; |
108 | for ( ; p <= limit ; p = minix_next_entry(p, sbi)) { | 113 | for ( ; p <= limit; p = minix_next_entry(p, sbi)) { |
109 | minix_dirent *de = (minix_dirent *)p; | 114 | if (sbi->s_version == MINIX_V3) { |
110 | if (de->inode) { | 115 | minix3_dirent *de3 = (minix3_dirent *)p; |
116 | name = de3->name; | ||
117 | inumber = de3->inode; | ||
118 | } else { | ||
119 | minix_dirent *de = (minix_dirent *)p; | ||
120 | name = de->name; | ||
121 | inumber = de->inode; | ||
122 | } | ||
123 | if (inumber) { | ||
111 | int over; | 124 | int over; |
112 | unsigned l = strnlen(de->name,sbi->s_namelen); | ||
113 | 125 | ||
126 | unsigned l = strnlen(name, sbi->s_namelen); | ||
114 | offset = p - kaddr; | 127 | offset = p - kaddr; |
115 | over = filldir(dirent, de->name, l, | 128 | over = filldir(dirent, name, l, |
116 | (n<<PAGE_CACHE_SHIFT) | offset, | 129 | (n << PAGE_CACHE_SHIFT) | offset, |
117 | de->inode, DT_UNKNOWN); | 130 | inumber, DT_UNKNOWN); |
118 | if (over) { | 131 | if (over) { |
119 | dir_put_page(page); | 132 | dir_put_page(page); |
120 | goto done; | 133 | goto done; |
@@ -156,23 +169,34 @@ minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page) | |||
156 | unsigned long n; | 169 | unsigned long n; |
157 | unsigned long npages = dir_pages(dir); | 170 | unsigned long npages = dir_pages(dir); |
158 | struct page *page = NULL; | 171 | struct page *page = NULL; |
159 | struct minix_dir_entry *de; | 172 | char *p; |
160 | 173 | ||
174 | char *namx; | ||
175 | __u32 inumber; | ||
161 | *res_page = NULL; | 176 | *res_page = NULL; |
162 | 177 | ||
163 | for (n = 0; n < npages; n++) { | 178 | for (n = 0; n < npages; n++) { |
164 | char *kaddr; | 179 | char *kaddr, *limit; |
180 | |||
165 | page = dir_get_page(dir, n); | 181 | page = dir_get_page(dir, n); |
166 | if (IS_ERR(page)) | 182 | if (IS_ERR(page)) |
167 | continue; | 183 | continue; |
168 | 184 | ||
169 | kaddr = (char*)page_address(page); | 185 | kaddr = (char*)page_address(page); |
170 | de = (struct minix_dir_entry *) kaddr; | 186 | limit = kaddr + minix_last_byte(dir, n) - sbi->s_dirsize; |
171 | kaddr += minix_last_byte(dir, n) - sbi->s_dirsize; | 187 | for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) { |
172 | for ( ; (char *) de <= kaddr ; de = minix_next_entry(de,sbi)) { | 188 | if (sbi->s_version == MINIX_V3) { |
173 | if (!de->inode) | 189 | minix3_dirent *de3 = (minix3_dirent *)p; |
190 | namx = de3->name; | ||
191 | inumber = de3->inode; | ||
192 | } else { | ||
193 | minix_dirent *de = (minix_dirent *)p; | ||
194 | namx = de->name; | ||
195 | inumber = de->inode; | ||
196 | } | ||
197 | if (!inumber) | ||
174 | continue; | 198 | continue; |
175 | if (namecompare(namelen,sbi->s_namelen,name,de->name)) | 199 | if (namecompare(namelen, sbi->s_namelen, name, namx)) |
176 | goto found; | 200 | goto found; |
177 | } | 201 | } |
178 | dir_put_page(page); | 202 | dir_put_page(page); |
@@ -181,7 +205,7 @@ minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page) | |||
181 | 205 | ||
182 | found: | 206 | found: |
183 | *res_page = page; | 207 | *res_page = page; |
184 | return de; | 208 | return (minix_dirent *)p; |
185 | } | 209 | } |
186 | 210 | ||
187 | int minix_add_link(struct dentry *dentry, struct inode *inode) | 211 | int minix_add_link(struct dentry *dentry, struct inode *inode) |
@@ -192,12 +216,15 @@ int minix_add_link(struct dentry *dentry, struct inode *inode) | |||
192 | struct super_block * sb = dir->i_sb; | 216 | struct super_block * sb = dir->i_sb; |
193 | struct minix_sb_info * sbi = minix_sb(sb); | 217 | struct minix_sb_info * sbi = minix_sb(sb); |
194 | struct page *page = NULL; | 218 | struct page *page = NULL; |
195 | struct minix_dir_entry * de; | ||
196 | unsigned long npages = dir_pages(dir); | 219 | unsigned long npages = dir_pages(dir); |
197 | unsigned long n; | 220 | unsigned long n; |
198 | char *kaddr; | 221 | char *kaddr, *p; |
222 | minix_dirent *de; | ||
223 | minix3_dirent *de3; | ||
199 | unsigned from, to; | 224 | unsigned from, to; |
200 | int err; | 225 | int err; |
226 | char *namx = NULL; | ||
227 | __u32 inumber; | ||
201 | 228 | ||
202 | /* | 229 | /* |
203 | * We take care of directory expansion in the same loop | 230 | * We take care of directory expansion in the same loop |
@@ -205,7 +232,7 @@ int minix_add_link(struct dentry *dentry, struct inode *inode) | |||
205 | * to protect that region. | 232 | * to protect that region. |
206 | */ | 233 | */ |
207 | for (n = 0; n <= npages; n++) { | 234 | for (n = 0; n <= npages; n++) { |
208 | char *dir_end; | 235 | char *limit, *dir_end; |
209 | 236 | ||
210 | page = dir_get_page(dir, n); | 237 | page = dir_get_page(dir, n); |
211 | err = PTR_ERR(page); | 238 | err = PTR_ERR(page); |
@@ -214,20 +241,30 @@ int minix_add_link(struct dentry *dentry, struct inode *inode) | |||
214 | lock_page(page); | 241 | lock_page(page); |
215 | kaddr = (char*)page_address(page); | 242 | kaddr = (char*)page_address(page); |
216 | dir_end = kaddr + minix_last_byte(dir, n); | 243 | dir_end = kaddr + minix_last_byte(dir, n); |
217 | de = (minix_dirent *)kaddr; | 244 | limit = kaddr + PAGE_CACHE_SIZE - sbi->s_dirsize; |
218 | kaddr += PAGE_CACHE_SIZE - sbi->s_dirsize; | 245 | for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) { |
219 | while ((char *)de <= kaddr) { | 246 | de = (minix_dirent *)p; |
220 | if ((char *)de == dir_end) { | 247 | de3 = (minix3_dirent *)p; |
248 | if (sbi->s_version == MINIX_V3) { | ||
249 | namx = de3->name; | ||
250 | inumber = de3->inode; | ||
251 | } else { | ||
252 | namx = de->name; | ||
253 | inumber = de->inode; | ||
254 | } | ||
255 | if (p == dir_end) { | ||
221 | /* We hit i_size */ | 256 | /* We hit i_size */ |
222 | de->inode = 0; | 257 | if (sbi->s_version == MINIX_V3) |
258 | de3->inode = 0; | ||
259 | else | ||
260 | de->inode = 0; | ||
223 | goto got_it; | 261 | goto got_it; |
224 | } | 262 | } |
225 | if (!de->inode) | 263 | if (!inumber) |
226 | goto got_it; | 264 | goto got_it; |
227 | err = -EEXIST; | 265 | err = -EEXIST; |
228 | if (namecompare(namelen,sbi->s_namelen,name,de->name)) | 266 | if (namecompare(namelen, sbi->s_namelen, name, namx)) |
229 | goto out_unlock; | 267 | goto out_unlock; |
230 | de = minix_next_entry(de, sbi); | ||
231 | } | 268 | } |
232 | unlock_page(page); | 269 | unlock_page(page); |
233 | dir_put_page(page); | 270 | dir_put_page(page); |
@@ -236,14 +273,19 @@ int minix_add_link(struct dentry *dentry, struct inode *inode) | |||
236 | return -EINVAL; | 273 | return -EINVAL; |
237 | 274 | ||
238 | got_it: | 275 | got_it: |
239 | from = (char*)de - (char*)page_address(page); | 276 | from = p - (char*)page_address(page); |
240 | to = from + sbi->s_dirsize; | 277 | to = from + sbi->s_dirsize; |
241 | err = page->mapping->a_ops->prepare_write(NULL, page, from, to); | 278 | err = page->mapping->a_ops->prepare_write(NULL, page, from, to); |
242 | if (err) | 279 | if (err) |
243 | goto out_unlock; | 280 | goto out_unlock; |
244 | memcpy (de->name, name, namelen); | 281 | memcpy (namx, name, namelen); |
245 | memset (de->name + namelen, 0, sbi->s_dirsize - namelen - 2); | 282 | if (sbi->s_version == MINIX_V3) { |
246 | de->inode = inode->i_ino; | 283 | memset (namx + namelen, 0, sbi->s_dirsize - namelen - 4); |
284 | de3->inode = inode->i_ino; | ||
285 | } else { | ||
286 | memset (namx + namelen, 0, sbi->s_dirsize - namelen - 2); | ||
287 | de->inode = inode->i_ino; | ||
288 | } | ||
247 | err = dir_commit_chunk(page, from, to); | 289 | err = dir_commit_chunk(page, from, to); |
248 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; | 290 | dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; |
249 | mark_inode_dirty(dir); | 291 | mark_inode_dirty(dir); |
@@ -283,8 +325,7 @@ int minix_make_empty(struct inode *inode, struct inode *dir) | |||
283 | { | 325 | { |
284 | struct address_space *mapping = inode->i_mapping; | 326 | struct address_space *mapping = inode->i_mapping; |
285 | struct page *page = grab_cache_page(mapping, 0); | 327 | struct page *page = grab_cache_page(mapping, 0); |
286 | struct minix_sb_info * sbi = minix_sb(inode->i_sb); | 328 | struct minix_sb_info *sbi = minix_sb(inode->i_sb); |
287 | struct minix_dir_entry * de; | ||
288 | char *kaddr; | 329 | char *kaddr; |
289 | int err; | 330 | int err; |
290 | 331 | ||
@@ -299,12 +340,23 @@ int minix_make_empty(struct inode *inode, struct inode *dir) | |||
299 | kaddr = kmap_atomic(page, KM_USER0); | 340 | kaddr = kmap_atomic(page, KM_USER0); |
300 | memset(kaddr, 0, PAGE_CACHE_SIZE); | 341 | memset(kaddr, 0, PAGE_CACHE_SIZE); |
301 | 342 | ||
302 | de = (struct minix_dir_entry *)kaddr; | 343 | if (sbi->s_version == MINIX_V3) { |
303 | de->inode = inode->i_ino; | 344 | minix3_dirent *de3 = (minix3_dirent *)kaddr; |
304 | strcpy(de->name,"."); | 345 | |
305 | de = minix_next_entry(de, sbi); | 346 | de3->inode = inode->i_ino; |
306 | de->inode = dir->i_ino; | 347 | strcpy(de3->name, "."); |
307 | strcpy(de->name,".."); | 348 | de3 = minix_next_entry(de3, sbi); |
349 | de3->inode = dir->i_ino; | ||
350 | strcpy(de3->name, ".."); | ||
351 | } else { | ||
352 | minix_dirent *de = (minix_dirent *)kaddr; | ||
353 | |||
354 | de->inode = inode->i_ino; | ||
355 | strcpy(de->name, "."); | ||
356 | de = minix_next_entry(de, sbi); | ||
357 | de->inode = dir->i_ino; | ||
358 | strcpy(de->name, ".."); | ||
359 | } | ||
308 | kunmap_atomic(kaddr, KM_USER0); | 360 | kunmap_atomic(kaddr, KM_USER0); |
309 | 361 | ||
310 | err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize); | 362 | err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize); |
@@ -321,33 +373,41 @@ int minix_empty_dir(struct inode * inode) | |||
321 | struct page *page = NULL; | 373 | struct page *page = NULL; |
322 | unsigned long i, npages = dir_pages(inode); | 374 | unsigned long i, npages = dir_pages(inode); |
323 | struct minix_sb_info *sbi = minix_sb(inode->i_sb); | 375 | struct minix_sb_info *sbi = minix_sb(inode->i_sb); |
376 | char *name; | ||
377 | __u32 inumber; | ||
324 | 378 | ||
325 | for (i = 0; i < npages; i++) { | 379 | for (i = 0; i < npages; i++) { |
326 | char *kaddr; | 380 | char *p, *kaddr, *limit; |
327 | minix_dirent * de; | ||
328 | page = dir_get_page(inode, i); | ||
329 | 381 | ||
382 | page = dir_get_page(inode, i); | ||
330 | if (IS_ERR(page)) | 383 | if (IS_ERR(page)) |
331 | continue; | 384 | continue; |
332 | 385 | ||
333 | kaddr = (char *)page_address(page); | 386 | kaddr = (char *)page_address(page); |
334 | de = (minix_dirent *)kaddr; | 387 | limit = kaddr + minix_last_byte(inode, i) - sbi->s_dirsize; |
335 | kaddr += minix_last_byte(inode, i) - sbi->s_dirsize; | 388 | for (p = kaddr; p <= limit; p = minix_next_entry(p, sbi)) { |
389 | if (sbi->s_version == MINIX_V3) { | ||
390 | minix3_dirent *de3 = (minix3_dirent *)p; | ||
391 | name = de3->name; | ||
392 | inumber = de3->inode; | ||
393 | } else { | ||
394 | minix_dirent *de = (minix_dirent *)p; | ||
395 | name = de->name; | ||
396 | inumber = de->inode; | ||
397 | } | ||
336 | 398 | ||
337 | while ((char *)de <= kaddr) { | 399 | if (inumber != 0) { |
338 | if (de->inode != 0) { | ||
339 | /* check for . and .. */ | 400 | /* check for . and .. */ |
340 | if (de->name[0] != '.') | 401 | if (name[0] != '.') |
341 | goto not_empty; | 402 | goto not_empty; |
342 | if (!de->name[1]) { | 403 | if (!name[1]) { |
343 | if (de->inode != inode->i_ino) | 404 | if (inumber != inode->i_ino) |
344 | goto not_empty; | 405 | goto not_empty; |
345 | } else if (de->name[1] != '.') | 406 | } else if (name[1] != '.') |
346 | goto not_empty; | 407 | goto not_empty; |
347 | else if (de->name[2]) | 408 | else if (name[2]) |
348 | goto not_empty; | 409 | goto not_empty; |
349 | } | 410 | } |
350 | de = minix_next_entry(de, sbi); | ||
351 | } | 411 | } |
352 | dir_put_page(page); | 412 | dir_put_page(page); |
353 | } | 413 | } |