diff options
Diffstat (limited to 'g13/mountinfo.c')
-rw-r--r-- | g13/mountinfo.c | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/g13/mountinfo.c b/g13/mountinfo.c new file mode 100644 index 0000000..ed898b8 --- /dev/null +++ b/g13/mountinfo.c @@ -0,0 +1,198 @@ +/* mountinfo.c - Track infos about mounts + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * This file is part of GnuPG. + * + * GnuPG 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 3 of the License, or + * (at your option) any later version. + * + * GnuPG 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 this program; if not, see <https://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/stat.h> +#include <assert.h> + +#include "g13.h" +#include "../common/i18n.h" +#include "mountinfo.h" + +#include "keyblob.h" +#include "g13tuple.h" + + + +/* The object to keep track of mount information. */ +struct mounttable_s +{ + int in_use; /* The slot is in use. */ + char *container; /* Name of the container. */ + char *mountpoint; /* Name of the mounttype. */ + int conttype; /* Type of the container. */ + unsigned int rid; /* Identifier of the runner task. */ + struct { + unsigned int remove:1; /* True if the mountpoint shall be removed + on umount. */ + } flags; +}; + + +/* The allocated table of mounts and its size. */ +static mtab_t mounttable; +size_t mounttable_size; + + + +/* Add CONTAINER,MOUNTPOINT,CONTTYPE,RID to the mounttable. */ +gpg_error_t +mountinfo_add_mount (const char *container, const char *mountpoint, + int conttype, unsigned int rid, int remove_flag) +{ + size_t idx; + mtab_t m; + + for (idx=0; idx < mounttable_size; idx++) + if (!mounttable[idx].in_use) + break; + if (!(idx < mounttable_size)) + { + size_t nslots = mounttable_size; + + mounttable_size += 10; + m = xtrycalloc (mounttable_size, sizeof *mounttable); + if (!m) + return gpg_error_from_syserror (); + if (mounttable) + { + for (idx=0; idx < nslots; idx++) + m[idx] = mounttable[idx]; + xfree (mounttable); + } + mounttable = m; + m = mounttable + nslots; + assert (!m->in_use); + } + else + m = mounttable + idx; + + m->container = xtrystrdup (container); + if (!m->container) + return gpg_error_from_syserror (); + m->mountpoint = xtrystrdup (mountpoint); + if (!m->mountpoint) + { + xfree (m->container); + m->container = NULL; + return gpg_error_from_syserror (); + } + m->conttype = conttype; + m->rid = rid; + m->flags.remove = !!remove_flag; + m->in_use = 1; + + return 0; +} + + +/* Remove a mount info. Either the CONTAINER, the MOUNTPOINT or the + RID must be given. The first argument given is used. */ +gpg_error_t +mountinfo_del_mount (const char *container, const char *mountpoint, + unsigned int rid) +{ + gpg_error_t err; + size_t idx; + mtab_t m; + + /* If a container or mountpint is givem search the RID via the + standard find function. */ + if (container || mountpoint) + { + err = mountinfo_find_mount (container, mountpoint, &rid); + if (err) + return err; + } + + /* Find via RID and delete. */ + for (idx=0, m = mounttable; idx < mounttable_size; idx++, m++) + if (m->in_use && m->rid == rid) + { + if (m->flags.remove && m->mountpoint) + { + /* FIXME: This does not always work because the umount may + not have completed yet. We should add the mountpoints + to an idle queue and retry a remove. */ + if (rmdir (m->mountpoint)) + log_error ("error removing mount point '%s': %s\n", + m->mountpoint, + gpg_strerror (gpg_error_from_syserror ())); + } + m->in_use = 0; + xfree (m->container); + m->container = NULL; + xfree (m->mountpoint); + m->mountpoint = NULL; + return 0; + } + return gpg_error (GPG_ERR_NOT_FOUND); +} + + +/* Find a mount and return its rid at R_RID. If CONTAINER is given, + the search is done by the container name, if it is not given the + search is done by MOUNTPOINT. */ +gpg_error_t +mountinfo_find_mount (const char *container, const char *mountpoint, + unsigned int *r_rid) +{ + size_t idx; + mtab_t m; + + if (container) + { + for (idx=0, m = mounttable; idx < mounttable_size; idx++, m++) + if (m->in_use && !strcmp (m->container, container)) + break; + } + else if (mountpoint) + { + for (idx=0, m = mounttable; idx < mounttable_size; idx++, m++) + if (m->in_use && !strcmp (m->mountpoint, mountpoint)) + break; + } + else + idx = mounttable_size; + if (!(idx < mounttable_size)) + return gpg_error (GPG_ERR_NOT_FOUND); + + *r_rid = m->rid; + return 0; +} + + +/* Dump all info to the log stream. */ +void +mountinfo_dump_all (void) +{ + size_t idx; + mtab_t m; + + for (idx=0, m = mounttable; idx < mounttable_size; idx++, m++) + if (m->in_use) + log_info ("mtab[%d] %s on %s type %d rid %u%s\n", + (int)idx, m->container, m->mountpoint, m->conttype, m->rid, + m->flags.remove?" [remove]":""); +} |