mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
4d7dc432b5
--
199 lines
5.3 KiB
C
199 lines
5.3 KiB
C
/* 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 "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]":"");
|
||
}
|