/* A list of active translators. Copyright (C) 2013,14 Free Software Foundation, Inc. Written by Justus Winter <4winter@informatik.uni-hamburg.de> This file is part of the GNU Hurd. The GNU Hurd 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, or (at your option) any later version. The GNU Hurd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with the GNU Hurd. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "fshelp.h" struct translator { struct port_info *pi; char *name; mach_port_t active; }; /* The list of active translators. */ static struct hurd_ihash translator_ihash = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP); /* The lock protecting the translator_ihash. */ static pthread_mutex_t translator_ihash_lock = PTHREAD_MUTEX_INITIALIZER; static void translator_ihash_cleanup (void *element, void *arg) { struct translator *translator = element; if (translator->pi) ports_port_deref (translator->pi); /* No need to deallocate translator->active, we only keep the name of the port, not a reference. */ free (translator->name); free (translator); } /* Record an active translator being bound to the given file name NAME. ACTIVE is the control port of the translator. */ error_t fshelp_set_active_translator (struct port_info *pi, const char *name, mach_port_t active) { error_t err = 0; pthread_mutex_lock (&translator_ihash_lock); if (! translator_ihash.cleanup) hurd_ihash_set_cleanup (&translator_ihash, translator_ihash_cleanup, NULL); struct translator *t = NULL; HURD_IHASH_ITERATE (&translator_ihash, value) { t = value; if (strcmp (name, t->name) == 0) goto update; /* Entry exists. */ } t = malloc (sizeof (struct translator)); if (! t) return ENOMEM; t->active = MACH_PORT_NULL; t->pi = NULL; t->name = strdup (name); if (! t->name) { err = errno; free (t); goto out; } err = hurd_ihash_add (&translator_ihash, (hurd_ihash_key_t) t, t); if (err) goto out; update: if (active) { if (t->pi != pi) { mach_port_t old; err = mach_port_request_notification (mach_task_self (), active, MACH_NOTIFY_DEAD_NAME, 0, pi->port_right, MACH_MSG_TYPE_MAKE_SEND_ONCE, &old); if (err) return err; if (old != MACH_PORT_NULL) mach_port_deallocate (mach_task_self (), old); if (t->pi) ports_port_deref (t->pi); ports_port_ref (pi); t->pi = pi; } /* No need to increment the reference count, we only keep the name, not a reference. */ t->active = active; } else hurd_ihash_remove (&translator_ihash, (hurd_ihash_key_t) t); out: pthread_mutex_unlock (&translator_ihash_lock); return err; } /* Remove the active translator specified by its control port ACTIVE. If there is no active translator with the given control port, this does nothing. */ error_t fshelp_remove_active_translator (mach_port_t active) { error_t err = 0; pthread_mutex_lock (&translator_ihash_lock); struct translator *t = NULL; HURD_IHASH_ITERATE (&translator_ihash, value) { struct translator *v = value; if (active == v->active) { t = v; break; } } if (t) hurd_ihash_remove (&translator_ihash, (hurd_ihash_key_t) t); pthread_mutex_unlock (&translator_ihash_lock); return err; } /* Records the list of active translators into the argz vector specified by TRANSLATORS filtered by FILTER. */ error_t fshelp_get_active_translators (char **translators, size_t *translators_len, fshelp_filter filter) { error_t err = 0; pthread_mutex_lock (&translator_ihash_lock); HURD_IHASH_ITERATE (&translator_ihash, value) { struct translator *t = value; if (filter) { char *dir = strdup (t->name); if (! dir) { err = ENOMEM; break; } err = filter (dirname (dir)); free (dir); if (err) { err = 0; continue; /* Skip this entry. */ } } err = argz_add (translators, translators_len, t->name); if (err) break; } pthread_mutex_unlock (&translator_ihash_lock); return err; }