/* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 2011-2019 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "mudbm.h" static mu_list_t implist; mu_url_t mu_dbm_hint; static void _implist_free (void *p) { struct mu_dbm_impl *impl = p; free (impl->_dbm_name); free (impl); } static int _implist_cmp (const void *a, const void *b) { struct mu_dbm_impl const *ia = a; struct mu_dbm_impl const *ib = b; return strcmp (ia->_dbm_name, ib->_dbm_name); } void mu_dbm_init () { int rc; if (implist) return; rc = mu_list_create (&implist); if (rc) { mu_error (_("cannot initialize DBM subsystem: %s"), mu_strerror (rc)); abort (); } mu_list_set_destroy_item (implist, _implist_free); mu_list_set_comparator (implist, _implist_cmp); /* Add built-in entries */ #ifdef WITH_GDBM mu_dbm_register (&_mu_dbm_gdbm); #endif #ifdef WITH_BDB mu_dbm_register (&_mu_dbm_bdb); #endif #ifdef WITH_NDBM mu_dbm_register (&_mu_dbm_ndbm); #endif #ifdef WITH_TOKYOCABINET mu_dbm_register (&_mu_dbm_tokyocabinet); #endif #ifdef WITH_KYOTOCABINET mu_dbm_register (&_mu_dbm_kyotocabinet); #endif if (!mu_dbm_hint) { struct mu_dbm_impl *impl; if ((rc = mu_list_get (implist, 0, (void**) &impl)) || (rc = mu_url_create_null (&mu_dbm_hint)) || (rc = mu_url_set_scheme (mu_dbm_hint, impl->_dbm_name))) { mu_error (_("cannot initialize DBM hint: %s"), mu_strerror (rc)); abort (); } } } mu_url_t mu_dbm_get_hint () { mu_dbm_init (); return mu_dbm_hint; } int mu_dbm_register (struct mu_dbm_impl *impl) { int rc; struct mu_dbm_impl *ptr; mu_dbm_init (); ptr = calloc (1, sizeof (*ptr)); if (!ptr) return ENOMEM; *ptr = *impl; ptr->_dbm_name = strdup (impl->_dbm_name); if (!ptr->_dbm_name) { free (ptr); return ENOMEM; } rc = mu_list_append (implist, ptr); if (rc) _implist_free (ptr); return rc; } int mu_dbm_create_from_url (mu_url_t url, mu_dbm_file_t *db, int defsafety) { mu_dbm_file_t p; int flags; int rc; const char *db_name; struct mu_dbm_impl impl_key; struct mu_dbm_impl *impl; struct mu_auth_data *auth; int safety_flags = 0; int safety_flags_set = 0; uid_t owner_uid = getuid (); mu_dbm_init (); mu_url_get_flags (url, &flags); if ((flags & (MU_URL_HOST | MU_URL_PATH)) == (MU_URL_HOST | MU_URL_PATH)) return MU_ERR_URL_EXTRA_PARTS; if (flags & MU_URL_HOST) rc = mu_url_sget_host (url, &db_name); else rc = mu_url_sget_path (url, &db_name); if (rc) return rc; rc = mu_url_sget_scheme (url, (const char**)&impl_key._dbm_name); if (rc) return rc; rc = mu_list_locate (implist, (void *) &impl_key, (void **) &impl); if (rc) return rc; if (flags & MU_URL_PARAM) { size_t fvc, i; char **fvp; mu_url_sget_fvpairs (url, &fvc, &fvp); for (i = 0; i < fvc; i++) { const char *name = fvp[i]; int negate = 0; int val; if (*name == '-') { if (!safety_flags_set) /* Imply default safety settings */ safety_flags = defsafety; negate = 1; name++; } else if (*name == '+') name++; safety_flags_set = 1; if (strncmp (name, "owner", 5) == 0) { val = MU_FILE_SAFETY_OWNER_MISMATCH; if (name[5] == '=') { auth = mu_get_auth_by_name (name + 6); if (auth) { owner_uid = auth->uid; mu_auth_data_free (auth); } else { char *end; unsigned long uid; errno = 0; uid = strtoul (name + 6, &end, 0); if (*end || errno) return MU_ERR_NO_SUCH_USER; owner_uid = uid; } } else if (name[5]) return MU_ERR_URL_INVALID_PARAMETER; } else if (strcmp (name, "none") == 0) { safety_flags = negate ? MU_FILE_SAFETY_ALL : MU_FILE_SAFETY_NONE; continue; } else if (strcmp (name, "all") == 0) { safety_flags = negate ? MU_FILE_SAFETY_NONE : MU_FILE_SAFETY_ALL; continue; } else if (strcmp (name, "default") == 0) { val = defsafety; } else if (mu_file_safety_name_to_code (name, &val)) return MU_ERR_URL_INVALID_PARAMETER; if (negate) safety_flags &= ~val; else safety_flags |= val; } } p = calloc (1, sizeof (*p)); if (!p) return ENOMEM; p->db_name = strdup (db_name); if (!p->db_name) { free (p); return ENOMEM; } p->db_safety_flags = safety_flags_set ? safety_flags : defsafety; p->db_owner = owner_uid; p->db_sys = impl; *db = p; return 0; } int mu_dbm_impl_iterator (mu_iterator_t *itr) { mu_dbm_init (); return mu_list_get_iterator (implist, itr); }