[scd] Memory leak fix.
[gnupg.git] / g13 / mountinfo.c
blob07c6240d43e73e70e8e82818999ade0d7104adc4
1 /* mountinfo.c - Track infos about mounts
2 * Copyright (C) 2009 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <sys/stat.h>
27 #include <assert.h>
29 #include "g13.h"
30 #include "i18n.h"
31 #include "mountinfo.h"
33 #include "keyblob.h"
34 #include "utils.h"
38 /* The object to keep track of mount information. */
39 struct mounttable_s
41 int in_use; /* The slot is in use. */
42 char *container; /* Name of the container. */
43 char *mountpoint; /* Name of the mounttype. */
44 int conttype; /* Type of the container. */
45 unsigned int rid; /* Identifier of the runner task. */
46 struct {
47 unsigned int remove:1; /* True if the mountpoint shall be removed
48 on umount. */
49 } flags;
53 /* The allocated table of mounts and its size. */
54 static mtab_t mounttable;
55 size_t mounttable_size;
59 /* Add CONTAINER,MOUNTPOINT,CONTTYPE,RID to the mounttable. */
60 gpg_error_t
61 mountinfo_add_mount (const char *container, const char *mountpoint,
62 int conttype, unsigned int rid, int remove_flag)
64 size_t idx;
65 mtab_t m;
67 for (idx=0; idx < mounttable_size; idx++)
68 if (!mounttable[idx].in_use)
69 break;
70 if (!(idx < mounttable_size))
72 size_t nslots = mounttable_size;
74 mounttable_size += 10;
75 m = xtrycalloc (mounttable_size, sizeof *mounttable);
76 if (!m)
77 return gpg_error_from_syserror ();
78 if (mounttable)
80 for (idx=0; idx < nslots; idx++)
81 m[idx] = mounttable[idx];
82 xfree (mounttable);
84 mounttable = m;
85 m = mounttable + nslots;
86 assert (!m->in_use);
88 else
89 m = mounttable + idx;
91 m->container = xtrystrdup (container);
92 if (!m->container)
93 return gpg_error_from_syserror ();
94 m->mountpoint = xtrystrdup (mountpoint);
95 if (!m->mountpoint)
97 xfree (m->container);
98 m->container = NULL;
99 return gpg_error_from_syserror ();
101 m->conttype = conttype;
102 m->rid = rid;
103 m->flags.remove = !!remove_flag;
104 m->in_use = 1;
106 return 0;
110 /* Remove a mount info. Either the CONTAINER, the MOUNTPOINT or the
111 RID must be given. The first argument given is used. */
112 gpg_error_t
113 mountinfo_del_mount (const char *container, const char *mountpoint,
114 unsigned int rid)
116 gpg_error_t err;
117 size_t idx;
118 mtab_t m;
120 /* If a container or mountpint is givem search the RID via the
121 standard find fucntion. */
122 if (container || mountpoint)
124 err = mountinfo_find_mount (container, mountpoint, &rid);
125 if (err)
126 return err;
129 /* Find via RID and delete. */
130 for (idx=0, m = mounttable; idx < mounttable_size; idx++, m++)
131 if (m->in_use && m->rid == rid)
133 if (m->flags.remove && m->mountpoint)
135 /* FIXME: This does not always work because the umount may
136 not have completed yet. We should add the mountpoints
137 to an idle queue and retry a remove. */
138 if (rmdir (m->mountpoint))
139 log_error ("error removing mount point `%s': %s\n",
140 m->mountpoint,
141 gpg_strerror (gpg_error_from_syserror ()));
143 m->in_use = 0;
144 xfree (m->container);
145 m->container = NULL;
146 xfree (m->mountpoint);
147 m->mountpoint = NULL;
148 return 0;
150 return gpg_error (GPG_ERR_NOT_FOUND);
154 /* Find a mount and return its rid at R_RID. If CONTAINER is given,
155 the search is done by the container name, if it is not given the
156 search is done by MOUNTPOINT. */
157 gpg_error_t
158 mountinfo_find_mount (const char *container, const char *mountpoint,
159 unsigned int *r_rid)
161 size_t idx;
162 mtab_t m;
164 if (container)
166 for (idx=0, m = mounttable; idx < mounttable_size; idx++, m++)
167 if (m->in_use && !strcmp (m->container, container))
168 break;
170 else if (mountpoint)
172 for (idx=0, m = mounttable; idx < mounttable_size; idx++, m++)
173 if (m->in_use && !strcmp (m->mountpoint, mountpoint))
174 break;
176 else
177 idx = mounttable_size;
178 if (!(idx < mounttable_size))
179 return gpg_error (GPG_ERR_NOT_FOUND);
181 *r_rid = m->rid;
182 return 0;
186 /* Dump all info to the log stream. */
187 void
188 mountinfo_dump_all (void)
190 size_t idx;
191 mtab_t m;
193 for (idx=0, m = mounttable; idx < mounttable_size; idx++, m++)
194 if (m->in_use)
195 log_info ("mtab[%d] %s on %s type %d rid %u%s\n",
196 idx, m->container, m->mountpoint, m->conttype, m->rid,
197 m->flags.remove?" [remove]":"");