help-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: "find" doesn't work


From: Wolfgang Jährling
Subject: Re: "find" doesn't work
Date: Mon, 10 Jun 2002 15:51:49 +0200
User-agent: Mutt/1.0.1i

Hi!

Ludovic Courtès <ludovic.courtes@utbm.fr> wrote:
> If I remember well, "find -name \*" doesn't work with shadowfs which is a
> libnetfs-based translator. I encountered the same problem with another
> libnetfs translator, even though something like "ls -R" does work fine. I
> tried to look at the code of find but 1) I didn't manage to compile it and 2)
> the code seems quite hard to read. ;)

Moritz told me that find uses an optimization that causes it to ignore
some directories in Shadowfs: The "struct stat" for a directory contains
the number of links to the directory, which also tells us the number of
subdirectories, as we have a ".." link from each subdir plus two other
links ("." and the link to it in its parent directory).  Thus, if find
has processed st_nlink-2 subdirs, it assumes there are no more.  And
Shadowfs simply returned the struct stat for one of its underlying
directories.  You can work around this by using the "-noleaf" option of
find, but I also made a patch for the old Shadowfs (see below).  But the
new Shadowfs will be very different internally, and I'm waiting for
Moritz to release it so I can start doing some work on it (Hello Moritz!).

Cheers,
GNU/Wolfgang

Now here's my patch (note that Shadowfs probably should calculate more
of the fields for the stat structure and do caching of the information,
which the new version will do):

diff -rup shadowfs-0.1.9-/fs.h shadowfs-0.1.9/fs.h
--- shadowfs-0.1.9-/fs.h        Mon Oct 22 16:15:32 2001
+++ shadowfs-0.1.9/fs.h Thu May  2 22:57:38 2002
@@ -16,6 +16,9 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
    USA */
 
+#ifndef __SHADOWFS_FS_H__
+#define __SHADOWFS_FS_H__
+
 #include <hurd.h>
 
 struct dirent_chain
@@ -35,3 +38,5 @@ error_t find_writable_fs (struct node *d
 error_t create_dir_on_writable_fs (struct node *dir, char *name);
 error_t do_copy_on_write (struct node *dir, mach_port_t port, char *name,
                          int flags, mach_port_t *the_port);
+
+#endif
diff -rup shadowfs-0.1.9-/main.c shadowfs-0.1.9/main.c
--- shadowfs-0.1.9-/main.c      Mon Oct 22 16:15:32 2001
+++ shadowfs-0.1.9/main.c       Thu May  2 23:14:50 2002
@@ -34,7 +34,7 @@
 const char *argp_program_version = STANDARD_HURD_VERSION (shadowfs);
 const char *argp_program_bug_address = "Moritz Schulte <moritz@chaosdorf.de>";
 const char *args_doc = "FILESYSTEMS ...";
-const char *doc = "Hurd Shadowfs translator v" SHADOWFS_VERSION;
+const char *doc = "The Hurd Shadowfs translator v" SHADOWFS_VERSION;
 
 /* General state information for the shadowfs.  */
 int shadowfs_flags = 0;
diff -rup shadowfs-0.1.9-/netfs.c shadowfs-0.1.9/netfs.c
--- shadowfs-0.1.9-/netfs.c     Mon Oct 22 16:15:32 2001
+++ shadowfs-0.1.9/netfs.c      Sat May  4 01:50:51 2002
@@ -1,6 +1,7 @@
 /* Shadowfs - a shadowfs translator for GNU/Hurd
    Copyright (C) 2001 Moritz Schulte <moritz@chaosdorf.de>
- 
+   Copyright (C) 2002 Wolfgang Jaehrling <wolfgang@pro-linux.de>
+
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
@@ -18,9 +19,12 @@
 
 #define _GNU_SOURCE
 
+#include <hurd.h>
 #include <hurd/netfs.h>
 #include <hurd/paths.h>
+#include <hurd/io.h>
 #include <error.h>
+#include <errno.h>
 #include <argz.h>
 #include <stdio.h>
 #include <stddef.h>
@@ -286,10 +290,80 @@ netfs_validate_stat (struct node *np, st
   error_t err = 0;
 
   if (np != netfs_root_node)
-    /* The last port is the one we take the stat information from.  */
-    err = io_stat ((np->nn->ports + np->nn->nports - 1)->port,
-                  &np->nn_stat);
+    {
+      struct dirent_chain *dirent_chain;
+
+      /* The last port is the one we take the stat information from.  */
+      err = io_stat ((np->nn->ports + np->nn->nports - 1)->port,
+                    &np->nn_stat);
 
+      /* We need to fix the link count, as we might have more
+        subdirectories.  */
+      if (! err)
+       {
+         err = shadowfs_readdir (np, &dirent_chain);
+         if (! err)
+           {
+             int link_cnt = 0;
+             struct dirent_chain *dec;
+
+             /* Delete the entire chain.  */
+             void free_dirent_chain (void)
+               {
+                 struct dirent_chain *prev;
+
+                 for (; dirent_chain; (prev = dirent_chain,
+                                       dirent_chain = dirent_chain->next,
+                                       free (prev->dirent),
+                                       free (prev)))
+                   ;
+               }
+
+             /* Find file we wish to io_stat ().  */
+             file_t shadowfs_lookup (const char *name)
+               {
+                 int i;
+
+                 for (i = 0; i < np->nn->nports; i++)
+                   {
+                     file_t port
+                       = file_name_lookup_under (np->nn->ports[i].port,
+                                                 name, O_NORW, 0);
+
+                     if (port)
+                       return port;
+                     if (errno != ENOENT)
+                       {
+                         err = errno;
+                         return MACH_PORT_NULL;
+                       }
+                   }
+                 err = EIEIO;
+                 return MACH_PORT_NULL;
+               }
+
+             /* Count directories.  */
+             for (dec = dirent_chain; dec; dec = dec->next)
+               {
+                 struct stat stat;
+                 file_t port = shadowfs_lookup (dec->dirent->d_name);
+
+                 if (! port)
+                   break;
+                 err = io_stat (port, &stat);
+                 if (err)
+                   break;
+                 mach_port_deallocate (mach_task_self (), port);
+
+                 if (stat.st_mode & S_IFDIR)
+                   link_cnt++;
+               }
+             free_dirent_chain ();
+             if (! err)
+               np->nn_stat.st_nlink = link_cnt;
+           }
+       }
+    }
   return err;
 }
 
