Justus Winter, le Sun 05 Oct 2014 13:26:42 +0200, a écrit : > * trans/mtab.c (struct mtab): Add a hash table to keep track of seen > ports. > (mtab_mark_as_seen): New function that records the identity port of a > given node in the hash table and reports whether it has been there > before. > (mtab_populate): Use the new function to avoid running in circles. > (main, open_hook): Initialize hash table. > (close_hook): Free ports and destroy hash table.
Yes, it does avoid loops, please commit, thanks! > --- > trans/mtab.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 45 insertions(+), 1 deletion(-) > > diff --git a/trans/mtab.c b/trans/mtab.c > index 5207c1e..a9928b3 100644 > --- a/trans/mtab.c > +++ b/trans/mtab.c > @@ -24,6 +24,7 @@ > #include <error.h> > #include <fcntl.h> > #include <hurd.h> > +#include <hurd/ihash.h> > #include <hurd/trivfs.h> > #include <inttypes.h> > #include <mntent.h> > @@ -55,6 +56,7 @@ struct mtab > char *contents; > size_t contents_len; > off_t offs; > + struct hurd_ihash ports_seen; > }; > > const char *argp_program_version = STANDARD_HURD_VERSION (mtab); > @@ -244,7 +246,11 @@ main (int argc, char *argv[]) > else > { > /* One-shot mode. */ > - struct mtab mtab = { .lock = PTHREAD_MUTEX_INITIALIZER }; > + struct mtab mtab = > + { > + .lock = PTHREAD_MUTEX_INITIALIZER, > + .ports_seen = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP), > + }; > err = mtab_populate (&mtab, target_path, insecure); > if (err) > error (5, err, "%s", target_path); > @@ -301,6 +307,33 @@ is_filesystem_translator (file_t node) > } > } > > +/* Records NODE's idport in ports_seen, returns true if we have > + already seen this node or there was an error getting the id > + port. */ > +boolean_t > +mtab_mark_as_seen (struct mtab *mtab, mach_port_t node) > +{ > + error_t err; > + mach_port_t idport, fsidport; > + ino_t fileno; > + > + err = io_identity (node, &idport, &fsidport, &fileno); > + if (err) > + return TRUE; > + > + mach_port_deallocate (mach_task_self (), fsidport); > + > + if (hurd_ihash_find (&mtab->ports_seen, idport)) > + { > + /* Already seen. Get rid of the extra reference. */ > + mach_port_deallocate (mach_task_self (), idport); > + return TRUE; > + } > + > + hurd_ihash_add (&mtab->ports_seen, idport, idport); > + return FALSE; > +} > + > /* Populates the given MTAB object with the information for PATH. If > INSECURE is given, also follow translators bound to nodes not owned > by root or the current user. */ > @@ -363,6 +396,13 @@ mtab_populate (struct mtab *mtab, const char *path, int > insecure) > goto errout; > } > > + /* Avoid running in circles. */ > + if (mtab_mark_as_seen (mtab, node)) > + { > + err = 0; > + goto errout; > + } > + > /* Query its options. */ > err = file_get_fs_options (node, &argz, &argz_len); > if (err) > @@ -602,6 +642,7 @@ open_hook (struct trivfs_peropen *peropen) > mtab->offs = 0; > mtab->contents = NULL; > mtab->contents_len = 0; > + hurd_ihash_init (&mtab->ports_seen, HURD_IHASH_NO_LOCP); > > /* The mtab object is initialized, but not yet populated. We delay > that until that data is really needed. This avoids the following > @@ -635,6 +676,9 @@ close_hook (struct trivfs_peropen *peropen) > struct mtab *op = peropen->hook; > pthread_mutex_destroy (&op->lock); > free (op->contents); > + HURD_IHASH_ITERATE (&op->ports_seen, p) > + mach_port_deallocate (mach_task_self (), (mach_port_t) p); > + hurd_ihash_destroy (&op->ports_seen); > free (op); > } > > -- > 2.1.1 > -- Samuel * D a decide de peter un cable dans son rapport de pfp <c> et il a bien raison ;-) <c> tu vas dire quoi ? <D> j'ai mis les paroles de "le coq est mort" en en-tete -+- #ens-mim et la peufeupeu -+-