Line data Source code
1 : /* vfs-mount.c - vfs mount support in GPGME
2 : Copyright (C) 2009 g10 Code GmbH
3 :
4 : This file is part of GPGME.
5 :
6 : GPGME is free software; you can redistribute it and/or modify it
7 : under the terms of the GNU Lesser General Public License as
8 : published by the Free Software Foundation; either version 2.1 of
9 : the License, or (at your option) any later version.
10 :
11 : GPGME is distributed in the hope that it will be useful, but
12 : WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : Lesser General Public License for more details.
15 :
16 : You should have received a copy of the GNU Lesser General Public
17 : License along with this program; if not, write to the Free Software
18 : Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 : 02111-1307, USA. */
20 :
21 : #if HAVE_CONFIG_H
22 : #include <config.h>
23 : #endif
24 :
25 : #include <stdlib.h>
26 :
27 : #include "gpgme.h"
28 : #include "debug.h"
29 : #include "context.h"
30 : #include "ops.h"
31 : #include "util.h"
32 :
33 : typedef struct
34 : {
35 : struct _gpgme_op_vfs_mount_result result;
36 : } *op_data_t;
37 :
38 :
39 :
40 : gpgme_vfs_mount_result_t
41 0 : gpgme_op_vfs_mount_result (gpgme_ctx_t ctx)
42 : {
43 : gpgme_error_t err;
44 : void *hook;
45 : op_data_t opd;
46 :
47 0 : err = _gpgme_op_data_lookup (ctx, OPDATA_VFS_MOUNT, &hook, -1, NULL);
48 0 : opd = hook;
49 : /* Check in case this function is used without having run a command
50 : before. */
51 0 : if (err || !opd)
52 0 : return NULL;
53 :
54 0 : return &opd->result;
55 : }
56 :
57 :
58 : static gpgme_error_t
59 0 : _gpgme_vfs_mount_status_handler (void *priv, const char *code, const char *args)
60 : {
61 0 : gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
62 : gpgme_error_t err;
63 : void *hook;
64 : op_data_t opd;
65 :
66 0 : err = _gpgme_op_data_lookup (ctx, OPDATA_VFS_MOUNT, &hook, -1, NULL);
67 0 : opd = hook;
68 0 : if (err)
69 0 : return err;
70 :
71 0 : if (! strcasecmp ("MOUNTPOINT", code))
72 : {
73 0 : if (opd->result.mount_dir)
74 0 : free (opd->result.mount_dir);
75 0 : opd->result.mount_dir = strdup (args);
76 : }
77 :
78 0 : return 0;
79 : }
80 :
81 :
82 : static gpgme_error_t
83 0 : vfs_start (gpgme_ctx_t ctx, int synchronous,
84 : const char *command,
85 : gpgme_assuan_data_cb_t data_cb,
86 : void *data_cb_value,
87 : gpgme_assuan_inquire_cb_t inq_cb,
88 : void *inq_cb_value,
89 : gpgme_assuan_status_cb_t status_cb,
90 : void *status_cb_value)
91 : {
92 : gpgme_error_t err;
93 : void *hook;
94 : op_data_t opd;
95 :
96 0 : if (!command || !*command)
97 0 : return gpg_error (GPG_ERR_INV_VALUE);
98 :
99 : /* The flag value 256 is used to suppress an engine reset. This is
100 : required to keep the connection running. */
101 0 : err = _gpgme_op_reset (ctx, ((synchronous & 255) | 256));
102 0 : if (err)
103 0 : return err;
104 :
105 0 : err = _gpgme_op_data_lookup (ctx, OPDATA_VFS_MOUNT, &hook, sizeof (*opd),
106 : NULL);
107 0 : opd = hook;
108 0 : if (err)
109 0 : return err;
110 :
111 0 : return _gpgme_engine_op_assuan_transact (ctx->engine, command,
112 : data_cb, data_cb_value,
113 : inq_cb, inq_cb_value,
114 : status_cb, status_cb_value);
115 : }
116 :
117 :
118 :
119 : #if 0
120 : /* XXXX. This is the asynchronous variant. */
121 : static gpgme_error_t
122 : gpgme_op_vfs_transact_start (gpgme_ctx_t ctx,
123 : const char *command,
124 : gpgme_assuan_data_cb_t data_cb,
125 : void *data_cb_value,
126 : gpgme_assuan_inquire_cb_t inq_cb,
127 : void *inq_cb_value,
128 : gpgme_assuan_status_cb_t status_cb,
129 : void *status_cb_value)
130 : {
131 : return vfs_start (ctx, 0, command, data_cb, data_cb_value,
132 : inq_cb, inq_cb_value, status_cb, status_cb_value);
133 : }
134 : #endif
135 :
136 :
137 : /* XXXX. This is the synchronous variant. */
138 : static gpgme_error_t
139 0 : gpgme_op_vfs_transact (gpgme_ctx_t ctx,
140 : const char *command,
141 : gpgme_assuan_data_cb_t data_cb,
142 : void *data_cb_value,
143 : gpgme_assuan_inquire_cb_t inq_cb,
144 : void *inq_cb_value,
145 : gpgme_assuan_status_cb_t status_cb,
146 : void *status_cb_value,
147 : gpgme_error_t *op_err)
148 : {
149 : gpgme_error_t err;
150 :
151 0 : if (!ctx)
152 0 : return gpg_error (GPG_ERR_INV_VALUE);
153 :
154 0 : err = vfs_start (ctx, 1, command, data_cb, data_cb_value,
155 : inq_cb, inq_cb_value, status_cb, status_cb_value);
156 0 : if (!err)
157 0 : err = _gpgme_wait_one_ext (ctx, op_err);
158 0 : return err;
159 : }
160 :
161 :
162 : /* The actual exported interface follows. */
163 :
164 : /* The container is automatically unmounted when the context is reset
165 : or destroyed. This is a synchronous convenience interface, which
166 : automatically returns an operation error if there is no
167 : transmission error. */
168 : static gpgme_error_t
169 0 : _gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file,
170 : const char *mount_dir, int flags, gpgme_error_t *op_err)
171 : {
172 : gpg_error_t err;
173 : char *cmd;
174 0 : char *container_file_esc = NULL;
175 :
176 : /* We want to encourage people to check error values, so not getting
177 : them is discouraged here. Also makes our code easier. */
178 0 : if (! op_err)
179 0 : return gpg_error (GPG_ERR_INV_VALUE);
180 :
181 0 : err = _gpgme_encode_percent_string (container_file, &container_file_esc, 0);
182 0 : if (err)
183 0 : return err;
184 :
185 0 : if (asprintf (&cmd, "OPEN -- %s", container_file_esc) < 0)
186 : {
187 0 : err = gpg_error_from_syserror ();
188 0 : free (container_file_esc);
189 0 : return err;
190 : }
191 0 : free (container_file_esc);
192 :
193 0 : err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL,
194 : NULL, NULL, op_err);
195 0 : free (cmd);
196 0 : if (err || *op_err)
197 0 : return err;
198 :
199 0 : if (mount_dir)
200 : {
201 0 : char *mount_dir_esc = NULL;
202 :
203 0 : err = _gpgme_encode_percent_string (mount_dir, &mount_dir_esc, 0);
204 0 : if (err)
205 0 : return err;
206 :
207 0 : if (asprintf (&cmd, "MOUNT -- %s", mount_dir_esc) < 0)
208 : {
209 0 : err = gpg_error_from_syserror ();
210 0 : free (mount_dir_esc);
211 0 : return err;
212 : }
213 0 : free (mount_dir_esc);
214 : }
215 : else
216 : {
217 0 : if (asprintf (&cmd, "MOUNT") < 0)
218 0 : return gpg_error_from_syserror ();
219 : }
220 :
221 0 : err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL,
222 : _gpgme_vfs_mount_status_handler, ctx, op_err);
223 0 : free (cmd);
224 :
225 0 : return err;
226 : }
227 :
228 : gpgme_error_t
229 0 : gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file,
230 : const char *mount_dir, unsigned int flags,
231 : gpgme_error_t *op_err)
232 : {
233 : gpg_error_t err;
234 :
235 0 : TRACE_BEG4 (DEBUG_CTX, "gpgme_op_vfs_mount", ctx,
236 : "container=%s, mount_dir=%s, flags=0x%x, op_err=%p",
237 : container_file, mount_dir, flags, op_err);
238 :
239 0 : if (!ctx)
240 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
241 :
242 0 : err = _gpgme_op_vfs_mount (ctx, container_file, mount_dir, flags, op_err);
243 0 : return TRACE_ERR (err);
244 : }
245 :
|