summaryrefslogtreecommitdiffstats
path: root/g13/mountinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'g13/mountinfo.c')
-rw-r--r--g13/mountinfo.c198
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]":"");
+}