summaryrefslogtreecommitdiffstats
path: root/g13
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2009-10-15 19:20:41 +0200
committerWerner Koch <wk@gnupg.org>2009-10-15 19:20:41 +0200
commit598bf9199e89a53bc0ffd2e32141a42d5ec85184 (patch)
tree0a5d888558adc8f13d873bbf93c639f5aaebb738 /g13
parentmount does now work in server and standalone mode. (diff)
downloadgnupg2-598bf9199e89a53bc0ffd2e32141a42d5ec85184.tar.xz
gnupg2-598bf9199e89a53bc0ffd2e32141a42d5ec85184.zip
Reworked the server commands.
Track mounts. --create does now work as expected.
Diffstat (limited to 'g13')
-rw-r--r--g13/Makefile.am1
-rw-r--r--g13/backend.c9
-rw-r--r--g13/backend.h6
-rw-r--r--g13/be-encfs.c27
-rw-r--r--g13/be-encfs.h6
-rw-r--r--g13/create.c4
-rw-r--r--g13/g13.c8
-rw-r--r--g13/mount.c110
-rw-r--r--g13/mount.h7
-rw-r--r--g13/mountinfo.c183
-rw-r--r--g13/mountinfo.h40
-rw-r--r--g13/runner.c66
-rw-r--r--g13/runner.h6
-rw-r--r--g13/server.c317
14 files changed, 601 insertions, 189 deletions
diff --git a/g13/Makefile.am b/g13/Makefile.am
index e65684c0f..3143e8a4d 100644
--- a/g13/Makefile.am
+++ b/g13/Makefile.am
@@ -33,6 +33,7 @@ g13_SOURCES = \
server.c server.h \
create.c create.h \
mount.c mount.h \
+ mountinfo.c mountinfo.h \
call-gpg.c call-gpg.h \
runner.c runner.h \
backend.c backend.h \
diff --git a/g13/backend.c b/g13/backend.c
index 08aec324f..531e745ed 100644
--- a/g13/backend.c
+++ b/g13/backend.c
@@ -101,14 +101,15 @@ be_create_new_keys (int conttype, membuf_t *mb)
/* Dispatcher to the backend's create function. */
gpg_error_t
be_create_container (ctrl_t ctrl, int conttype,
- const char *fname, int fd, tupledesc_t tuples)
+ const char *fname, int fd, tupledesc_t tuples,
+ unsigned int *r_id)
{
(void)fd; /* Not yet used. */
switch (conttype)
{
case CONTTYPE_ENCFS:
- return be_encfs_create_container (ctrl, fname, tuples);
+ return be_encfs_create_container (ctrl, fname, tuples, r_id);
default:
return no_such_backend (conttype);
@@ -120,12 +121,12 @@ be_create_container (ctrl_t ctrl, int conttype,
gpg_error_t
be_mount_container (ctrl_t ctrl, int conttype,
const char *fname, const char *mountpoint,
- tupledesc_t tuples)
+ tupledesc_t tuples, unsigned int *r_id)
{
switch (conttype)
{
case CONTTYPE_ENCFS:
- return be_encfs_mount_container (ctrl, fname, mountpoint, tuples);
+ return be_encfs_mount_container (ctrl, fname, mountpoint, tuples, r_id);
default:
return no_such_backend (conttype);
diff --git a/g13/backend.h b/g13/backend.h
index 7cdde9e4b..2048697dc 100644
--- a/g13/backend.h
+++ b/g13/backend.h
@@ -30,10 +30,12 @@ gpg_error_t be_create_new_keys (int conttype, membuf_t *mb);
gpg_error_t be_create_container (ctrl_t ctrl, int conttype,
const char *fname, int fd,
- tupledesc_t tuples);
+ tupledesc_t tuples,
+ unsigned int *r_id);
gpg_error_t be_mount_container (ctrl_t ctrl, int conttype,
const char *fname, const char *mountpoint,
- tupledesc_t tuples);
+ tupledesc_t tuples,
+ unsigned int *r_id);
#endif /*G13_BACKEND_H*/
diff --git a/g13/be-encfs.c b/g13/be-encfs.c
index de3209a91..06e8792b3 100644
--- a/g13/be-encfs.c
+++ b/g13/be-encfs.c
@@ -211,7 +211,8 @@ encfs_handler_cleanup (void *opaque)
/* Run the encfs tool. */
static gpg_error_t
run_encfs_tool (ctrl_t ctrl, enum encfs_cmds cmd,
- const char *rawdir, const char *mountpoint, tupledesc_t tuples)
+ const char *rawdir, const char *mountpoint, tupledesc_t tuples,
+ unsigned int *r_id)
{
gpg_error_t err;
encfs_parm_t parm;
@@ -240,15 +241,9 @@ run_encfs_tool (ctrl_t ctrl, enum encfs_cmds cmd,
goto leave;
}
- {
- static int namecounter;
- char buffer[50];
-
- snprintf (buffer, sizeof buffer, "encfs-%d", ++namecounter);
- err = runner_new (&runner, buffer);
- if (err)
- goto leave;
- }
+ err = runner_new (&runner, "encfs");
+ if (err)
+ goto leave;
err = gnupg_create_inbound_pipe (inbound);
if (!err)
@@ -295,6 +290,7 @@ run_encfs_tool (ctrl_t ctrl, enum encfs_cmds cmd,
if (err)
goto leave;
+ *r_id = runner_get_rid (runner);
log_info ("running `%s' in the background\n", pgmname);
leave:
@@ -400,7 +396,8 @@ be_encfs_create_new_keys (membuf_t *mb)
/* Create the container described by the filename FNAME and the keyblob
information in TUPLES. */
gpg_error_t
-be_encfs_create_container (ctrl_t ctrl, const char *fname, tupledesc_t tuples)
+be_encfs_create_container (ctrl_t ctrl, const char *fname, tupledesc_t tuples,
+ unsigned int *r_id)
{
gpg_error_t err;
int dummy;
@@ -426,7 +423,7 @@ be_encfs_create_container (ctrl_t ctrl, const char *fname, tupledesc_t tuples)
}
err = run_encfs_tool (ctrl, ENCFS_CMD_CREATE, containername, mountpoint,
- tuples);
+ tuples, r_id);
/* In any case remove the temporary mount point. */
if (rmdir (mountpoint))
@@ -442,11 +439,11 @@ be_encfs_create_container (ctrl_t ctrl, const char *fname, tupledesc_t tuples)
/* Mount the container described by the filename FNAME and the keyblob
- information in TUPLES. */
+ information in TUPLES. On success the runner id is stored at R_ID. */
gpg_error_t
be_encfs_mount_container (ctrl_t ctrl,
const char *fname, const char *mountpoint,
- tupledesc_t tuples)
+ tupledesc_t tuples, unsigned int *r_id)
{
gpg_error_t err;
int dummy;
@@ -464,7 +461,7 @@ be_encfs_mount_container (ctrl_t ctrl,
goto leave;
err = run_encfs_tool (ctrl, ENCFS_CMD_MOUNT, containername, mountpoint,
- tuples);
+ tuples, r_id);
leave:
xfree (containername);
diff --git a/g13/be-encfs.h b/g13/be-encfs.h
index c6c8396c5..8ac35f947 100644
--- a/g13/be-encfs.h
+++ b/g13/be-encfs.h
@@ -28,12 +28,14 @@ gpg_error_t be_encfs_create_new_keys (membuf_t *mb);
gpg_error_t be_encfs_create_container (ctrl_t ctrl,
const char *fname,
- tupledesc_t tuples);
+ tupledesc_t tuples,
+ unsigned int *r_id);
gpg_error_t be_encfs_mount_container (ctrl_t ctrl,
const char *fname,
const char *mountpoint,
- tupledesc_t tuples);
+ tupledesc_t tuples,
+ unsigned int *r_id);
#endif /*G13_BE_ENCFS_H*/
diff --git a/g13/create.c b/g13/create.c
index 0279c337d..9de9edc0b 100644
--- a/g13/create.c
+++ b/g13/create.c
@@ -231,6 +231,7 @@ g13_create_container (ctrl_t ctrl, const char *filename)
char *detachedname = NULL;
int detachedisdir;
tupledesc_t tuples = NULL;
+ unsigned int dummy_rid;
/* A quick check to see that no container with that name already
exists. */
@@ -304,7 +305,8 @@ g13_create_container (ctrl_t ctrl, const char *filename)
/* Create and append the container. FIXME: We should pass the
estream object in addition to the filename, so that the backend
can append the container to the g13 file. */
- err = be_create_container (ctrl, ctrl->conttype, filename, -1, tuples);
+ err = be_create_container (ctrl, ctrl->conttype, filename, -1, tuples,
+ &dummy_rid);
leave:
diff --git a/g13/g13.c b/g13/g13.c
index 288689457..453fa9e65 100644
--- a/g13/g13.c
+++ b/g13/g13.c
@@ -39,7 +39,8 @@
#include "server.h"
#include "runner.h"
#include "create.h"
-#include "./mount.h"
+#include "mount.h"
+#include "mountinfo.h"
enum cmd_and_opt_values {
@@ -707,6 +708,8 @@ main ( int argc, char **argv)
if (err)
log_error ("server exited with error: %s <%s>\n",
gpg_strerror (err), gpg_strsource (err));
+ else
+ shutdown_pending++;
}
break;
@@ -719,6 +722,8 @@ main ( int argc, char **argv)
if (err)
log_error ("error creating a new container: %s <%s>\n",
gpg_strerror (err), gpg_strsource (err));
+ else
+ shutdown_pending++;
}
break;
@@ -807,6 +812,7 @@ handle_signal (int signo)
case SIGUSR1:
log_info ("SIGUSR1 received - printing internal information:\n");
pth_ctrl (PTH_CTRL_DUMPSTATE, log_get_stream ());
+ mountinfo_dump_all ();
break;
case SIGUSR2:
diff --git a/g13/mount.c b/g13/mount.c
index 85851e9a8..dc23b6b2b 100644
--- a/g13/mount.c
+++ b/g13/mount.c
@@ -35,6 +35,8 @@
#include "utils.h"
#include "call-gpg.h"
#include "estream.h"
+#include "mountinfo.h"
+#include "runner.h"
/* Parse the header prefix and return the length of the entire header. */
@@ -89,28 +91,23 @@ parse_header (const char *filename,
}
-
-/* Read the keyblob at FILENAME. The caller should have acquired a
- lockfile and checked that the file exists. */
+/* Read the prefix of the keyblob and do some basic parsing. On
+ success returns an open estream file at R_FP and the length of the
+ header at R_HEADERLEN. */
static gpg_error_t
-read_keyblob (const char *filename,
- void **r_enckeyblob, size_t *r_enckeybloblen)
+read_keyblob_prefix (const char *filename, estream_t *r_fp, size_t *r_headerlen)
{
gpg_error_t err;
estream_t fp;
unsigned char packet[32];
- size_t headerlen, msglen;
- void *msg = NULL;
- *r_enckeyblob = NULL;
- *r_enckeybloblen = 0;
+ *r_fp = NULL;
fp = es_fopen (filename, "rb");
if (!fp)
{
err = gpg_error_from_syserror ();
- log_error ("error reading `%s': %s\n",
- filename, gpg_strerror (err));
+ log_error ("error reading `%s': %s\n", filename, gpg_strerror (err));
return err;
}
@@ -120,10 +117,35 @@ read_keyblob (const char *filename,
err = gpg_error_from_syserror ();
log_error ("error reading the header of `%s': %s\n",
filename, gpg_strerror (err));
- goto leave;
+ es_fclose (fp);
+ return err;
}
- err = parse_header (filename, packet, 32, &headerlen);
+ err = parse_header (filename, packet, 32, r_headerlen);
+ if (err)
+ es_fclose (fp);
+ else
+ *r_fp = fp;
+
+ return err;
+}
+
+
+/* Read the keyblob at FILENAME. The caller should have acquired a
+ lockfile and checked that the file exists. */
+static gpg_error_t
+read_keyblob (const char *filename,
+ void **r_enckeyblob, size_t *r_enckeybloblen)
+{
+ gpg_error_t err;
+ estream_t fp = NULL;
+ size_t headerlen, msglen;
+ void *msg = NULL;
+
+ *r_enckeyblob = NULL;
+ *r_enckeybloblen = 0;
+
+ err = read_keyblob_prefix (filename, &fp, &headerlen);
if (err)
goto leave;
@@ -227,6 +249,7 @@ g13_mount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
size_t n;
const unsigned char *value;
int conttype;
+ unsigned int rid;
/* A quick check to see whether the container exists. */
if (access (filename, R_OK))
@@ -292,7 +315,13 @@ g13_mount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
err = gpg_error (GPG_ERR_NOT_SUPPORTED);
goto leave;
}
- err = be_mount_container (ctrl, conttype, filename, mountpoint, tuples);
+ err = be_mount_container (ctrl, conttype, filename, mountpoint, tuples, &rid);
+ if (!err)
+ {
+ err = mountinfo_add_mount (filename, mountpoint, conttype, rid);
+ /* Fixme: What shall we do if this fails? Add a provisional
+ mountinfo entry first and remove it on error? */
+ }
leave:
destroy_tupledesc (tuples);
@@ -301,3 +330,56 @@ g13_mount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
destroy_dotlock (lock);
return err;
}
+
+
+/* Unmount the container with name FILENAME or the one mounted at
+ MOUNTPOINT. If both are given the FILENAME takes precedence. */
+gpg_error_t
+g13_umount_container (ctrl_t ctrl, const char *filename, const char *mountpoint)
+{
+ gpg_error_t err;
+ unsigned int rid;
+ runner_t runner;
+
+ (void)ctrl;
+
+ if (!filename && !mountpoint)
+ return gpg_error (GPG_ERR_ENOENT);
+ err = mountinfo_find_mount (filename, mountpoint, &rid);
+ if (err)
+ return err;
+
+ runner = runner_find_by_rid (rid);
+ if (!runner)
+ {
+ log_error ("runner %u not found\n", rid);
+ return gpg_error (GPG_ERR_NOT_FOUND);
+ }
+
+ runner_cancel (runner);
+ runner_release (runner);
+
+ return 0;
+}
+
+
+/* Test whether the container with name FILENAME is a suitable G13
+ container. This function may even be called on a mounted
+ container. */
+gpg_error_t
+g13_is_container (ctrl_t ctrl, const char *filename)
+{
+ gpg_error_t err;
+ estream_t fp = NULL;
+ size_t dummy;
+
+ (void)ctrl;
+
+ /* Read just the prefix of the header. */
+ err = read_keyblob_prefix (filename, &fp, &dummy);
+ if (!err)
+ es_fclose (fp);
+ return err;
+}
+
+
diff --git a/g13/mount.h b/g13/mount.h
index 03b8264c9..f99426494 100644
--- a/g13/mount.h
+++ b/g13/mount.h
@@ -1,4 +1,4 @@
-/* mmount.h - Defs to mount a crypto container
+/* mount.h - Defs to mount a crypto container
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* This file is part of GnuPG.
@@ -23,6 +23,11 @@
gpg_error_t g13_mount_container (ctrl_t ctrl,
const char *filename,
const char *mountpoint);
+gpg_error_t g13_umount_container (ctrl_t ctrl,
+ const char *filename,
+ const char *mountpoint);
+
+gpg_error_t g13_is_container (ctrl_t ctrl, const char *filename);
#endif /*G13_MOUNT_H*/
diff --git a/g13/mountinfo.c b/g13/mountinfo.c
new file mode 100644
index 000000000..100c1e475
--- /dev/null
+++ b/g13/mountinfo.c
@@ -0,0 +1,183 @@
+/* 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 <http://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 "utils.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. */
+};
+
+
+/* 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)
+{
+ 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->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 fucntion. */
+ 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)
+ {
+ 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\n",
+ idx, m->container, m->mountpoint, m->conttype, m->rid);
+}
+
diff --git a/g13/mountinfo.h b/g13/mountinfo.h
new file mode 100644
index 000000000..187dff0db
--- /dev/null
+++ b/g13/mountinfo.h
@@ -0,0 +1,40 @@
+/* mountinfo.h - 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef G13_MOUNTINFO_H
+#define G13_MOUNTINFO_H
+
+struct mounttable_s;
+typedef struct mounttable_s *mtab_t;
+
+gpg_error_t mountinfo_add_mount (const char *container,
+ const char *mountpoint,
+ int conttype, unsigned int rid);
+gpg_error_t mountinfo_del_mount (const char *container,
+ const char *mountpoint,
+ unsigned int rid);
+gpg_error_t mountinfo_find_mount (const char *container,
+ const char *mountpoint,
+ unsigned int *r_rid);
+
+void mountinfo_dump_all (void);
+
+
+#endif /*G13_MOUNTINFO_H*/
+
diff --git a/g13/runner.c b/g13/runner.c
index 27d03702a..6cf88c0b4 100644
--- a/g13/runner.c
+++ b/g13/runner.c
@@ -31,12 +31,13 @@
#include "keyblob.h"
#include "runner.h"
#include "../common/exechelp.h"
-
+#include "mountinfo.h"
/* The runner object. */
struct runner_s
{
- char *name; /* The name of this runner. */
+ char *name; /* The name of this runner. */
+ unsigned int identifier; /* The runner identifier. */
int spawned; /* True if runner_spawn has been called. */
pth_t threadid; /* The TID of the runner thread. */
@@ -131,12 +132,19 @@ runner_get_threads (void)
void
runner_release (runner_t runner)
{
+ gpg_error_t err;
+
if (!runner)
return;
if (!--runner->refcount)
return;
+ err = mountinfo_del_mount (NULL, NULL, runner->identifier);
+ if (err)
+ log_error ("failed to remove mount with rid %u from mtab: %s\n",
+ runner->identifier, gpg_strerror (err));
+
es_fclose (runner->status_fp);
if (runner->in_fd != -1)
close (runner->in_fd);
@@ -171,14 +179,32 @@ runner_release (runner_t runner)
gpg_error_t
runner_new (runner_t *r_runner, const char *name)
{
- runner_t runner;
+ static unsigned int namecounter; /* Global name counter. */
+ char *namebuffer;
+ runner_t runner, r;
*r_runner = NULL;
runner = xtrycalloc (1, sizeof *runner);
if (!runner)
return gpg_error_from_syserror ();
- runner->name = xtrystrdup (name? name: "[unknown]");
+
+ /* Bump up the namecounter. In case we ever had an overflow we
+ check that this number is currently not in use. The algorithm is
+ a bit lame but should be sufficient because such an wrap is not
+ very likely: Assuming that we do a mount 10 times a second, then
+ we would overwrap on a 32 bit system after 13 years. */
+ do
+ {
+ namecounter++;
+ for (r = running_threads; r; r = r->next_running)
+ if (r->identifier == namecounter)
+ break;
+ }
+ while (r);
+
+ runner->identifier = namecounter;
+ runner->name = namebuffer = xtryasprintf ("%s-%d", name, namecounter);
if (!runner->name)
{
xfree (runner);
@@ -189,13 +215,37 @@ runner_new (runner_t *r_runner, const char *name)
runner->in_fd = -1;
runner->out_fd = -1;
-
*r_runner = runner;
return 0;
}
-/* A runner usually maintaines two file descriptors to control the
+/* Return the identifier of RUNNER. */
+unsigned int
+runner_get_rid (runner_t runner)
+{
+ return runner->identifier;
+}
+
+
+/* Find a runner by its rid. Returns the runner object. The caller
+ must release the runner object. */
+runner_t
+runner_find_by_rid (unsigned int rid)
+{
+ runner_t r;
+
+ for (r = running_threads; r; r = r->next_running)
+ if (r->identifier == rid)
+ {
+ r->refcount++;
+ return r;
+ }
+ return NULL;
+}
+
+
+/* A runner usually maintains two file descriptors to control the
backend engine. This function is used to set these file
descriptors. The function takes ownership of these file
descriptors. IN_FD will be used to read from engine and OUT_FD to
@@ -382,8 +432,8 @@ runner_spawn (runner_t runner)
}
tattr = pth_attr_new ();
- pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
- pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
+ pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
+ pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 128*1024);
pth_attr_set (tattr, PTH_ATTR_NAME, runner->name);
tid = pth_spawn (tattr, runner_thread, runner);
diff --git a/g13/runner.h b/g13/runner.h
index 88ebc7d2d..e68eca03a 100644
--- a/g13/runner.h
+++ b/g13/runner.h
@@ -40,6 +40,12 @@ gpg_error_t runner_new (runner_t *r_runner, const char *name);
/* Free a runner object. */
void runner_release (runner_t runner);
+/* Return the identifier of RUNNER. */
+unsigned int runner_get_rid (runner_t runner);
+
+/* Find a runner by its rid. */
+runner_t runner_find_by_rid (unsigned int rid);
+
/* Functions to set properties of the runner. */
void runner_set_fds (runner_t runner, int in_fd, int out_fd);
diff --git a/g13/server.c b/g13/server.c
index bdf214f32..900dbc909 100644
--- a/g13/server.c
+++ b/g13/server.c
@@ -40,42 +40,28 @@ struct server_local_s
/* The Assuan contect we are working on. */
assuan_context_t assuan_ctx;
- char *mountpoint; /* Malloced current mountpoint. */
+ char *containername; /* Malloced active containername. */
};
-/* Cookie definition for assuan data line output. */
-static ssize_t data_line_cookie_write (void *cookie,
- const void *buffer, size_t size);
-static int data_line_cookie_close (void *cookie);
-static es_cookie_io_functions_t data_line_cookie_functions =
- {
- NULL,
- data_line_cookie_write,
- NULL,
- data_line_cookie_close
- };
-
-
-/* The filepointer for status message used in non-server mode. */
-/* static FILE *statusfp; FIXME; */
-
-
+/* Local prototypes. */
static int command_has_option (const char *cmd, const char *cmdopt);
-#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
+/*
+ Helper functions.
+ */
+/* Set an error and a description. */
+#define set_error(e,t) assuan_set_error (ctx, gpg_error (e), (t))
-
-/* Skip over options.
- Blanks after the options are also removed. */
+/* Skip over options. Blanks after the options are also removed. */
static char *
skip_options (const char *line)
{
@@ -93,52 +79,41 @@ skip_options (const char *line)
/* Check whether the option NAME appears in LINE. */
-static int
-has_option (const char *line, const char *name)
-{
- const char *s;
- int n = strlen (name);
+/* static int */
+/* has_option (const char *line, const char *name) */
+/* { */
+/* const char *s; */
+/* int n = strlen (name); */
- s = strstr (line, name);
- if (s && s >= skip_options (line))
- return 0;
- return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
-}
+/* s = strstr (line, name); */
+/* if (s && s >= skip_options (line)) */
+/* return 0; */
+/* return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n))); */
+/* } */
-/* A write handler used by es_fopencookie to write Assuan data
- lines. */
-static ssize_t
-data_line_cookie_write (void *cookie, const void *buffer, size_t size)
+/* Helper to print a message while leaving a command. */
+static gpg_error_t
+leave_cmd (assuan_context_t ctx, gpg_error_t err)
{
- assuan_context_t ctx = cookie;
-
- if (assuan_send_data (ctx, buffer, size))
+ if (err)
{
- errno = EIO;
- return -1;
+ const char *name = assuan_get_command_name (ctx);
+ if (!name)
+ name = "?";
+ if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
+ log_error ("command '%s' failed: %s\n", name,
+ gpg_strerror (err));
+ else
+ log_error ("command '%s' failed: %s <%s>\n", name,
+ gpg_strerror (err), gpg_strsource (err));
}
-
- return size;
+ return err;
}
-/* A close handler used by es_fopencookie to write Assuan data
- lines. */
-static int
-data_line_cookie_close (void *cookie)
-{
- assuan_context_t ctx = cookie;
-
- if (assuan_send_data (ctx, NULL, 0))
- {
- errno = EIO;
- return -1;
- }
-
- return 0;
-}
+
/* The handler for Assuan OPTION commands. */
static gpg_error_t
option_handler (assuan_context_t ctx, const char *key, const char *value)
@@ -146,6 +121,8 @@ option_handler (assuan_context_t ctx, const char *key, const char *value)
ctrl_t ctrl = assuan_get_pointer (ctx);
gpg_error_t err = 0;
+ (void)ctrl;
+
if (!strcmp (key, "putenv"))
{
/* Change the session's environment to be used for the
@@ -213,84 +190,83 @@ reset_notify (assuan_context_t ctx)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
- xfree (ctrl->server_local->mountpoint);
- ctrl->server_local->mountpoint = NULL;
+ xfree (ctrl->server_local->containername);
+ ctrl->server_local->containername = NULL;
assuan_close_input_fd (ctx);
assuan_close_output_fd (ctx);
}
-/* Helper to print a message while leaving a command. */
-static gpg_error_t
-leave_cmd (assuan_context_t ctx, gpg_error_t err)
-{
- if (err)
- {
- const char *name = assuan_get_command_name (ctx);
- if (!name)
- name = "?";
- if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
- log_error ("command '%s' failed: %s\n", name,
- gpg_strerror (err));
- else
- log_error ("command '%s' failed: %s <%s>\n", name,
- gpg_strerror (err), gpg_strsource (err));
- }
- return err;
-}
-
-
-/* RECIPIENT <userID>
+/* OPEN [options] <filename>
- FIXME - description.
- All RECIPIENT commands are cumulative until a RESET or an
- successful CREATE command.
+ Open the container FILENAME. FILENAME must be percent-plus
+ escaped. A quick check to see whether this is a suitable G13
+ container file is done. However no cryptographic check or any
+ other check is done. This command is used to define the target for
+ further commands. The filename is reset with the RESET command,
+ another OPEN or the CREATE command.
*/
static gpg_error_t
-cmd_recipient (assuan_context_t ctx, char *line)
+cmd_open (assuan_context_t ctx, char *line)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
- gpg_error_t err;
-
- (void)ctrl;
- err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
- /* err = gpgsm_add_to_certlist (ctrl, line, 0, */
- /* &ctrl->server_local->recplist, 0); */
- /* if (err) */
- /* { */
- /* gpgsm_status2 (ctrl, STATUS_INV_RECP, */
- /* get_inv_recpsgnr_code (rc), line, NULL); */
- /* } */
-
- return leave_cmd (ctx, err);
-}
+ gpg_error_t err = 0;
+ char *p, *pend;
+ size_t len;
+ /* In any case reset the active container. */
+ xfree (ctrl->server_local->containername);
+ ctrl->server_local->containername = NULL;
-/* SIGNER <userID>
+ /* Parse the line. */
+ line = skip_options (line);
+ for (p=line; *p && !spacep (p); p++)
+ ;
+ pend = p;
+ while (spacep(p))
+ p++;
+ if (*p || pend == line)
+ {
+ err = gpg_error (GPG_ERR_ASS_SYNTAX);
+ goto leave;
+ }
+ *pend = 0;
- FIXME - description.
- */
-static gpg_error_t
-cmd_signer (assuan_context_t ctx, char *line)
-{
- ctrl_t ctrl = assuan_get_pointer (ctx);
- gpg_error_t err;
+ /* Unescape the line and check for embedded Nul bytes. */
+ len = percent_plus_unescape_inplace (line, 0);
+ line[len] = 0;
+ if (!len || memchr (line, 0, len))
+ {
+ err = gpg_error (GPG_ERR_INV_NAME);
+ goto leave;
+ }
- (void)ctrl;
+ /* Do a basic check. */
+ err = g13_is_container (ctrl, line);
+ if (err)
+ goto leave;
- err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ /* Store the filename. */
+ ctrl->server_local->containername = xtrystrdup (line);
+ if (!ctrl->server_local->containername)
+ err = gpg_error_from_syserror ();
+
+
+ leave:
return leave_cmd (ctx, err);
}
-/* SETMOUNTPOINT [options] [<dirname>]
+/* MOUNT [options] [<mountpoint>]
- Set DIRNAME as the new mount point for future operations.
+ Mount the currently open file onto MOUNTPOINT. If MOUNTPOINT is
+ not given the system picks an unused mountpoint. MOUNTPOINT must
+ be percent-plus escaped to allow for arbitrary names.
*/
static gpg_error_t
-cmd_setmountpoint (assuan_context_t ctx, char *line)
+cmd_mount (assuan_context_t ctx, char *line)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
gpg_error_t err = 0;
@@ -319,40 +295,28 @@ cmd_setmountpoint (assuan_context_t ctx, char *line)
goto leave;
}
- xfree (ctrl->server_local->mountpoint);
- if (!len) /* Reset mountpoint. */
- ctrl->server_local->mountpoint = NULL;
- else
+ if (!ctrl->server_local->containername)
{
- ctrl->server_local->mountpoint = xtrystrdup (line);
- if (!ctrl->server_local->mountpoint)
- err = gpg_error_from_syserror ();
+ err = gpg_error (GPG_ERR_MISSING_ACTION);
+ goto leave;
}
- if (!err)
- log_debug ("mountpoint is now `%s'\n",
- ctrl->server_local->mountpoint
- ? ctrl->server_local->mountpoint: "[none]");
+ /* Perform the mount. */
+ err = g13_mount_container (ctrl, ctrl->server_local->containername,
+ *line? line : NULL);
leave:
return leave_cmd (ctx, err);
}
-/* MOUNT [options] <containername>
+/* UMOUNT [options] [<mountpoint>]
- Mount CONTAINERNAME onto the current mount point. CONTAINERNAME is
- the name of a file in the g13 format and must be percent-plus
- escaped to allow for arbitrary names. The mount poiunt must have
- been set already.
-
-
- A reason why we use a separate command for the mount point is to
- allow for longer filenames (an assuan command line is limited to
- ~1000 byte.
+ Unmount the currently open file or the one opened at MOUNTPOINT.
+ MOUNTPOINT must be percent-plus escaped.
*/
static gpg_error_t
-cmd_mount (assuan_context_t ctx, char *line)
+cmd_umount (assuan_context_t ctx, char *line)
{
ctrl_t ctrl = assuan_get_pointer (ctx);
gpg_error_t err = 0;
@@ -365,7 +329,7 @@ cmd_mount (assuan_context_t ctx, char *line)
pend = p;
while (spacep(p))
p++;
- if (*p || pend == line)
+ if (*p)
{
err = gpg_error (GPG_ERR_ASS_SYNTAX);
goto leave;
@@ -375,20 +339,89 @@ cmd_mount (assuan_context_t ctx, char *line)
/* Unescape the line and check for embedded Nul bytes. */
len = percent_plus_unescape_inplace (line, 0);
line[len] = 0;
- if (!len || memchr (line, 0, len))
+ if (memchr (line, 0, len))
{
err = gpg_error (GPG_ERR_INV_NAME);
goto leave;
}
-
- /* Perform the mount. */
- err = g13_mount_container (ctrl, line, ctrl->server_local->mountpoint);
+
+ /* Perform the unmount. */
+ err = g13_umount_container (ctrl, ctrl->server_local->containername,
+ *line? line : NULL);
leave:
return leave_cmd (ctx, err);
}
+
+/* RECIPIENT <userID>
+
+ FIXME - description.
+ All RECIPIENT commands are cumulative until a RESET or an
+ successful CREATE command.
+ */
+static gpg_error_t
+cmd_recipient (assuan_context_t ctx, char *line)
+{
+ ctrl_t ctrl = assuan_get_pointer (ctx);
+ gpg_error_t err;
+
+ (void)ctrl;
+ err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ /* err = gpgsm_add_to_certlist (ctrl, line, 0, */
+ /* &ctrl->server_local->recplist, 0); */
+ /* if (err) */
+ /* { */
+ /* gpgsm_status2 (ctrl, STATUS_INV_RECP, */
+ /* get_inv_recpsgnr_code (rc), line, NULL); */
+ /* } */
+
+ return leave_cmd (ctx, err);
+}
+
+
+/* SIGNER <userID>
+
+ FIXME - description.
+ */
+static gpg_error_t
+cmd_signer (assuan_context_t ctx, char *line)
+{
+ ctrl_t ctrl = assuan_get_pointer (ctx);
+ gpg_error_t err;
+
+ (void)ctrl;
+
+ err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ return leave_cmd (ctx, err);
+}
+
+
+/* CREATE [options] filename
+
+ Create a new container. On success the OPEN command is done
+ implictly for the new container.
+ */
+static gpg_error_t
+cmd_create (assuan_context_t ctx, char *line)
+{
+ ctrl_t ctrl = assuan_get_pointer (ctx);
+ gpg_error_t err;
+
+ (void)ctrl;
+
+ /* First we close the active container. */
+ xfree (ctrl->server_local->containername);
+ ctrl->server_local->containername = NULL;
+
+
+
+ err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ return leave_cmd (ctx, err);
+}
+
+
/* GETINFO <what>
Multipurpose function to return a variety of information.
@@ -476,10 +509,12 @@ register_commands (assuan_context_t ctx)
const char *name;
gpg_error_t (*handler)(assuan_context_t, char *line);
} table[] = {
+ { "OPEN", cmd_open },
+ { "MOUNT", cmd_mount },
+ { "UMOUNT", cmd_umount },
{ "RECIPIENT", cmd_recipient },
{ "SIGNER", cmd_signer },
- { "MOUNT", cmd_mount },
- { "SETMOUNTPOINT", cmd_setmountpoint },
+ { "CREATE", cmd_create },
{ "INPUT", NULL },
{ "OUTPUT", NULL },
{ "GETINFO", cmd_getinfo },