* add p cc
[mascara-docs.git] / i386 / linux / linux-2.3.21 / fs / umsdos / dir.c
blobc09c293cf5911ca4723b7e3ad07942bc59a99275
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/sched.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/malloc.h>
20 #include <asm/uaccess.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, int flags)
35 return 1;
38 /* for now, drop everything to force lookups ... */
39 static void umsdos_dentry_dput(struct dentry *dentry)
41 struct inode *inode = dentry->d_inode;
42 if (inode) {
43 d_drop(dentry);
47 struct dentry_operations umsdos_dentry_operations =
49 umsdos_dentry_validate, /* d_revalidate(struct dentry *, int) */
50 NULL, /* d_hash */
51 NULL, /* d_compare */
52 umsdos_dentry_dput, /* d_delete(struct dentry *) */
53 NULL,
54 NULL,
59 * So grep * doesn't complain in the presence of directories.
62 int dummy_dir_read (struct file *filp, char *buff, size_t size, loff_t *count)
64 return -EISDIR;
68 struct UMSDOS_DIR_ONCE {
69 void *dirbuf;
70 filldir_t filldir;
71 int count;
72 int stop;
76 * Record a single entry the first call.
77 * Return -EINVAL the next one.
78 * NOTE: filldir DOES NOT use a dentry
81 static int umsdos_dir_once ( void *buf,
82 const char *name,
83 int len,
84 off_t offset,
85 ino_t ino)
87 int ret = -EINVAL;
88 struct UMSDOS_DIR_ONCE *d = (struct UMSDOS_DIR_ONCE *) buf;
90 if (d->count == 0) {
91 PRINTK ((KERN_DEBUG "dir_once :%.*s: offset %Ld\n",
92 len, name, offset));
93 ret = d->filldir (d->dirbuf, name, len, offset, ino);
94 d->stop = ret < 0;
95 d->count = 1;
97 return ret;
102 * Read count directory entries from directory filp
103 * Return a negative value from linux/errno.h.
104 * Return > 0 if success (the number of bytes written by filldir).
106 * This function is used by the normal readdir VFS entry point,
107 * and in order to get the directory entry from a file's dentry.
108 * See umsdos_dentry_to_entry() below.
111 static int umsdos_readdir_x (struct inode *dir, struct file *filp,
112 void *dirbuf, int internal_read,
113 struct umsdos_dirent *u_entry,
114 int follow_hlink, filldir_t filldir)
116 struct dentry *demd;
117 off_t start_fpos;
118 int ret = 0;
119 struct file new_filp;
121 umsdos_startlookup (dir);
123 if (filp->f_pos == UMSDOS_SPECIAL_DIRFPOS &&
124 dir == pseudo_root && !internal_read) {
127 * We don't need to simulate this pseudo directory
128 * when umsdos_readdir_x is called for internal operation
129 * of umsdos. This is why dirent_in_fs is tested
131 /* #Specification: pseudo root / directory /DOS
132 * When umsdos operates in pseudo root mode (C:\linux is the
133 * linux root), it simulate a directory /DOS which points to
134 * the real root of the file system.
137 Printk ((KERN_WARNING "umsdos_readdir_x: pseudo_root thing UMSDOS_SPECIAL_DIRFPOS\n"));
138 if (filldir (dirbuf, "DOS", 3,
139 UMSDOS_SPECIAL_DIRFPOS, UMSDOS_ROOT_INO) == 0) {
140 filp->f_pos++;
142 goto out_end;
145 if (filp->f_pos < 2 ||
146 (dir->i_ino != UMSDOS_ROOT_INO && filp->f_pos == 32)) {
148 int last_f_pos = filp->f_pos;
149 struct UMSDOS_DIR_ONCE bufk;
151 Printk (("umsdos_readdir_x: . or .. /mn/?\n"));
153 bufk.dirbuf = dirbuf;
154 bufk.filldir = filldir;
155 bufk.count = 0;
157 ret = fat_readdir (filp, &bufk, umsdos_dir_once);
158 if (last_f_pos > 0 && filp->f_pos > last_f_pos)
159 filp->f_pos = UMSDOS_SPECIAL_DIRFPOS;
160 if (u_entry != NULL)
161 u_entry->flags = 0;
162 goto out_end;
165 Printk (("umsdos_readdir_x: normal file /mn/?\n"));
167 /* get the EMD dentry */
168 demd = umsdos_get_emd_dentry(filp->f_dentry);
169 ret = PTR_ERR(demd);
170 if (IS_ERR(demd))
171 goto out_end;
172 ret = -EIO;
173 if (!demd->d_inode) {
174 printk(KERN_WARNING
175 "umsdos_readir_x: EMD file %s/%s not found\n",
176 demd->d_parent->d_name.name, demd->d_name.name);
177 goto out_dput;
180 /* set up our private filp ... */
181 fill_new_filp(&new_filp, demd);
182 new_filp.f_pos = filp->f_pos;
183 start_fpos = filp->f_pos;
185 if (new_filp.f_pos <= UMSDOS_SPECIAL_DIRFPOS + 1)
186 new_filp.f_pos = 0;
187 Printk (("f_pos %Ld i_size %ld\n", new_filp.f_pos, demd->d_inode->i_size));
188 ret = 0;
189 while (new_filp.f_pos < demd->d_inode->i_size) {
190 off_t cur_f_pos = new_filp.f_pos;
191 struct dentry *dret;
192 struct inode *inode;
193 struct umsdos_dirent entry;
194 struct umsdos_info info;
196 ret = -EIO;
197 if (umsdos_emd_dir_readentry (&new_filp, &entry) != 0)
198 break;
199 if (entry.name_len == 0)
200 continue;
201 #ifdef UMSDOS_DEBUG_VERBOSE
202 if (entry.flags & UMSDOS_HLINK)
203 printk("umsdos_readdir_x: %s/%s is hardlink\n",
204 filp->f_dentry->d_name.name, entry.name);
205 #endif
207 umsdos_parse (entry.name, entry.name_len, &info);
208 info.f_pos = cur_f_pos;
209 umsdos_manglename (&info);
211 * Do a real lookup on the short name.
213 dret = umsdos_covered(filp->f_dentry, info.fake.fname,
214 info.fake.len);
215 ret = PTR_ERR(dret);
216 if (IS_ERR(dret))
217 break;
219 * If the file wasn't found, remove it from the EMD.
221 inode = dret->d_inode;
222 if (!inode)
223 goto remove_name;
224 #ifdef UMSDOS_DEBUG_VERBOSE
225 if (inode->u.umsdos_i.i_is_hlink)
226 printk("umsdos_readdir_x: %s/%s already resolved, ino=%ld\n",
227 dret->d_parent->d_name.name, dret->d_name.name, inode->i_ino);
228 #endif
230 Printk (("Found %s/%s, ino=%ld, flags=%x\n",
231 dret->d_parent->d_name.name, info.fake.fname, dret->d_inode->i_ino,
232 entry.flags));
233 /* check whether to resolve a hard-link */
234 if ((entry.flags & UMSDOS_HLINK) && follow_hlink &&
235 !inode->u.umsdos_i.i_is_hlink) {
236 dret = umsdos_solve_hlink (dret);
237 ret = PTR_ERR(dret);
238 if (IS_ERR(dret))
239 break;
240 inode = dret->d_inode;
241 if (!inode) {
242 printk("umsdos_readdir_x: %s/%s negative after link\n",
243 dret->d_parent->d_name.name, dret->d_name.name);
244 goto clean_up;
248 /* #Specification: pseudo root / reading real root
249 * The pseudo root (/linux) is logically
250 * erased from the real root. This means that
251 * ls /DOS, won't show "linux". This avoids
252 * infinite recursion (/DOS/linux/DOS/linux/...) while
253 * walking the file system.
255 if (inode != pseudo_root &&
256 (internal_read || !(entry.flags & UMSDOS_HIDDEN))) {
257 if (filldir (dirbuf, entry.name, entry.name_len,
258 cur_f_pos, inode->i_ino) < 0) {
259 new_filp.f_pos = cur_f_pos;
261 Printk(("umsdos_readdir_x: got %s/%s, ino=%ld\n",
262 dret->d_parent->d_name.name, dret->d_name.name, inode->i_ino));
263 if (u_entry != NULL)
264 *u_entry = entry;
265 dput(dret);
266 ret = 0;
267 break;
269 clean_up:
270 dput(dret);
271 continue;
273 remove_name:
274 /* #Specification: umsdos / readdir / not in MSDOS
275 * During a readdir operation, if the file is not
276 * in the MS-DOS directory any more, the entry is
277 * removed from the EMD file silently.
279 #ifdef UMSDOS_PARANOIA
280 printk("umsdos_readdir_x: %s/%s out of sync, erasing\n",
281 filp->f_dentry->d_name.name, info.entry.name);
282 #endif
283 ret = umsdos_delentry(filp->f_dentry, &info,
284 S_ISDIR(info.entry.mode));
285 if (ret)
286 printk(KERN_WARNING
287 "umsdos_readdir_x: delentry %s, err=%d\n",
288 info.entry.name, ret);
289 goto clean_up;
292 * If the fillbuf has failed, f_pos is back to 0.
293 * To avoid getting back into the . and .. state
294 * (see comments at the beginning), we put back
295 * the special offset.
297 filp->f_pos = new_filp.f_pos;
298 if (filp->f_pos == 0)
299 filp->f_pos = start_fpos;
300 out_dput:
301 dput(demd);
303 out_end:
304 umsdos_endlookup (dir);
306 Printk ((KERN_DEBUG "read dir %p pos %Ld ret %d\n",
307 dir, filp->f_pos, ret));
308 return ret;
313 * Read count directory entries from directory filp.
314 * Return a negative value from linux/errno.h.
315 * Return 0 or positive if successful.
318 static int UMSDOS_readdir (struct file *filp, void *dirbuf, filldir_t filldir)
320 struct inode *dir = filp->f_dentry->d_inode;
321 int ret = 0, count = 0;
322 struct UMSDOS_DIR_ONCE bufk;
324 bufk.dirbuf = dirbuf;
325 bufk.filldir = filldir;
326 bufk.stop = 0;
328 Printk (("UMSDOS_readdir in\n"));
329 while (ret == 0 && bufk.stop == 0) {
330 struct umsdos_dirent entry;
332 bufk.count = 0;
333 ret = umsdos_readdir_x (dir, filp, &bufk, 0, &entry, 1,
334 umsdos_dir_once);
335 if (bufk.count == 0)
336 break;
337 count += bufk.count;
339 Printk (("UMSDOS_readdir out %d count %d pos %Ld\n",
340 ret, count, filp->f_pos));
341 return count ? : ret;
346 * Complete the inode content with info from the EMD file.
348 * This function modifies the state of a dir inode. It decides
349 * whether the dir is a UMSDOS or DOS directory. This is done
350 * deeper in umsdos_patch_inode() called at the end of this function.
352 * Because it is does disk access, umsdos_patch_inode() may block.
353 * At the same time, another process may get here to initialise
354 * the same directory inode. There are three cases.
356 * 1) The inode is already initialised. We do nothing.
357 * 2) The inode is not initialised. We lock access and do it.
358 * 3) Like 2 but another process has locked the inode, so we try
359 * to lock it and check right afterward check whether
360 * initialisation is still needed.
363 * Thanks to the "mem" option of the kernel command line, it was
364 * possible to consistently reproduce this problem by limiting
365 * my memory to 4 MB and running X.
367 * Do this only if the inode is freshly read, because we will lose
368 * the current (updated) content.
370 * A lookup of a mount point directory yield the inode into
371 * the other fs, so we don't care about initialising it. iget()
372 * does this automatically.
375 void umsdos_lookup_patch_new(struct dentry *dentry, struct umsdos_info *info)
377 struct inode *inode = dentry->d_inode;
378 struct umsdos_dirent *entry = &info->entry;
381 * This part of the initialization depends only on i_patched.
383 if (inode->u.umsdos_i.i_patched)
384 goto out;
385 inode->u.umsdos_i.i_patched = 1;
386 if (S_ISREG (entry->mode))
387 entry->mtime = inode->i_mtime;
388 inode->i_mode = entry->mode;
389 inode->i_rdev = to_kdev_t (entry->rdev);
390 inode->i_atime = entry->atime;
391 inode->i_ctime = entry->ctime;
392 inode->i_mtime = entry->mtime;
393 inode->i_uid = entry->uid;
394 inode->i_gid = entry->gid;
396 /* #Specification: umsdos / i_nlink
397 * The nlink field of an inode is maintained by the MSDOS file system
398 * for directory and by UMSDOS for other files. The logic is that
399 * MSDOS is already figuring out what to do for directories and
400 * does nothing for other files. For MSDOS, there are no hard links
401 * so all file carry nlink==1. UMSDOS use some info in the
402 * EMD file to plug the correct value.
404 if (!S_ISDIR (entry->mode)) {
405 if (entry->nlink > 0) {
406 inode->i_nlink = entry->nlink;
407 } else {
408 printk (KERN_ERR
409 "UMSDOS: lookup_patch entry->nlink < 1 ???\n");
413 * The mode may have changed, so patch the inode again.
415 umsdos_patch_dentry_inode(dentry, info->f_pos);
416 umsdos_set_dirinfo_new(dentry, info->f_pos);
418 out:
419 return;
424 * Return != 0 if an entry is the pseudo DOS entry in the pseudo root.
427 int umsdos_is_pseudodos (struct inode *dir, struct dentry *dentry)
429 /* #Specification: pseudo root / DOS hard coded
430 * The pseudo sub-directory DOS in the pseudo root is hard coded.
431 * The name is DOS. This is done this way to help standardised
432 * the umsdos layout. The idea is that from now on /DOS is
433 * a reserved path and nobody will think of using such a path
434 * for a package.
436 return dir == pseudo_root
437 && dentry->d_name.len == 3
438 && dentry->d_name.name[0] == 'D'
439 && dentry->d_name.name[1] == 'O'
440 && dentry->d_name.name[2] == 'S';
445 * Check whether a file exists in the current directory.
446 * Return 0 if OK, negative error code if not (ex: -ENOENT).
448 * fills dentry->d_inode with found inode, and increments its count.
449 * if not found, return -ENOENT.
451 /* #Specification: umsdos / lookup
452 * A lookup for a file is done in two steps. First, we
453 * locate the file in the EMD file. If not present, we
454 * return an error code (-ENOENT). If it is there, we
455 * repeat the operation on the msdos file system. If
456 * this fails, it means that the file system is not in
457 * sync with the EMD file. We silently remove this
458 * entry from the EMD file, and return ENOENT.
461 struct dentry *umsdos_lookup_x (struct inode *dir, struct dentry *dentry, int nopseudo)
463 struct dentry *dret = NULL;
464 struct inode *inode;
465 int ret = -ENOENT;
466 struct umsdos_info info;
468 #ifdef UMSDOS_DEBUG_VERBOSE
469 printk("umsdos_lookup_x: looking for %s/%s\n",
470 dentry->d_parent->d_name.name, dentry->d_name.name);
471 #endif
473 umsdos_startlookup (dir);
474 if (umsdos_is_pseudodos (dir, dentry)) {
475 /* #Specification: pseudo root / lookup(DOS)
476 * A lookup of DOS in the pseudo root will always succeed
477 * and return the inode of the real root.
479 Printk ((KERN_DEBUG "umsdos_lookup_x: following /DOS\n"));
480 inode = saved_root->d_inode;
481 goto out_add;
484 ret = umsdos_parse (dentry->d_name.name, dentry->d_name.len, &info);
485 if (ret) {
486 printk("umsdos_lookup_x: %s/%s parse failed, ret=%d\n",
487 dentry->d_parent->d_name.name, dentry->d_name.name, ret);
488 goto out;
491 ret = umsdos_findentry (dentry->d_parent, &info, 0);
492 if (ret) {
493 if (ret != -ENOENT)
494 printk("umsdos_lookup_x: %s/%s findentry failed, ret=%d\n",
495 dentry->d_parent->d_name.name, dentry->d_name.name, ret);
496 goto out;
498 Printk (("lookup %.*s pos %lu ret %d len %d ",
499 info.fake.len, info.fake.fname, info.f_pos, ret, info.fake.len));
501 /* do a real lookup to get the short name ... */
502 dret = umsdos_covered(dentry->d_parent, info.fake.fname, info.fake.len);
503 ret = PTR_ERR(dret);
504 if (IS_ERR(dret)) {
505 printk("umsdos_lookup_x: %s/%s real lookup failed, ret=%d\n",
506 dentry->d_parent->d_name.name, dentry->d_name.name, ret);
507 goto out;
509 inode = dret->d_inode;
510 if (!inode)
511 goto out_remove;
512 umsdos_lookup_patch_new(dret, &info);
513 #ifdef UMSDOS_DEBUG_VERBOSE
514 printk("umsdos_lookup_x: found %s/%s, ino=%ld\n",
515 dret->d_parent->d_name.name, dret->d_name.name, dret->d_inode->i_ino);
516 #endif
518 /* Check for a hard link */
519 if ((info.entry.flags & UMSDOS_HLINK) &&
520 !inode->u.umsdos_i.i_is_hlink) {
521 dret = umsdos_solve_hlink (dret);
522 ret = PTR_ERR(dret);
523 if (IS_ERR(dret))
524 goto out;
525 ret = -ENOENT;
526 inode = dret->d_inode;
527 if (!inode) {
528 printk("umsdos_lookup_x: %s/%s negative after link\n",
529 dret->d_parent->d_name.name, dret->d_name.name);
530 goto out_dput;
534 if (inode == pseudo_root && !nopseudo) {
535 /* #Specification: pseudo root / dir lookup
536 * For the same reason as readdir, a lookup in /DOS for
537 * the pseudo root directory (linux) will fail.
540 * This has to be allowed for resolving hard links
541 * which are recorded independently of the pseudo-root
542 * mode.
544 printk("umsdos_lookup_x: skipping DOS/linux\n");
545 ret = -ENOENT;
546 goto out_dput;
550 * We've found it OK. Now hash the dentry with the inode.
552 out_add:
553 inode->i_count++;
554 d_add (dentry, inode);
555 dentry->d_op = &umsdos_dentry_operations;
556 ret = 0;
558 out_dput:
559 if (dret && dret != dentry)
560 d_drop(dret);
561 dput(dret);
562 out:
563 umsdos_endlookup (dir);
564 return ERR_PTR(ret);
566 out_remove:
567 printk(KERN_WARNING "UMSDOS: entry %s/%s out of sync, erased\n",
568 dentry->d_parent->d_name.name, dentry->d_name.name);
569 umsdos_delentry (dentry->d_parent, &info, S_ISDIR (info.entry.mode));
570 ret = -ENOENT;
571 goto out_dput;
576 * Check whether a file exists in the current directory.
577 * Return 0 if OK, negative error code if not (ex: -ENOENT).
579 * Called by VFS; should fill dentry->d_inode via d_add.
582 struct dentry *UMSDOS_lookup (struct inode *dir, struct dentry *dentry)
584 struct dentry *ret;
586 ret = umsdos_lookup_x (dir, dentry, 0);
588 /* Create negative dentry if not found. */
589 if (ret == ERR_PTR(-ENOENT)) {
590 Printk ((KERN_DEBUG
591 "UMSDOS_lookup: converting -ENOENT to negative\n"));
592 d_add (dentry, NULL);
593 dentry->d_op = &umsdos_dentry_operations;
594 ret = NULL;
596 return ret;
599 struct dentry *umsdos_covered(struct dentry *parent, char *name, int len)
601 struct dentry *result, *dentry;
602 struct qstr qstr;
604 qstr.name = name;
605 qstr.len = len;
606 qstr.hash = full_name_hash(name, len);
607 result = ERR_PTR(-ENOMEM);
608 dentry = d_alloc(parent, &qstr);
609 if (dentry) {
610 /* XXXXXXXXXXXXXXXXXXX Race alert! */
611 result = UMSDOS_rlookup(parent->d_inode, dentry);
612 d_drop(dentry);
613 if (result)
614 goto out_fail;
615 return dentry;
617 out:
618 return result;
620 out_fail:
621 dput(dentry);
622 goto out;
626 * Lookup or create a dentry from within the filesystem.
628 * We need to use this instead of lookup_dentry, as the
629 * directory semaphore lock is already held.
631 struct dentry *umsdos_lookup_dentry(struct dentry *parent, char *name, int len,
632 int real)
634 struct dentry *result, *dentry;
635 struct qstr qstr;
637 qstr.name = name;
638 qstr.len = len;
639 qstr.hash = full_name_hash(name, len);
640 result = d_lookup(parent, &qstr);
641 if (!result) {
642 result = ERR_PTR(-ENOMEM);
643 dentry = d_alloc(parent, &qstr);
644 if (dentry) {
645 result = real ?
646 UMSDOS_rlookup(parent->d_inode, dentry) :
647 UMSDOS_lookup(parent->d_inode, dentry);
648 if (result)
649 goto out_fail;
650 return dentry;
653 out:
654 return result;
656 out_fail:
657 dput(dentry);
658 goto out;
662 * Return a path relative to our root.
664 char * umsdos_d_path(struct dentry *dentry, char * buffer, int len)
666 struct dentry * old_root = current->fs->root;
667 char * path;
669 /* N.B. not safe -- fix this soon! */
670 current->fs->root = dentry->d_sb->s_root;
671 path = d_path(dentry, buffer, len);
673 if (*path == '/')
674 path++; /* skip leading '/' */
676 if (old_root->d_inode == pseudo_root)
678 *(path-1) = '/';
679 path -= (UMSDOS_PSDROOT_LEN+1);
680 memcpy(path, UMSDOS_PSDROOT_NAME, UMSDOS_PSDROOT_LEN);
683 current->fs->root = old_root;
684 return path;
688 * Return the dentry which points to a pseudo-hardlink.
690 * it should try to find file it points to
691 * if file is found, return new dentry/inode
692 * The resolved inode will have i_is_hlink set.
694 * Note: the original dentry is always dput(), even if an error occurs.
697 struct dentry *umsdos_solve_hlink (struct dentry *hlink)
699 /* root is our root for resolving pseudo-hardlink */
700 struct dentry *base = hlink->d_sb->s_root;
701 struct dentry *dentry_dst;
702 char *path, *pt;
703 int len;
704 struct file filp;
706 #ifdef UMSDOS_DEBUG_VERBOSE
707 printk("umsdos_solve_hlink: following %s/%s\n",
708 hlink->d_parent->d_name.name, hlink->d_name.name);
709 #endif
711 dentry_dst = ERR_PTR (-ENOMEM);
712 path = (char *) kmalloc (PATH_MAX, GFP_KERNEL);
713 if (path == NULL)
714 goto out;
716 fill_new_filp (&filp, hlink);
717 filp.f_flags = O_RDONLY;
719 len = umsdos_file_read_kmem (&filp, path, hlink->d_inode->i_size);
720 if (len != hlink->d_inode->i_size)
721 goto out_noread;
722 #ifdef UMSDOS_DEBUG_VERBOSE
723 printk ("umsdos_solve_hlink: %s/%s is path %s\n",
724 hlink->d_parent->d_name.name, hlink->d_name.name, path);
725 #endif
727 /* start at root dentry */
728 dentry_dst = dget(base);
729 path[len] = '\0';
731 pt = path;
732 if (*path == '/')
733 pt++; /* skip leading '/' */
735 if (base->d_inode == pseudo_root)
736 pt += (UMSDOS_PSDROOT_LEN + 1);
738 while (1) {
739 struct dentry *dir = dentry_dst, *demd;
740 char *start = pt;
741 int real;
743 while (*pt != '\0' && *pt != '/') pt++;
744 len = (int) (pt - start);
745 if (*pt == '/') *pt++ = '\0';
747 real = 1;
748 demd = umsdos_get_emd_dentry(dir);
749 if (!IS_ERR(demd)) {
750 if (demd->d_inode)
751 real = 0;
752 dput(demd);
755 #ifdef UMSDOS_DEBUG_VERBOSE
756 printk ("umsdos_solve_hlink: dir %s/%s, name=%s, real=%d\n",
757 dir->d_parent->d_name.name, dir->d_name.name, start, real);
758 #endif
759 dentry_dst = umsdos_lookup_dentry(dir, start, len, real);
760 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
761 if (real)
762 d_drop(dir);
763 dput (dir);
764 if (IS_ERR(dentry_dst))
765 break;
766 /* not found? stop search ... */
767 if (!dentry_dst->d_inode) {
768 break;
770 if (*pt == '\0') /* we're finished! */
771 break;
772 } /* end while */
774 if (!IS_ERR(dentry_dst)) {
775 struct inode *inode = dentry_dst->d_inode;
776 if (inode) {
777 inode->u.umsdos_i.i_is_hlink = 1;
778 #ifdef UMSDOS_DEBUG_VERBOSE
779 printk ("umsdos_solve_hlink: resolved link %s/%s, ino=%ld\n",
780 dentry_dst->d_parent->d_name.name, dentry_dst->d_name.name, inode->i_ino);
781 #endif
782 } else {
783 #ifdef UMSDOS_DEBUG_VERBOSE
784 printk ("umsdos_solve_hlink: resolved link %s/%s negative!\n",
785 dentry_dst->d_parent->d_name.name, dentry_dst->d_name.name);
786 #endif
788 } else
789 printk(KERN_WARNING
790 "umsdos_solve_hlink: err=%ld\n", PTR_ERR(dentry_dst));
792 out_free:
793 kfree (path);
795 out:
796 dput(hlink); /* original hlink no longer needed */
797 return dentry_dst;
799 out_noread:
800 printk(KERN_WARNING "umsdos_solve_hlink: failed reading pseudolink!\n");
801 goto out_free;
805 static struct file_operations umsdos_dir_operations =
807 NULL, /* lseek - default */
808 dummy_dir_read, /* read */
809 NULL, /* write - bad */
810 UMSDOS_readdir, /* readdir */
811 NULL, /* poll - default */
812 UMSDOS_ioctl_dir, /* ioctl - default */
813 NULL, /* mmap */
814 NULL, /* no special open code */
815 NULL, /* flush */
816 NULL, /* no special release code */
817 NULL /* fsync */
820 struct inode_operations umsdos_dir_inode_operations =
822 &umsdos_dir_operations, /* default directory file-ops */
823 UMSDOS_create, /* create */
824 UMSDOS_lookup, /* lookup */
825 UMSDOS_link, /* link */
826 UMSDOS_unlink, /* unlink */
827 UMSDOS_symlink, /* symlink */
828 UMSDOS_mkdir, /* mkdir */
829 UMSDOS_rmdir, /* rmdir */
830 UMSDOS_mknod, /* mknod */
831 UMSDOS_rename, /* rename */
832 NULL, /* readlink */
833 NULL, /* followlink */
834 NULL, /* get_block */
835 NULL, /* readpage */
836 NULL, /* writepage */
837 NULL, /* flushpage */
838 NULL, /* truncate */
839 NULL, /* permission */
840 NULL, /* smap */
841 NULL, /* revalidate */