@@ -695,6 +769,7 @@ netfs_node_norefs (struct node *np)
    The number of entries in the array is stored in *AMT and the number
    of bytes in *DATACNT.  If the supplied buffer is not large enough
    to hold the data, it should be grown.  */
+/* FIXME: The above argument names are wrong.  --wj */
 error_t
 netfs_get_dirents (struct iouser *cred, struct node *dir,
                   int first_entry, int num_entries, char **data,
@@ -713,6 +788,7 @@ netfs_get_dirents (struct iouser *cred, 
       if (num_entries == -1 || count < num_entries)
        {
          size_t new_size = size + len;
+
          if (max_data_len > 0 && new_size > max_data_len)
            return 0;
          size = new_size;
diff -rup shadowfs-0.1.9-/node.h shadowfs-0.1.9/node.h
--- shadowfs-0.1.9-/node.h      Mon Oct 22 16:15:32 2001
+++ shadowfs-0.1.9/node.h       Sat May  4 02:02:55 2002
@@ -16,8 +16,13 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
    USA */
 
+#ifndef __SHADOWFS_NODE_H__
+#define __SHADOWFS_NODE_H__
+
 error_t shadowfs_make_node (struct node *dir, char *name,
                            struct node **the_node);
 error_t make_root_node (struct node **root_node);
 error_t shadowfs_free_node (struct node *node);
 error_t add_port_to_node (struct node *node, mach_port_t port, int flags);
+
+#endif
Only in shadowfs-0.1.9: node.h~
diff -rup shadowfs-0.1.9-/shadowfs.h shadowfs-0.1.9/shadowfs.h
--- shadowfs-0.1.9-/shadowfs.h  Mon Oct 22 16:15:32 2001
+++ shadowfs-0.1.9/shadowfs.h   Sat May  4 02:03:16 2002
@@ -16,6 +16,9 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
    USA */
 
+#ifndef __SHADOWFS_SHADOWFS_H
+#define __SHADOWFS_SHADOWFS_H
+
 #include <dirent.h>
 #include "version.h"
 
@@ -64,3 +67,5 @@ struct netnode
   int nports;            /* The number of ports in PORTS. */
   struct node *dir;      /* The parent directory. */
 };
+
+#endif




reply via email to

[Prev in Thread] Current Thread [Next in Thread]