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 : (void)flags;
177 :
178 : /* We want to encourage people to check error values, so not getting
179 : them is discouraged here. Also makes our code easier. */
180 0 : if (! op_err)
181 0 : return gpg_error (GPG_ERR_INV_VALUE);
182 :
183 0 : err = _gpgme_encode_percent_string (container_file, &container_file_esc, 0);
184 0 : if (err)
185 0 : return err;
186 :
187 0 : if (gpgrt_asprintf (&cmd, "OPEN -- %s", container_file_esc) < 0)
188 : {
189 0 : err = gpg_error_from_syserror ();
190 0 : free (container_file_esc);
191 0 : return err;
192 : }
193 0 : free (container_file_esc);
194 :
195 0 : err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL,
196 : NULL, NULL, op_err);
197 0 : gpgrt_free (cmd);
198 0 : if (err || *op_err)
199 0 : return err;
200 :
201 0 : if (mount_dir)
202 : {
203 0 : char *mount_dir_esc = NULL;
204 :
205 0 : err = _gpgme_encode_percent_string (mount_dir, &mount_dir_esc, 0);
206 0 : if (err)
207 0 : return err;
208 :
209 0 : if (gpgrt_asprintf (&cmd, "MOUNT -- %s", mount_dir_esc) < 0)
210 : {
211 0 : err = gpg_error_from_syserror ();
212 0 : free (mount_dir_esc);
213 0 : return err;
214 : }
215 0 : free (mount_dir_esc);
216 : }
217 : else
218 : {
219 0 : if (gpgrt_asprintf (&cmd, "MOUNT") < 0)
220 0 : return gpg_error_from_syserror ();
221 : }
222 :
223 0 : err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL,
224 : _gpgme_vfs_mount_status_handler, ctx, op_err);
225 0 : gpgrt_free (cmd);
226 :
227 0 : return err;
228 : }
229 :
230 : gpgme_error_t
231 0 : gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file,
232 : const char *mount_dir, unsigned int flags,
233 : gpgme_error_t *op_err)
234 : {
235 : gpg_error_t err;
236 :
237 0 : TRACE_BEG4 (DEBUG_CTX, "gpgme_op_vfs_mount", ctx,
238 : "container=%s, mount_dir=%s, flags=0x%x, op_err=%p",
239 : container_file, mount_dir, flags, op_err);
240 :
241 0 : if (!ctx)
242 0 : return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
243 :
244 0 : err = _gpgme_op_vfs_mount (ctx, container_file, mount_dir, flags, op_err);
245 0 : return TRACE_ERR (err);
246 : }
247 :
|