From 97932b102af882a37c2613b0f50dc39369c48723 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Tue, 3 Nov 2009 19:15:35 +0000 Subject: 2009-11-03 Marcus Brinkmann * Makefile.am (main_sources): Change g13.c to vfs-mount.c. Add vfs-create.c * vfs-create.c: New file. * g13.c: Renamed to ... * vfs-mount.c: ... this new file. * gpgme.h.in (gpgme_op_vfs_create): New prototype. * gpgme.def, libgpgme.vers: Add gpgme_op_vfs_create. * gpgme-tool.c (gt_vfs_create, cmd_vfs_create): New functions. (register_commands): Add VFS_CREATE and CREAET. --- src/ChangeLog | 12 ++++ src/Makefile.am | 2 +- src/g13.c | 209 ----------------------------------------------------- src/gpgme-tool.c | 122 ++++++++++++++++++++++++++++++- src/gpgme.def | 1 + src/gpgme.h.in | 6 +- src/libgpgme.vers | 2 + src/vfs-create.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++++ src/vfs-mount.c | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 544 insertions(+), 213 deletions(-) delete mode 100644 src/g13.c create mode 100644 src/vfs-create.c create mode 100644 src/vfs-mount.c (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 8c3689e7..bcfaa729 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,15 @@ +2009-11-03 Marcus Brinkmann + + * Makefile.am (main_sources): Change g13.c to vfs-mount.c. Add + vfs-create.c + * vfs-create.c: New file. + * g13.c: Renamed to ... + * vfs-mount.c: ... this new file. + * gpgme.h.in (gpgme_op_vfs_create): New prototype. + * gpgme.def, libgpgme.vers: Add gpgme_op_vfs_create. + * gpgme-tool.c (gt_vfs_create, cmd_vfs_create): New functions. + (register_commands): Add VFS_CREATE and CREAET. + 2009-11-02 Marcus Brinkmann * debug.h (_gpgme_debug_buffer): Make TAG argument const const. diff --git a/src/Makefile.am b/src/Makefile.am index 677a8969..b1d93d36 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -111,7 +111,7 @@ main_sources = \ opassuan.c \ engine.h engine-backend.h engine.c engine-gpg.c status-table.h \ $(gpgsm_components) $(assuan_components) $(gpgconf_components) \ - $(g13_components) g13.c \ + $(g13_components) vfs-mount.c vfs-create.c \ gpgconf.c \ sema.h priv-io.h $(system_components) dirinfo.c \ debug.c debug.h gpgme.c version.c error.c diff --git a/src/g13.c b/src/g13.c deleted file mode 100644 index a2ab675e..00000000 --- a/src/g13.c +++ /dev/null @@ -1,209 +0,0 @@ -/* g13.c - g13 support in GPGME - Copyright (C) 2009 g10 Code GmbH - - This file is part of GPGME. - - GPGME is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of - the License, or (at your option) any later version. - - GPGME 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ - -#if HAVE_CONFIG_H -#include -#endif - -#include - -#include "gpgme.h" -#include "debug.h" -#include "context.h" -#include "ops.h" -#include "util.h" - -typedef struct -{ - struct _gpgme_op_vfs_mount_result result; -} *op_data_t; - - - -gpgme_vfs_mount_result_t -gpgme_op_vfs_mount_result (gpgme_ctx_t ctx) -{ - gpgme_error_t err; - void *hook; - op_data_t opd; - - err = _gpgme_op_data_lookup (ctx, OPDATA_VFS_MOUNT, &hook, -1, NULL); - opd = hook; - /* Check in case this function is used without having run a command - before. */ - if (err || !opd) - return NULL; - - return &opd->result; -} - - -static gpgme_error_t -vfs_start (gpgme_ctx_t ctx, int synchronous, - const char *command, - gpgme_assuan_data_cb_t data_cb, - void *data_cb_value, - gpgme_assuan_inquire_cb_t inq_cb, - void *inq_cb_value, - gpgme_assuan_status_cb_t status_cb, - void *status_cb_value) -{ - gpgme_error_t err; - void *hook; - op_data_t opd; - - if (!command || !*command) - return gpg_error (GPG_ERR_INV_VALUE); - - /* The flag value 256 is used to suppress an engine reset. This is - required to keep the connection running. */ - err = _gpgme_op_reset (ctx, ((synchronous & 255) | 256)); - if (err) - return err; - - err = _gpgme_op_data_lookup (ctx, OPDATA_VFS_MOUNT, &hook, sizeof (*opd), - NULL); - opd = hook; - if (err) - return err; - - return _gpgme_engine_op_assuan_transact (ctx->engine, command, - data_cb, data_cb_value, - inq_cb, inq_cb_value, - status_cb, status_cb_value); -} - - - -/* XXXX. This is the asynchronous variant. */ -static gpgme_error_t -gpgme_op_vfs_transact_start (gpgme_ctx_t ctx, - const char *command, - gpgme_assuan_data_cb_t data_cb, - void *data_cb_value, - gpgme_assuan_inquire_cb_t inq_cb, - void *inq_cb_value, - gpgme_assuan_status_cb_t status_cb, - void *status_cb_value) -{ - return vfs_start (ctx, 0, command, data_cb, data_cb_value, - inq_cb, inq_cb_value, status_cb, status_cb_value); -} - - -/* XXXX. This is the synchronous variant. */ -static gpgme_error_t -gpgme_op_vfs_transact (gpgme_ctx_t ctx, - const char *command, - gpgme_assuan_data_cb_t data_cb, - void *data_cb_value, - gpgme_assuan_inquire_cb_t inq_cb, - void *inq_cb_value, - gpgme_assuan_status_cb_t status_cb, - void *status_cb_value, - gpgme_error_t *op_err) -{ - gpgme_error_t err; - - err = vfs_start (ctx, 1, command, data_cb, data_cb_value, - inq_cb, inq_cb_value, status_cb, status_cb_value); - if (!err) - err = _gpgme_wait_one_ext (ctx, op_err); - return err; -} - - -/* The actual exported interface follows. */ - -/* The container is automatically unmounted when the context is reset - or destroyed. This is a synchronous convenience interface, which - automatically returns an operation error if there is no - transmission error. */ -static gpgme_error_t -_gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file, - const char *mount_dir, int flags, gpgme_error_t *op_err) -{ - gpg_error_t err; - char *cmd; - char *container_file_esc = NULL; - - /* We want to encourage people to check error values, so not getting - them is discouraged here. Also makes our code easier. */ - if (! op_err) - return gpg_error (GPG_ERR_INV_VALUE); - - err = _gpgme_encode_percent_string (container_file, &container_file_esc, 0); - if (err) - return err; - - if (asprintf (&cmd, "OPEN -- %s", container_file_esc) < 0) - { - err = gpg_error_from_syserror (); - free (container_file_esc); - return err; - } - free (container_file_esc); - - err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL, - NULL, NULL, op_err); - free (cmd); - if (err || *op_err) - return err; - - if (mount_dir) - { - char *mount_dir_esc = NULL; - - err = _gpgme_encode_percent_string (mount_dir, &mount_dir_esc, 0); - if (err) - return err; - - if (asprintf (&cmd, "MOUNT -- %s", mount_dir_esc) < 0) - { - err = gpg_error_from_syserror (); - free (mount_dir_esc); - return err; - } - free (mount_dir_esc); - } - else - { - if (asprintf (&cmd, "MOUNT") < 0) - return gpg_error_from_syserror (); - } - - err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL, - NULL, NULL, op_err); - free (cmd); - - return err; -} - -gpgme_error_t -gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file, - const char *mount_dir, int flags, gpgme_error_t *op_err) -{ - TRACE_BEG4 (DEBUG_CTX, "gpgme_op_vfs_mount", ctx, - "container=%s, mount_dir=%s, flags=0x%x, op_err=%p", - container_file, mount_dir, flags, op_err); - return TRACE_ERR (_gpgme_op_vfs_mount (ctx, container_file, mount_dir, - flags, op_err)); -} - diff --git a/src/gpgme-tool.c b/src/gpgme-tool.c index e4948e28..7a41be08 100644 --- a/src/gpgme-tool.c +++ b/src/gpgme-tool.c @@ -483,6 +483,7 @@ typedef enum status STATUS_TEXTMODE, STATUS_INCLUDE_CERTS, STATUS_KEYLIST_MODE, + STATUS_RECIPIENT, STATUS_ENCRYPT_RESULT } status_t; @@ -495,6 +496,7 @@ const char *status_string[] = "TEXTMODE", "INCLUDE_CERTS", "KEYLIST_MODE", + "RECIPIENT", "ENCRYPT_RESULT" }; @@ -574,7 +576,88 @@ gt_signers_clear (gpgme_tool_t gt) gpg_error_t -gt_recipients_add (gpgme_tool_t gt, const char *fpr) +gt_get_key (gpgme_tool_t gt, const char *pattern, gpgme_key_t *r_key) +{ + gpgme_ctx_t ctx; + gpgme_ctx_t listctx; + gpgme_error_t err; + gpgme_key_t key; + + if (!gt || !r_key || !pattern) + return gpg_error (GPG_ERR_INV_VALUE); + + ctx = gt->ctx; + + err = gpgme_new (&listctx); + if (err) + return err; + + { + gpgme_protocol_t proto; + gpgme_engine_info_t info; + + /* Clone the relevant state. */ + proto = gpgme_get_protocol (ctx); + /* The g13 protocol does not allow keylisting, we need to choose + something else. */ + if (proto == GPGME_PROTOCOL_G13) + proto = GPGME_PROTOCOL_OpenPGP; + + gpgme_set_protocol (listctx, proto); + gpgme_set_keylist_mode (listctx, gpgme_get_keylist_mode (ctx)); + info = gpgme_ctx_get_engine_info (ctx); + while (info && info->protocol != proto) + info = info->next; + if (info) + gpgme_ctx_set_engine_info (listctx, proto, + info->file_name, info->home_dir); + } + + err = gpgme_op_keylist_start (listctx, pattern, 0); + if (!err) + err = gpgme_op_keylist_next (listctx, r_key); + if (!err) + { + try_next_key: + err = gpgme_op_keylist_next (listctx, &key); + if (gpgme_err_code (err) == GPG_ERR_EOF) + err = 0; + else + { + if (!err + && *r_key && (*r_key)->subkeys && (*r_key)->subkeys->fpr + && key && key->subkeys && key->subkeys->fpr + && !strcmp ((*r_key)->subkeys->fpr, key->subkeys->fpr)) + { + /* The fingerprint is identical. We assume that this is + the same key and don't mark it as an ambiguous. This + problem may occur with corrupted keyrings and has + been noticed often with gpgsm. In fact gpgsm uses a + similar hack to sort out such duplicates but it can't + do that while listing keys. */ + gpgme_key_unref (key); + goto try_next_key; + } + if (!err) + { + gpgme_key_unref (key); + err = gpg_error (GPG_ERR_AMBIGUOUS_NAME); + } + gpgme_key_unref (*r_key); + } + } + gpgme_release (listctx); + + if (! err) + gt_write_status (gt, STATUS_RECIPIENT, + ((*r_key)->subkeys && (*r_key)->subkeys->fpr) ? + (*r_key)->subkeys->fpr : "invalid", NULL); + return err; +} + + +gpg_error_t +gt_recipients_add (gpgme_tool_t gt, const char *pattern) { gpg_error_t err; gpgme_key_t key; @@ -582,7 +665,7 @@ gt_recipients_add (gpgme_tool_t gt, const char *fpr) if (gt->recipients_nr >= MAX_RECIPIENTS) return gpg_error_from_errno (ENOMEM); - err = gpgme_get_key (gt->ctx, fpr, &key, 0); + err = gt_get_key (gt, pattern, &key); if (err) return err; @@ -962,6 +1045,18 @@ gt_vfs_mount (gpgme_tool_t gt, const char *container_file, } +gpg_error_t +gt_vfs_create (gpgme_tool_t gt, const char *container_file, int flags) +{ + gpg_error_t err; + gpg_error_t op_err; + err = gpgme_op_vfs_create (gt->ctx, gt->recipients, container_file, + flags, &op_err); + gt_recipients_clear (gt); + return err || op_err; +} + + // TODO #define GT_RESULT_ENCRYPT 0x1 #define GT_RESULT_DECRYPT 0x2 @@ -1742,6 +1837,27 @@ cmd_vfs_mount (assuan_context_t ctx, char *line) } +static gpg_error_t +cmd_vfs_create (assuan_context_t ctx, char *line) +{ + struct server *server = assuan_get_pointer (ctx); + gpg_error_t err; + char *end; + + end = strchr (line, ' '); + if (end) + { + *(end++) = '\0'; + while (*end == ' ') + end++; + } + + err = gt_vfs_create (server->gt, line, 0); + + return err; +} + + static gpg_error_t cmd_result (assuan_context_t ctx, char *line) { @@ -1835,6 +1951,8 @@ register_commands (assuan_context_t ctx) // TODO: ASSUAN { "VFS_MOUNT", cmd_vfs_mount }, { "MOUNT", cmd_vfs_mount }, + { "VFS_CREATE", cmd_vfs_create }, + { "CREATE", cmd_vfs_create }, // TODO: GPGCONF { "RESULT", cmd_result }, { "STRERROR", cmd_strerror }, diff --git a/src/gpgme.def b/src/gpgme.def index 6d223f4d..816da318 100644 --- a/src/gpgme.def +++ b/src/gpgme.def @@ -190,6 +190,7 @@ EXPORTS gpgme_wait_ext @145 gpgme_op_vfs_mount_result @146 gpgme_op_vfs_mount @147 + gpgme_op_vfs_create @148 ; END diff --git a/src/gpgme.h.in b/src/gpgme.h.in index 42b9237f..f0a61d79 100644 --- a/src/gpgme.h.in +++ b/src/gpgme.h.in @@ -1808,9 +1808,13 @@ gpgme_vfs_mount_result_t gpgme_op_vfs_mount_result (gpgme_ctx_t ctx); or destroyed. Transmission errors are returned directly, operational errors are returned in OP_ERR. */ gpgme_error_t gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file, - const char *mount_dir, int flags, + const char *mount_dir, unsigned int flags, gpgme_error_t *op_err); +gpgme_error_t gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[], + const char *container_file, + unsigned int flags, gpgme_error_t *op_err); + /* Interface to gpgconf(1). */ diff --git a/src/libgpgme.vers b/src/libgpgme.vers index 9989c75b..24107d48 100644 --- a/src/libgpgme.vers +++ b/src/libgpgme.vers @@ -71,6 +71,8 @@ GPGME_1.1 { gpgme_op_vfs_mount_result; gpgme_op_vfs_mount; + gpgme_op_vfs_create; + }; diff --git a/src/vfs-create.c b/src/vfs-create.c new file mode 100644 index 00000000..a965a964 --- /dev/null +++ b/src/vfs-create.c @@ -0,0 +1,193 @@ +/* vfs-create.c - vfs create support in GPGME + Copyright (C) 2009 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + GPGME 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include + +#include "gpgme.h" +#include "debug.h" +#include "context.h" +#include "ops.h" +#include "util.h" + +static gpgme_error_t +vfs_start (gpgme_ctx_t ctx, int synchronous, + const char *command, + gpgme_assuan_data_cb_t data_cb, + void *data_cb_value, + gpgme_assuan_inquire_cb_t inq_cb, + void *inq_cb_value, + gpgme_assuan_status_cb_t status_cb, + void *status_cb_value) +{ + gpgme_error_t err; + + if (!command || !*command) + return gpg_error (GPG_ERR_INV_VALUE); + + /* The flag value 256 is used to suppress an engine reset. This is + required to keep the connection running. */ + err = _gpgme_op_reset (ctx, ((synchronous & 255) | 256)); + if (err) + return err; + + return _gpgme_engine_op_assuan_transact (ctx->engine, command, + data_cb, data_cb_value, + inq_cb, inq_cb_value, + status_cb, status_cb_value); +} + + + +/* XXXX. This is the asynchronous variant. */ +static gpgme_error_t +gpgme_op_vfs_transact_start (gpgme_ctx_t ctx, + const char *command, + gpgme_assuan_data_cb_t data_cb, + void *data_cb_value, + gpgme_assuan_inquire_cb_t inq_cb, + void *inq_cb_value, + gpgme_assuan_status_cb_t status_cb, + void *status_cb_value) +{ + return vfs_start (ctx, 0, command, data_cb, data_cb_value, + inq_cb, inq_cb_value, status_cb, status_cb_value); +} + + +/* XXXX. This is the synchronous variant. */ +static gpgme_error_t +gpgme_op_vfs_transact (gpgme_ctx_t ctx, + const char *command, + gpgme_assuan_data_cb_t data_cb, + void *data_cb_value, + gpgme_assuan_inquire_cb_t inq_cb, + void *inq_cb_value, + gpgme_assuan_status_cb_t status_cb, + void *status_cb_value, + gpgme_error_t *op_err) +{ + gpgme_error_t err; + + err = vfs_start (ctx, 1, command, data_cb, data_cb_value, + inq_cb, inq_cb_value, status_cb, status_cb_value); + if (!err) + err = _gpgme_wait_one_ext (ctx, op_err); + return err; +} + + +/* The actual exported interface follows. */ + +/* The container is automatically uncreateed when the context is reset + or destroyed. This is a synchronous convenience interface, which + automatically returns an operation error if there is no + transmission error. */ +static gpgme_error_t +_gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[], + const char *container_file, unsigned int flags, + gpgme_error_t *op_err) +{ + gpg_error_t err; + char *cmd; + char *container_file_esc = NULL; + int i; + + /* We want to encourage people to check error values, so not getting + them is discouraged here. Also makes our code easier. */ + if (! op_err) + return gpg_error (GPG_ERR_INV_VALUE); + + err = _gpgme_encode_percent_string (container_file, &container_file_esc, 0); + if (err) + return err; + + i = 0; + while (!err && recp[i]) + { + if (!recp[i]->subkeys || !recp[i]->subkeys->fpr) + { + free (container_file_esc); + return gpg_error (GPG_ERR_UNUSABLE_PUBKEY); + } + + if (asprintf (&cmd, "RECIPIENT %s", recp[i]->subkeys->fpr) < 0) + { + err = gpg_error_from_syserror (); + free (container_file_esc); + return err; + } + + err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL, + NULL, NULL, op_err); + free (cmd); + if (err || *op_err) + { + free (container_file_esc); + return err; + } + recp++; + } + + if (asprintf (&cmd, "CREATE -- %s", container_file_esc) < 0) + { + err = gpg_error_from_syserror (); + free (container_file_esc); + return err; + } + free (container_file_esc); + + err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL, + NULL, NULL, op_err); + free (cmd); + + return err; +} + + +gpgme_error_t +gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[], + const char *container_file, unsigned int flags, + gpgme_error_t *op_err) +{ + TRACE_BEG3 (DEBUG_CTX, "gpgme_op_vfs_create", ctx, + "container_file=%s, flags=0x%x, op_err=%p", + container_file, flags, op_err); + + if (_gpgme_debug_trace () && recp) + { + int i = 0; + + while (recp[i]) + { + TRACE_LOG3 ("recipient[%i] = %p (%s)", i, recp[i], + (recp[i]->subkeys && recp[i]->subkeys->fpr) ? + recp[i]->subkeys->fpr : "invalid"); + i++; + } + } + + return TRACE_ERR (_gpgme_op_vfs_create (ctx, recp, container_file, + flags, op_err)); +} + diff --git a/src/vfs-mount.c b/src/vfs-mount.c new file mode 100644 index 00000000..3c0b6f24 --- /dev/null +++ b/src/vfs-mount.c @@ -0,0 +1,210 @@ +/* vfs-mount.c - vfs mount support in GPGME + Copyright (C) 2009 g10 Code GmbH + + This file is part of GPGME. + + GPGME is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + GPGME 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#if HAVE_CONFIG_H +#include +#endif + +#include + +#include "gpgme.h" +#include "debug.h" +#include "context.h" +#include "ops.h" +#include "util.h" + +typedef struct +{ + struct _gpgme_op_vfs_mount_result result; +} *op_data_t; + + + +gpgme_vfs_mount_result_t +gpgme_op_vfs_mount_result (gpgme_ctx_t ctx) +{ + gpgme_error_t err; + void *hook; + op_data_t opd; + + err = _gpgme_op_data_lookup (ctx, OPDATA_VFS_MOUNT, &hook, -1, NULL); + opd = hook; + /* Check in case this function is used without having run a command + before. */ + if (err || !opd) + return NULL; + + return &opd->result; +} + + +static gpgme_error_t +vfs_start (gpgme_ctx_t ctx, int synchronous, + const char *command, + gpgme_assuan_data_cb_t data_cb, + void *data_cb_value, + gpgme_assuan_inquire_cb_t inq_cb, + void *inq_cb_value, + gpgme_assuan_status_cb_t status_cb, + void *status_cb_value) +{ + gpgme_error_t err; + void *hook; + op_data_t opd; + + if (!command || !*command) + return gpg_error (GPG_ERR_INV_VALUE); + + /* The flag value 256 is used to suppress an engine reset. This is + required to keep the connection running. */ + err = _gpgme_op_reset (ctx, ((synchronous & 255) | 256)); + if (err) + return err; + + err = _gpgme_op_data_lookup (ctx, OPDATA_VFS_MOUNT, &hook, sizeof (*opd), + NULL); + opd = hook; + if (err) + return err; + + return _gpgme_engine_op_assuan_transact (ctx->engine, command, + data_cb, data_cb_value, + inq_cb, inq_cb_value, + status_cb, status_cb_value); +} + + + +/* XXXX. This is the asynchronous variant. */ +static gpgme_error_t +gpgme_op_vfs_transact_start (gpgme_ctx_t ctx, + const char *command, + gpgme_assuan_data_cb_t data_cb, + void *data_cb_value, + gpgme_assuan_inquire_cb_t inq_cb, + void *inq_cb_value, + gpgme_assuan_status_cb_t status_cb, + void *status_cb_value) +{ + return vfs_start (ctx, 0, command, data_cb, data_cb_value, + inq_cb, inq_cb_value, status_cb, status_cb_value); +} + + +/* XXXX. This is the synchronous variant. */ +static gpgme_error_t +gpgme_op_vfs_transact (gpgme_ctx_t ctx, + const char *command, + gpgme_assuan_data_cb_t data_cb, + void *data_cb_value, + gpgme_assuan_inquire_cb_t inq_cb, + void *inq_cb_value, + gpgme_assuan_status_cb_t status_cb, + void *status_cb_value, + gpgme_error_t *op_err) +{ + gpgme_error_t err; + + err = vfs_start (ctx, 1, command, data_cb, data_cb_value, + inq_cb, inq_cb_value, status_cb, status_cb_value); + if (!err) + err = _gpgme_wait_one_ext (ctx, op_err); + return err; +} + + +/* The actual exported interface follows. */ + +/* The container is automatically unmounted when the context is reset + or destroyed. This is a synchronous convenience interface, which + automatically returns an operation error if there is no + transmission error. */ +static gpgme_error_t +_gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file, + const char *mount_dir, int flags, gpgme_error_t *op_err) +{ + gpg_error_t err; + char *cmd; + char *container_file_esc = NULL; + + /* We want to encourage people to check error values, so not getting + them is discouraged here. Also makes our code easier. */ + if (! op_err) + return gpg_error (GPG_ERR_INV_VALUE); + + err = _gpgme_encode_percent_string (container_file, &container_file_esc, 0); + if (err) + return err; + + if (asprintf (&cmd, "OPEN -- %s", container_file_esc) < 0) + { + err = gpg_error_from_syserror (); + free (container_file_esc); + return err; + } + free (container_file_esc); + + err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL, + NULL, NULL, op_err); + free (cmd); + if (err || *op_err) + return err; + + if (mount_dir) + { + char *mount_dir_esc = NULL; + + err = _gpgme_encode_percent_string (mount_dir, &mount_dir_esc, 0); + if (err) + return err; + + if (asprintf (&cmd, "MOUNT -- %s", mount_dir_esc) < 0) + { + err = gpg_error_from_syserror (); + free (mount_dir_esc); + return err; + } + free (mount_dir_esc); + } + else + { + if (asprintf (&cmd, "MOUNT") < 0) + return gpg_error_from_syserror (); + } + + err = gpgme_op_vfs_transact (ctx, cmd, NULL, NULL, NULL, NULL, + NULL, NULL, op_err); + free (cmd); + + return err; +} + +gpgme_error_t +gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file, + const char *mount_dir, unsigned int flags, + gpgme_error_t *op_err) +{ + TRACE_BEG4 (DEBUG_CTX, "gpgme_op_vfs_mount", ctx, + "container=%s, mount_dir=%s, flags=0x%x, op_err=%p", + container_file, mount_dir, flags, op_err); + return TRACE_ERR (_gpgme_op_vfs_mount (ctx, container_file, mount_dir, + flags, op_err)); +} + -- cgit v1.2.3