Merge with 2.5.75.
[linux-2.6/linux-mips.git] / fs / umsdos / dir.c
blob775f020211288a583f9241b8e4c5b3bf60d48bec
1 /*
2 * linux/fs/umsdos/dir.c
4 * Written 1993 by Jacques Gelinas
5 * Inspired from linux/fs/msdos/... : Werner Almesberger
7 * Extended MS-DOS directory handling functions
8 */
10 #include <linux/time.h>
11 #include <linux/string.h>
12 #include <linux/fs.h>
13 #include <linux/msdos_fs.h>
14 #include <linux/errno.h>
15 #include <linux/stat.h>
16 #include <linux/limits.h>
17 #include <linux/umsdos_fs.h>
18 #include <linux/slab.h>
19 #include <linux/pagemap.h>
20 #include <linux/smp_lock.h>
22 #define UMSDOS_SPECIAL_DIRFPOS 3
23 extern struct dentry *saved_root;
24 extern struct inode *pseudo_root;
26 /* #define UMSDOS_DEBUG_VERBOSE 1 */
29 * Dentry operations routines
32 /* nothing for now ... */
33 static int umsdos_dentry_validate(struct dentry *dentry, struct nameidata *nd)
35 return 1;
38 /* for now, drop everything to force lookups ... */
39 /* ITYM s/everything/& positive/... */
40 static int umsdos_dentry_dput(struct dentry *dentry)
42 struct inode *inode = dentry->d_inode;
43 if (inode) {
44 return 1;
46 return 0;
49 struct dentry_operations umsdos_dentry_operations =
51 .d_revalidate = umsdos_dentry_validate,
52 .d_delete = umsdos_dentry_dput,
55 struct UMSDOS_DIR_ONCE {
56 void *dirbuf;
57 filldir_t filldir;
58 int count;
59 int stop;
63 * Record a single entry the first call.
64 * Return -EINVAL the next one.
65 * NOTE: filldir DOES NOT use a dentry
68 static int umsdos_dir_once ( void *buf,
69 const char *name,
70 int len,
71 loff_t offset,
72 ino_t ino,
73 unsigned type)
75 int ret = -EINVAL;
76 struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *) buf;
78 if (d->count == 0) {
79 PRINTK ((KERN_DEBUG "dir_once :%.*s: offset %Ld\n",
80 len, name, offset));
81 ret = d->filldir (d->dirbuf, name, len, offset, ino, DT_UNKNOWN);
82 d->stop = ret < 0;
83 d->count = 1;
85 return ret;
90 * Read count directory entries from directory filp
91 * Return a negative value from linux/errno.h.
92 * Return > 0 if success (the number of bytes written by filldir).
94 * This function is used by the normal readdir VFS entry point,
95 * and in order to get the directory entry from a file's dentry.
96 * See umsdos_dentry_to_entry() below.
99 static int umsdos_readdir_x (struct inode *dir, struct file *filp,
100 void *dirbuf, struct umsdos_dirent *u_entry,
101 filldir_t filldir)
103 struct dentry *demd;
104 off_t start_fpos;
105 int ret = 0;
106 loff_t pos;
108 umsdos_startlookup (dir);
110 if (filp->f_pos == UMSDOS_SPECIAL_DIRFPOS && dir == pseudo_root) {
113 * We don't need to simulate this pseudo directory
114 * when umsdos_readdir_x is called for internal operation
115 * of umsdos. This is why dirent_in_fs is tested
117 /* #Specification: pseudo root / directory /DOS
118 * When umsdos operates in pseudo root mode (C:\linux is the
119 * linux root), it simulate a directory /DOS which points to
120 * the real root of the file system.
123 Printk ((KERN_WARNING "umsdos_readdir_x: pseudo_root thing UMSDOS_SPECIAL_DIRFPOS\n"));
124 if (filldir (dirbuf, "DOS", 3,
125 UMSDOS_SPECIAL_DIRFPOS, UMSDOS_ROOT_INO, DT_DIR) == 0) {
126 filp->f_pos++;
128 goto out_end;
131 if (filp->f_pos < 2 ||
132 (dir->i_ino != UMSDOS_ROOT_INO && filp->f_pos == 32)) {
134 int last_f_pos = filp->f_pos;
135 struct UMSDOS_DIR_ONCE bufk;
137 Printk (("umsdos_readdir_x: . or .. /mn/?\n"));
139 bufk.dirbuf = dirbuf;
140 bufk.filldir = filldir;
141 bufk.count = 0;
143 ret = fat_readdir (filp, &bufk, umsdos_dir_once);
144 if (last_f_pos > 0 && filp->f_pos > last_f_pos)
145 filp->f_pos = UMSDOS_SPECIAL_DIRFPOS;
146 if (u_entry != NULL)
147 u_entry->flags = 0;
148 goto out_end;
151 Printk (("umsdos_readdir_x: normal file /mn/?\n"));
153 /* get the EMD dentry */
154 demd = umsdos_get_emd_dentry(filp->f_dentry);
155 ret = PTR_ERR(demd);
156 if (IS_ERR(demd))
157 goto out_end;
158 ret = -EIO;
159 if (!demd->d_inode) {
160 printk(KERN_WARNING
161 "umsdos_readir_x: EMD file %s/%s not found\n",
162 demd->d_parent->d_name.name, demd->d_name.name);
163 goto out_dput;
166 pos = filp->f_pos;
167 start_fpos = filp->f_pos;
169 if (pos <= UMSDOS_SPECIAL_DIRFPOS + 1)
170 pos = 0;
171 ret = 0;
172 while (pos < demd->d_inode->i_size) {
173 off_t cur_f_pos = pos;
174 struct dentry *dret;
175 struct inode *inode;
176 struct umsdos_dirent entry;
177 struct umsdos_info info;
179 ret = -EIO;
180 if (umsdos_emd_dir_readentry (demd, &pos, &entry) != 0)
181 break;
182 if (entry.name_len == 0)
183 continue;
184 #ifdef UMSDOS_DEBUG_VERBOSE
185 if (entry.flags & UMSDOS_HLINK)
186 printk("umsdos_readdir_x: %s/%s is hardlink\n",
187 filp->f_dentry->d_name.name, entry.name);
188 #endif
190 umsdos_parse (entry.name, entry.name_len, &info);
191 info.f_pos = cur_f_pos;
192 umsdos_manglename (&info);
194 * Do a real lookup on the short name.
196 dret = umsdos_covered(filp->f_dentry, info.fake.fname,
197 info.fake.len);
198 ret = PTR_ERR(dret);
199 if (IS_ERR(dret))
200 break;
202 * If the file wasn't found, remove it from the EMD.
204 inode = dret->d_inode;
205 if (!inode)
206 goto remove_name;
207 #ifdef UMSDOS_DEBUG_VERBOSE
208 if (UMSDOS_I(inode)->i_is_hlink)
209 printk("umsdos_readdir_x: %s/%s already resolved, ino=%ld\n",
210 dret->d_parent->d_name.name, dret->d_name.name, inode->i_ino);
211 #endif
213 Printk (("Found %s/%s, ino=%ld, flags=%x\n",
214 dret->d_parent->d_name.name, info.fake.fname, dret->d_inode->i_ino,
215 entry.flags));
216 /* check whether to resolve a hard-link */
217 if ((entry.flags & UMSDOS_HLINK) &&
218 !UMSDOS_I(inode)->i_is_hlink) {
219 dret = umsdos_solve_hlink (dret);
220 ret = PTR_ERR(dret);
221 if (IS_ERR(dret))
222 break;
223 inode = dret->d_inode;
224 if (!inode) {
225 printk("umsdos_readdir_x: %s/%s negative after link\n",
226 dret->d_parent->d_name.name, dret->d_name.name);
227 goto clean_up;
231 /* #Specification: pseudo root / reading real root
232 * The pseudo root (/linux) is logically
233 * erased from the real root. This means that
234 * ls /DOS, won't show "linux". This avoids
235 * infinite recursion (/DOS/linux/DOS/linux/...) while
236 * walking the file system.
238 if (inode != pseudo_root && !(entry.flags & UMSDOS_HIDDEN)) {
239 if (filldir (dirbuf, entry.name, entry.name_len,
240 cur_f_pos, inode->i_ino, DT_UNKNOWN) < 0) {
241 pos = cur_f_pos;
243 Printk(("umsdos_readdir_x: got %s/%s, ino=%ld\n",
244 dret->d_parent->d_name.name, dret->d_name.name, inode->i_ino));
245 if (u_entry != NULL)
246 *u_entry = entry;
247 dput(dret);
248 ret = 0;
249 break;
251 clean_up:
252 dput(dret);
253 continue;
255 remove_name:
256 /* #Specification: umsdos / readdir / not in MSDOS
257 * During a readdir operation, if the file is not
258 * in the MS-DOS directory any more, the entry is
259 * removed from the EMD file silently.
261 #ifdef UMSDOS_PARANOIA
262 printk("umsdos_readdir_x: %s/%s out of sync, erasing\n",
263 filp->f_dentry->d_name.name, info.entry.name);
264 #endif
265 ret = umsdos_delentry(filp->f_dentry, &info,
266 S_ISDIR(info.entry.mode));
267 if (ret)
268 printk(KERN_WARNING
269 "umsdos_readdir_x: delentry %s, err=%d\n",
270 info.entry.name, ret);
271 goto clean_up;
274 * If the fillbuf has failed, f_pos is back to 0.
275 * To avoid getting back into the . and .. state
276 * (see comments at the beginning), we put back
277 * the special offset.
279 filp->f_pos = pos;
280 if (filp->f_pos == 0)
281 filp->f_pos = start_fpos;
282 out_dput:
283 dput(demd);
285 out_end:
286 umsdos_endlookup (dir);
288 Printk ((KERN_DEBUG "read dir %p pos %Ld ret %d\n",
289 dir, filp->f_pos, ret));
290 return ret;
295 * Read count directory entries from directory filp.
296 * Return a negative value from linux/errno.h.
297 * Return 0 or positive if successful.
300 static int UMSDOS_readdir (struct file *filp, void *dirbuf, filldir_t filldir)
302 struct inode *dir = filp->f_dentry->d_inode;
303 int ret = 0, count = 0;
304 struct UMSDOS_DIR_ONCE bufk;
306 lock_kernel();
308 bufk.dirbuf = dirbuf;
309 bufk.filldir = filldir;
310 bufk.stop = 0;
312 Printk (("UMSDOS_readdir in\n"));
313 while (ret == 0 && bufk.stop == 0) {
314 struct umsdos_dirent entry;
316 bufk.count = 0;
317 ret = umsdos_readdir_x (dir, filp, &bufk, &entry,
318 umsdos_dir_once);
319 if (bufk.count == 0)
320 break;
321 count += bufk.count;
323 unlock_kernel();
324 Printk (("UMSDOS_readdir out %d count %d pos %Ld\n",
325 ret, count, filp->f_pos));
326 return count ? : ret;
331 * Complete the inode content with info from the EMD file.
333 * This function modifies the state of a dir inode. It decides
334 * whether the dir is a UMSDOS or DOS directory. This is done
335 * deeper in umsdos_patch_inode() called at the end of this function.
337 * Because it is does disk access, umsdos_patch_inode() may block.
338 * At the same time, another process may get here to initialise
339 * the same directory inode. There are three cases.
341 * 1) The inode is already initialised. We do nothing.
342 * 2) The inode is not initialised. We lock access and do it.
343 * 3) Like 2 but another process has locked the inode, so we try
344 * to lock it and check right afterward check whether
345 * initialisation is still needed.
348 * Thanks to the "mem" option of the kernel command line, it was
349 * possible to consistently reproduce this problem by limiting
350 * my memory to 4 MB and running X.
352 * Do this only if the inode is freshly read, because we will lose
353 * the current (updated) content.
355 * A lookup of a mount point directory yield the inode into
356 * the other fs, so we don't care about initialising it. iget()
357 * does this automatically.
360 void umsdos_lookup_patch_new(struct dentry *dentry, struct umsdos_info *info)
362 struct inode *inode = dentry->d_inode;
363 struct umsdos_dirent *entry = &info->entry;
366 * This part of the initialization depends only on i_patched.
368 if (UMSDOS_I(inode)->i_patched)
369 goto out;
370 UMSDOS_I(inode)->i_patched = 1;
371 if (S_ISREG (entry->mode))
372 entry->mtime = inode->i_mtime;
373 inode->i_mode = entry->mode;
374 inode->i_rdev = to_kdev_t (entry->rdev);
375 inode->i_atime = entry->atime;
376 inode->i_ctime = entry->ctime;
377 inode->i_mtime = entry->mtime;
378 inode->i_uid = entry->uid;
379 inode->i_gid = entry->gid;
381 /* #Specification: umsdos / i_nlink
382 * The nlink field of an inode is maintained by the MSDOS file system
383 * for directory and by UMSDOS for other files. The logic is that
384 * MSDOS is already figuring out what to do for directories and
385 * does nothing for other files. For MSDOS, there are no hard links
386 * so all file carry nlink==1. UMSDOS use some info in the
387 * EMD file to plug the correct value.
389 if (!S_ISDIR (entry->mode)) {
390 if (entry->nlink > 0) {
391 inode->i_nlink = entry->nlink;
392 } else {
393 printk (KERN_ERR
394 "UMSDOS: lookup_patch entry->nlink < 1 ???\n");
398 * The mode may have changed, so patch the inode again.
400 umsdos_patch_dentry_inode(dentry, info->f_pos);
401 umsdos_set_dirinfo_new(dentry, info->f_pos);
403 out:
404 return;
409 * Return != 0 if an entry is the pseudo DOS entry in the pseudo root.
412 int umsdos_is_pseudodos (struct inode *dir, struct dentry *dentry)
414 /* #Specification: pseudo root / DOS hard coded
415 * The pseudo sub-directory DOS in the pseudo root is hard coded.
416 * The name is DOS. This is done this way to help standardised
417 * the umsdos layout. The idea is that from now on /DOS is
418 * a reserved path and nobody will think of using such a path
419 * for a package.
421 return dir == pseudo_root
422 && dentry->d_name.len == 3
423 && dentry->d_name.name[0] == 'D'
424 && dentry->d_name.name[1] == 'O'
425 && dentry->d_name.name[2] == 'S';
430 * Check whether a file exists in the current directory.
431 * Return 0 if OK, negative error code if not (ex: -ENOENT).
433 * fills dentry->d_inode with found inode, and increments its count.
434 * if not found, return -ENOENT.
436 /* #Specification: umsdos / lookup
437 * A lookup for a file is done in two steps. First, we
438 * locate the file in the EMD file. If not present, we
439 * return an error code (-ENOENT). If it is there, we
440 * repeat the operation on the msdos file system. If
441 * this fails, it means that the file system is not in
442 * sync with the EMD file. We silently remove this
443 * entry from the EMD file, and return ENOENT.
446 struct dentry *umsdos_lookup_x (struct inode *dir, struct dentry *dentry, int nopseudo)
448 struct dentry *dret = NULL;
449 struct inode *inode;
450 int ret = -ENOENT;
451 struct umsdos_info info;
453 #ifdef UMSDOS_DEBUG_VERBOSE
454 printk("umsdos_lookup_x: looking for %s/%s\n",
455 dentry->d_parent->d_name.name, dentry->d_name.name);
456 #endif
458 umsdos_startlookup (dir);
459 if (umsdos_is_pseudodos (dir, dentry)) {
460 /* #Specification: pseudo root / lookup(DOS)
461 * A lookup of DOS in the pseudo root will always succeed
462 * and return the inode of the real root.
464 Printk ((KERN_DEBUG "umsdos_lookup_x: following /DOS\n"));
465 inode = saved_root->d_inode;
466 goto out_add;
469 ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
470 if (ret) {
471 printk("umsdos_lookup_x: %s/%s parse failed, ret=%d\n",
472 dentry->d_parent->d_name.name, dentry->d_name.name, ret);
473 goto out;
476 ret = umsdos_findentry (dentry->d_parent, &info, 0);
477 if (ret) {
478 if (ret != -ENOENT)
479 printk("umsdos_lookup_x: %s/%s findentry failed, ret=%d\n",
480 dentry->d_parent->d_name.name, dentry->d_name.name, ret);
481 goto out;
483 Printk (("lookup %.*s pos %lu ret %d len %d ",
484 info.fake.len, info.fake.fname, info.f_pos, ret, info.fake.len));
486 /* do a real lookup to get the short name ... */
487 dret = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
488 ret = PTR_ERR(dret);
489 if (IS_ERR(dret)) {
490 printk("umsdos_lookup_x: %s/%s real lookup failed, ret=%d\n",
491 dentry->d_parent->d_name.name, dentry->d_name.name, ret);
492 goto out;
494 inode = dret->d_inode;
495 if (!inode)
496 goto out_remove;
497 umsdos_lookup_patch_new(dret, &info);
498 #ifdef UMSDOS_DEBUG_VERBOSE
499 printk("umsdos_lookup_x: found %s/%s, ino=%ld\n",
500 dret->d_parent->d_name.name, dret->d_name.name, dret->d_inode->i_ino);
501 #endif
503 /* Check for a hard link */
504 if ((info.entry.flags & UMSDOS_HLINK) &&
505 !UMSDOS_I(inode)->i_is_hlink) {
506 dret = umsdos_solve_hlink (dret);
507 ret = PTR_ERR(dret);
508 if (IS_ERR(dret))
509 goto out;
510 ret = -ENOENT;
511 inode = dret->d_inode;
512 if (!inode) {
513 printk("umsdos_lookup_x: %s/%s negative after link\n",
514 dret->d_parent->d_name.name, dret->d_name.name);
515 goto out_dput;
519 if (inode == pseudo_root && !nopseudo) {
520 /* #Specification: pseudo root / dir lookup
521 * For the same reason as readdir, a lookup in /DOS for
522 * the pseudo root directory (linux) will fail.
525 * This has to be allowed for resolving hard links
526 * which are recorded independently of the pseudo-root
527 * mode.
529 printk("umsdos_lookup_x: skipping DOS/linux\n");
530 ret = -ENOENT;
531 goto out_dput;
535 * We've found it OK. Now hash the dentry with the inode.
537 out_add:
538 atomic_inc(&inode->i_count);
539 d_add (dentry, inode);
540 dentry->d_op = &umsdos_dentry_operations;
541 ret = 0;
543 out_dput:
544 if (dret && dret != dentry)
545 d_drop(dret);
546 dput(dret);
547 out:
548 umsdos_endlookup (dir);
549 return ERR_PTR(ret);
551 out_remove:
552 printk(KERN_WARNING "UMSDOS: entry %s/%s out of sync, erased\n",
553 dentry->d_parent->d_name.name, dentry->d_name.name);
554 umsdos_delentry (dentry->d_parent, &info, S_ISDIR (info.entry.mode));
555 ret = -ENOENT;
556 goto out_dput;
561 * Check whether a file exists in the current directory.
562 * Return 0 if OK, negative error code if not (ex: -ENOENT).
564 * Called by VFS; should fill dentry->d_inode via d_add.
567 struct dentry *UMSDOS_lookup (struct inode *dir, struct dentry *dentry, struct nameidata *nd)
569 struct dentry *ret;
571 ret = umsdos_lookup_x (dir, dentry, 0);
573 /* Create negative dentry if not found. */
574 if (ret == ERR_PTR(-ENOENT)) {
575 Printk ((KERN_DEBUG
576 "UMSDOS_lookup: converting -ENOENT to negative\n"));
577 d_add (dentry, NULL);
578 dentry->d_op = &umsdos_dentry_operations;
579 ret = NULL;
581 return ret;
584 struct dentry *umsdos_covered(struct dentry *parent, char *name, int len)
586 struct dentry *result, *dentry;
587 struct qstr qstr;
589 qstr.name = name;
590 qstr.len = len;
591 qstr.hash = full_name_hash(name, len);
592 result = ERR_PTR(-ENOMEM);
593 dentry = d_alloc(parent, &qstr);
594 if (dentry) {
595 /* XXXXXXXXXXXXXXXXXXX Race alert! */
596 result = UMSDOS_rlookup(parent->d_inode, dentry);
597 d_drop(dentry);
598 if (result)
599 goto out_fail;
600 return dentry;
602 out:
603 return result;
605 out_fail:
606 dput(dentry);
607 goto out;
611 * Lookup or create a dentry from within the filesystem.
613 * We need to use this instead of lookup_dentry, as the
614 * directory semaphore lock is already held.
616 struct dentry *umsdos_lookup_dentry(struct dentry *parent, char *name, int len,
617 int real)
619 struct dentry *result, *dentry;
620 struct qstr qstr;
622 qstr.name = name;
623 qstr.len = len;
624 qstr.hash = full_name_hash(name, len);
625 result = d_lookup(parent, &qstr);
626 if (!result) {
627 result = ERR_PTR(-ENOMEM);
628 dentry = d_alloc(parent, &qstr);
629 if (dentry) {
630 result = real ?
631 UMSDOS_rlookup(parent->d_inode, dentry) :
632 UMSDOS_lookup(parent->d_inode, dentry);
633 if (result)
634 goto out_fail;
635 return dentry;
638 out:
639 return result;
641 out_fail:
642 dput(dentry);
643 goto out;
647 * Return a path relative to our root.
649 char * umsdos_d_path(struct dentry *dentry, char * buffer, int len)
651 struct dentry * old_root;
652 char * path;
654 read_lock(&current->fs->lock);
655 old_root = dget(current->fs->root);
656 read_unlock(&current->fs->lock);
657 spin_lock(&dcache_lock);
658 path = __d_path(dentry, current->fs->rootmnt, dentry->d_sb->s_root, current->fs->rootmnt, buffer, len); /* FIXME: current->fs->rootmnt */
659 spin_unlock(&dcache_lock);
661 if (*path == '/')
662 path++; /* skip leading '/' */
664 if (current->fs->root->d_inode == pseudo_root)
666 *(path-1) = '/';
667 path -= (UMSDOS_PSDROOT_LEN+1);
668 memcpy(path, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN);
670 dput(old_root);
672 return path;
676 * Return the dentry which points to a pseudo-hardlink.
678 * it should try to find file it points to
679 * if file is found, return new dentry/inode
680 * The resolved inode will have i_is_hlink set.
682 * Note: the original dentry is always dput(), even if an error occurs.
685 struct dentry *umsdos_solve_hlink (struct dentry *hlink)
687 /* root is our root for resolving pseudo-hardlink */
688 struct dentry *base = hlink->d_sb->s_root;
689 struct dentry *dentry_dst;
690 char *path, *pt;
691 int len;
692 struct address_space *mapping = hlink->d_inode->i_mapping;
693 struct page *page;
695 page=read_cache_page(mapping,0,(filler_t *)mapping->a_ops->readpage,NULL);
696 dentry_dst=(struct dentry *)page;
697 if (IS_ERR(page))
698 goto out;
699 wait_on_page_locked(page);
700 if (!PageUptodate(page))
701 goto async_fail;
703 dentry_dst = ERR_PTR(-ENOMEM);
704 path = (char *) kmalloc (PATH_MAX, GFP_KERNEL);
705 if (path == NULL)
706 goto out_release;
707 memcpy(path, kmap(page), hlink->d_inode->i_size);
708 kunmap(page);
709 page_cache_release(page);
711 len = hlink->d_inode->i_size;
713 /* start at root dentry */
714 dentry_dst = dget(base);
715 path[len] = '\0';
717 pt = path;
718 if (*path == '/')
719 pt++; /* skip leading '/' */
721 if (base->d_inode == pseudo_root)
722 pt += (UMSDOS_PSDROOT_LEN + 1);
724 while (1) {
725 struct dentry *dir = dentry_dst, *demd;
726 char *start = pt;
727 int real;
729 while (*pt != '\0' && *pt != '/') pt++;
730 len = (int) (pt - start);
731 if (*pt == '/') *pt++ = '\0';
733 real = 1;
734 demd = umsdos_get_emd_dentry(dir);
735 if (!IS_ERR(demd)) {
736 if (demd->d_inode)
737 real = 0;
738 dput(demd);
741 #ifdef UMSDOS_DEBUG_VERBOSE
742 printk ("umsdos_solve_hlink: dir %s/%s, name=%s, real=%d\n",
743 dir->d_parent->d_name.name, dir->d_name.name, start, real);
744 #endif
745 dentry_dst = umsdos_lookup_dentry(dir, start, len, real);
746 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
747 if (real)
748 d_drop(dir);
749 dput (dir);
750 if (IS_ERR(dentry_dst))
751 break;
752 /* not found? stop search ... */
753 if (!dentry_dst->d_inode) {
754 break;
756 if (*pt == '\0') /* we're finished! */
757 break;
758 } /* end while */
760 if (!IS_ERR(dentry_dst)) {
761 struct inode *inode = dentry_dst->d_inode;
762 if (inode) {
763 UMSDOS_I(inode)->i_is_hlink = 1;
764 #ifdef UMSDOS_DEBUG_VERBOSE
765 printk ("umsdos_solve_hlink: resolved link %s/%s, ino=%ld\n",
766 dentry_dst->d_parent->d_name.name, dentry_dst->d_name.name, inode->i_ino);
767 #endif
768 } else {
769 #ifdef UMSDOS_DEBUG_VERBOSE
770 printk ("umsdos_solve_hlink: resolved link %s/%s negative!\n",
771 dentry_dst->d_parent->d_name.name, dentry_dst->d_name.name);
772 #endif
774 } else
775 printk(KERN_WARNING
776 "umsdos_solve_hlink: err=%ld\n", PTR_ERR(dentry_dst));
777 kfree (path);
779 out:
780 dput(hlink); /* original hlink no longer needed */
781 return dentry_dst;
783 async_fail:
784 dentry_dst = ERR_PTR(-EIO);
785 out_release:
786 page_cache_release(page);
787 goto out;
791 struct file_operations umsdos_dir_operations =
793 .read = generic_read_dir,
794 .readdir = UMSDOS_readdir,
795 .ioctl = UMSDOS_ioctl_dir,
798 struct inode_operations umsdos_dir_inode_operations =
800 .create = UMSDOS_create,
801 .lookup = UMSDOS_lookup,
802 .link = UMSDOS_link,
803 .unlink = UMSDOS_unlink,
804 .symlink = UMSDOS_symlink,
805 .mkdir = UMSDOS_mkdir,
806 .rmdir = UMSDOS_rmdir,
807 .mknod = UMSDOS_mknod,
808 .rename = UMSDOS_rename,
809 .setattr = UMSDOS_notify_change,