aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2012-10-07 20:12:34 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2012-10-07 20:12:34 +0300
commit1fbcbdb432e945aa3f63be5b9170e94a0c9ef6c3 (patch)
tree209822ff7ef7766b94a714438473dcf8f12c4e1f /lib
parentcabb35e68d34bcccaa39a223eaa037b335c81558 (diff)
downloadeclat-1fbcbdb432e945aa3f63be5b9170e94a0c9ef6c3.tar.gz
eclat-1fbcbdb432e945aa3f63be5b9170e94a0c9ef6c3.tar.bz2
Implement resource identifier mapping.
Resource identifier mapping permits to use more customized identifiers instead of the Amazon resource identifiers. For instance, you can use hostnames instead of the instance IDs, etc. * lib/Makefile.am: Add new files. * lib/filemap.c: New file. * lib/map.c: New file. * lib/libeclat.h (eclat_map_drv,eclat_map): New structs. (eclat_map_status): New enum. (eclat_map_init,eclat_map_lookup,eclat_map_config) (eclat_map_free,eclat_map_open,eclat_map_close) (eclat_map_get,eclat_map_strerror,eclat_map_drv_register) (eclat_map_foreach,eclat_map_free_all) (eclat_get_string_node): New protos. (eclat_map_drv_file): New extern. * src/accfile.c (access_file_lookup): Fix memory leak. * src/cmdline.opt: New option: --translate (-x) * src/config.c (eclat_kw) <map>: New block statement. (config_finish): Parse map configs. * src/asscaddr.c: Translate key. * src/dscrinstattr.c: Likewise. * src/dscrinsts.c: Likewise. * src/dscrinststat.c: Likewise. * src/dscrsecgrps.c: Likewise. * src/getconout.c: Likewise. * src/startinst.c: Likewise. * src/eclat.c (main): Initialize maps and free them when no more needed. * src/eclat.h (translate_option): New extern. (translate_ids): New proto. * src/util.c (translate_option): New variable. (translate_ids): New function.
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am7
-rw-r--r--lib/filemap.c140
-rw-r--r--lib/libeclat.h42
-rw-r--r--lib/map.c335
4 files changed, 523 insertions, 1 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 50b28a5..e7b9d20 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -16,6 +16,9 @@
noinst_LIBRARIES=libeclat.a
+maps = \
+ filemap.c
+
libeclat_a_SOURCES=\
base64.c\
diag.c\
@@ -26,6 +29,7 @@ libeclat_a_SOURCES=\
forlanlex.l\
hmac_sha1.c\
libeclat.h\
+ map.c\
q2url.c\
qaddparm.c\
qcreat.c\
@@ -35,7 +39,8 @@ libeclat_a_SOURCES=\
sha1.c\
sha1.h\
urlencode.c\
- xmltree.c
+ xmltree.c\
+ $(maps)
AM_LDFLAGS = $(CURL_LIBS)
INCLUDES = -I$(top_srcdir)/grecs/src/ $(CURL_CFLAGS)
diff --git a/lib/filemap.c b/lib/filemap.c
new file mode 100644
index 0000000..bced0d4
--- /dev/null
+++ b/lib/filemap.c
@@ -0,0 +1,140 @@
+/* This file is part of Eclat.
+ Copyright (C) 2012 Sergey Poznyakoff.
+
+ Eclat 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, or (at your option)
+ any later version.
+
+ Eclat 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 Eclat. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "libeclat.h"
+#include <errno.h>
+
+struct filemap {
+ char *name;
+ FILE *fp;
+ struct grecs_locus locus;
+};
+
+static int
+filemap_config(int dbg, struct grecs_node *node, void *data)
+{
+ struct filemap *filemap, **return_filemap = data;
+ const char *filename;
+ struct grecs_node *p;
+
+ if (eclat_get_string_node(node, "file", 0, &p))
+ return eclat_map_failure;
+ filemap = grecs_malloc(sizeof(*filemap));
+ filemap->name = grecs_strdup(p->v.value->v.string);
+ filemap->locus = p->locus;
+ *return_filemap = filemap;
+ return eclat_map_ok;
+}
+
+static void
+filemap_free(int dbg, void *data)
+{
+ struct filemap *filemap = data;
+ free(filemap->name);
+ free(filemap);
+}
+
+static int
+filemap_open(int dbg, void *data)
+{
+ struct filemap *filemap = data;
+
+ filemap->fp = fopen(filemap->name, "r");
+ if (!filemap->fp) {
+ grecs_error(&filemap->locus, errno, "cannot open file");
+ return eclat_map_failure;
+ }
+ return eclat_map_ok;
+}
+
+
+static int
+filemap_close(int dbg, void *data)
+{
+ struct filemap *filemap = data;
+ fclose(filemap->fp);
+ return eclat_map_ok;
+}
+
+static void
+skipline(FILE *fp)
+{
+ int c;
+
+ while ((c = getc(fp)) != EOF && c != '\n')
+ ;
+}
+
+static int
+filemap_get(int dbg, void *data, const char *key, char **return_value)
+{
+ struct filemap *filemap = data;
+ FILE *fp = filemap->fp;
+ int line = 0;
+ int rc, c;
+ const char *p;
+
+ rewind(fp);
+ while ((c = getc(fp)) != EOF) {
+ line++;
+ while (c != EOF && (c == ' ' || c == '\t'))
+ c = getc(fp);
+ if (c == '\n')
+ continue;
+ if (c == '#') {
+ skipline(fp);
+ continue;
+ }
+ if (c == EOF)
+ break;
+
+ for (p = key; c != EOF && c != ':' && *p == c; p++)
+ c = getc(fp);
+ if (c == EOF)
+ break;
+ if (c == '\n')
+ continue;
+ if (c == ':')
+ break;
+ skipline(fp);
+ }
+
+ if (c == ':') {
+ struct grecs_txtacc *acc;
+
+ debug(dbg, 2, ("%s:%d: found key", filemap->name, line));
+ acc = grecs_txtacc_create();
+ while ((c = getc(fp)) != EOF && c != '\n')
+ grecs_txtacc_grow_char(acc, c);
+ grecs_txtacc_grow_char(acc, 0);
+ *return_value = grecs_txtacc_finish(acc, 1);
+ grecs_txtacc_free(acc);
+ rc = eclat_map_ok;
+ } else
+ rc = eclat_map_not_found;
+
+ return rc;
+}
+
+struct eclat_map_drv eclat_map_drv_file = {
+ "file",
+ filemap_config,
+ filemap_open,
+ filemap_close,
+ filemap_get,
+ filemap_free
+};
+
diff --git a/lib/libeclat.h b/lib/libeclat.h
index 5f37cc9..1f16d5d 100644
--- a/lib/libeclat.h
+++ b/lib/libeclat.h
@@ -101,6 +101,48 @@ void eclat_partial_tree_data_handler(void *data, const XML_Char *s, int len);
void eclat_partial_tree_start_handler(void *data, const XML_Char *name,
const XML_Char **atts);
void eclat_partial_tree_end_handler(void *data, const XML_Char *name);
+
+#define ECLAT_MAP_OPEN 0x01
+
+struct eclat_map_drv {
+ const char *name;
+ int (*map_config)(int, struct grecs_node *, void *);
+ int (*map_open)(int, void *);
+ int (*map_close)(int, void *);
+ int (*map_get)(int, void *, const char *, char **);
+ void (*map_free)(int, void *);
+};
+struct eclat_map {
+ char *name;
+ char *keytrans;
+ struct eclat_map_drv *drv;
+ void *data;
+ int flags;
+};
+
+enum eclat_map_status {
+ eclat_map_ok,
+ eclat_map_failure,
+ eclat_map_not_found
+};
+void eclat_map_init(void);
+struct eclat_map *eclat_map_lookup(const char *name);
+int eclat_map_config(struct grecs_node *node, struct eclat_map **return_map);
+void eclat_map_free(struct eclat_map *map);
+int eclat_map_open(struct eclat_map *map);
+int eclat_map_close(struct eclat_map *map);
+int eclat_map_get(struct eclat_map *map, const char *key, char **value);
+const char *eclat_map_strerror(int rc);
+int eclat_map_drv_register(struct eclat_map_drv *drv);
+void eclat_map_foreach(int (*fun)(struct eclat_map *, void *), void *data);
+void eclat_map_free_all(void);
+
+int eclat_get_string_node(struct grecs_node *node, const char *name,
+ int optional,
+ struct grecs_node **pret);
+
+extern struct eclat_map_drv eclat_map_drv_file;
+
diff --git a/lib/map.c b/lib/map.c
new file mode 100644
index 0000000..5a8d2fd
--- /dev/null
+++ b/lib/map.c
@@ -0,0 +1,335 @@
+/* This file is part of Eclat.
+ Copyright (C) 2012 Sergey Poznyakoff.
+
+ Eclat 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, or (at your option)
+ any later version.
+
+ Eclat 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 Eclat. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "libeclat.h"
+#include "wordsplit.h"
+#include <sysexits.h>
+#include <string.h>
+
+static int map_dbg = -1;
+static struct grecs_symtab *openmap_symtab, *mapdrv_symtab;
+
+void
+eclat_map_init()
+{
+ map_dbg = debug_register("map");
+}
+
+int
+eclat_get_string_node(struct grecs_node *node, const char *name,
+ int optional,
+ struct grecs_node **pret)
+{
+ struct grecs_node *p = grecs_find_node(node->down, name);
+
+ if (!p) {
+ if (optional)
+ return eclat_map_not_found;
+ grecs_error(&node->locus, 0,
+ "no \"%s\" statement found", name);
+ return eclat_map_failure;
+ }
+
+ if (p->type != grecs_node_stmt) {
+ grecs_error(&p->locus, 0, "must be simple statement");
+ return eclat_map_failure;
+ }
+
+ if (p->v.value->type != GRECS_TYPE_STRING) {
+ grecs_error(&p->locus, 0, "must be scalar");
+ return eclat_map_failure;
+ }
+
+ *pret = p;
+ return eclat_map_ok;
+}
+
+static int
+drv_copy(void *a, void *b)
+{
+ struct eclat_map_drv *drva = a;
+ struct eclat_map_drv *drvb = b;
+
+ *drva = *drvb;
+ drva->name = strdup(drvb->name);
+ return drva->name == NULL;
+}
+
+int
+eclat_map_drv_register(struct eclat_map_drv *drv)
+{
+ struct eclat_map_drv *p;
+ int install;
+
+ if (!mapdrv_symtab) {
+ mapdrv_symtab = grecs_symtab_create(sizeof(*drv),
+ NULL,
+ NULL,
+ drv_copy,
+ NULL,
+ NULL);
+ if (!mapdrv_symtab)
+ grecs_alloc_die();
+ }
+ install = 1;
+ if (!grecs_symtab_lookup_or_install(mapdrv_symtab, drv, &install))
+ die(EX_SOFTWARE, "cannot install map");
+ return install ? eclat_map_ok : eclat_map_failure;
+}
+
+struct eclat_map *
+eclat_map_lookup(const char *name)
+{
+ struct eclat_map key;
+
+ if (!openmap_symtab)
+ return NULL;
+ key.name = (char*) name;
+ return grecs_symtab_lookup_or_install(openmap_symtab, &key, NULL);
+}
+
+static void
+map_free(void *p)
+{
+ struct eclat_map *map = p;
+ if (map->flags & ECLAT_MAP_OPEN)
+ eclat_map_close(map);
+ if (map->data && map->drv->map_free)
+ map->drv->map_free(map_dbg, map->data);
+ free(map->name);
+ free(map->keytrans);
+ free(map);
+}
+
+int
+eclat_map_config(struct grecs_node *node, struct eclat_map **return_map)
+{
+ char *mapname;
+ struct grecs_node *p;
+ struct eclat_map key, *map;
+ struct eclat_map_drv dkey, *drv;
+ int install, rc;
+
+ if (node->v.value->type != GRECS_TYPE_STRING) {
+ grecs_error(&p->locus, 0, "value must be scalar");
+ return eclat_map_failure;
+ }
+
+ mapname = node->v.value->v.string;
+
+ if (debug_level(map_dbg) > 1)
+ diag(&node->locus, "debug", "configuring map \"%s\"",
+ mapname);
+ map = eclat_map_lookup(mapname);
+ if (map) {
+ debug(map_dbg, 1,
+ ("map \"%s\" already configured", mapname));
+ *return_map = map;
+ return eclat_map_ok;
+ }
+
+ if (eclat_get_string_node(node, "type", 0, &p))
+ return eclat_map_failure;
+
+ dkey.name = p->v.value->v.string;
+ if (!mapdrv_symtab) {
+ grecs_error(&p->locus, 0, "no drivers compiled");
+ return eclat_map_failure;
+ }
+
+ drv = grecs_symtab_lookup_or_install(mapdrv_symtab, &dkey, NULL);
+ if (!drv) {
+ grecs_error(&p->locus, 0, "no driver for this type");
+ return eclat_map_failure;
+ }
+
+ if (!openmap_symtab) {
+ openmap_symtab = grecs_symtab_create(sizeof(key),
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ map_free);
+ if (!openmap_symtab)
+ grecs_alloc_die();
+ }
+ install = 1;
+ key.name = (char*) mapname;
+ map = grecs_symtab_lookup_or_install(openmap_symtab, &key, &install);
+ if (!map)
+ die(EX_SOFTWARE, "cannot install map");
+ map->drv = drv;
+
+ rc = drv->map_config(map_dbg, node, &map->data);
+ if (rc != eclat_map_ok) {
+ grecs_error(&node->locus, 0, "map configration failed");
+ eclat_map_free(map);
+ return eclat_map_failure;
+ }
+
+ if (eclat_get_string_node(node, "key", 1, &p) == 0)
+ map->keytrans = grecs_strdup(p->v.value->v.string);
+
+ debug(map_dbg, 1, ("map \"%s\" configured", mapname));
+
+ *return_map = map;
+ return eclat_map_ok;
+}
+
+void
+eclat_map_free(struct eclat_map *map)
+{
+ grecs_symtab_remove(openmap_symtab, map);
+}
+
+int
+eclat_map_open(struct eclat_map *map)
+{
+ debug(map_dbg, 1, ("opening map \"%s\"", map->name));
+
+ if (map->flags & ECLAT_MAP_OPEN) {
+ debug(map_dbg, 1, ("map \"%s\" already open", map->name));
+ return eclat_map_ok;
+ }
+
+ if (map->drv->map_open(map_dbg, map->data)) {
+ err("failed to open map %s", map->name);
+ return eclat_map_failure;
+ }
+
+ debug(map_dbg, 1, ("map \"%s\" opened successfully", map->name));
+ map->flags |= ECLAT_MAP_OPEN;
+ return eclat_map_ok;
+}
+
+int
+eclat_map_close(struct eclat_map *map)
+{
+ int rc = eclat_map_ok;
+
+ debug(map_dbg, 1, ("closing map \"%s\"", map->name));
+ if (!(map->flags & ECLAT_MAP_OPEN)) {
+ debug(map_dbg, 1, ("map \"%s\" not open", map->name));
+ return eclat_map_ok;
+ }
+ if (map->drv->map_close)
+ rc = map->drv->map_close(map_dbg, map->data);
+
+ if (rc == eclat_map_ok) {
+ debug(map_dbg, 1,
+ ("map \"%s\" closed successfully", map->name));
+ map->flags &= ~ECLAT_MAP_OPEN;
+ } else
+ err("failed to close map %s", map->name);
+
+ return rc;
+}
+
+int
+eclat_map_get(struct eclat_map *map, const char *key, char **value)
+{
+ int rc;
+ struct wordsplit ws;
+
+ debug(map_dbg, 1,
+ ("looking up \"%s\" in map \"%s\"", key, map->name));
+ if (!(map->flags & ECLAT_MAP_OPEN)) {
+ debug(map_dbg, 1, ("map \"%s\" not open", map->name));
+ return eclat_map_failure;
+ }
+
+ if (map->keytrans) {
+ const char *kve[5];
+ kve[0] = "key";
+ kve[1] = key;
+ kve[2] = "map";
+ kve[3] = map->name;
+ kve[4] = NULL;
+
+ ws.ws_env = kve;
+
+ if (wordsplit(map->keytrans, &ws,
+ WRDSF_NOSPLIT | WRDSF_NOCMD |
+ WRDSF_ENV | WRDSF_ENV_KV))
+ die(EX_SOFTWARE, "error transforming key: %s",
+ wordsplit_strerror(&ws));
+ debug(map_dbg, 1,
+ ("transformed key \"%s\" => \"%s\"",
+ key, ws.ws_wordv[0]));
+ key = ws.ws_wordv[0];
+ }
+
+ rc = map->drv->map_get(map_dbg, map->data, key, value);
+
+ if (map->keytrans)
+ wordsplit_free(&ws);
+
+ debug(map_dbg, 1, ("result: \"%s\"", eclat_map_strerror(rc)));
+ if (rc == eclat_map_ok)
+ debug(map_dbg, 2, ("found value: \"%s\"", *value));
+ return rc;
+}
+
+const char *
+eclat_map_strerror(int rc)
+{
+ switch (rc) {
+ case eclat_map_ok:
+ return "success";
+ case eclat_map_failure:
+ return "failure";
+ case eclat_map_not_found:
+ return "not found";
+ }
+ return "unknown error";
+}
+
+struct foreach_closure {
+ int (*fun)(struct eclat_map *, void *);
+ void *data;
+};
+
+static int
+map_foreach(void *item, void *data)
+{
+ struct eclat_map *map = item;
+ struct foreach_closure *cp = data;
+
+ return cp->fun(map, cp->data);
+}
+
+void
+eclat_map_foreach(int (*fun)(struct eclat_map *, void *), void *data)
+{
+ struct foreach_closure cl;
+
+ if (!openmap_symtab)
+ return;
+
+ cl.fun = fun;
+ cl.data = data;
+ grecs_symtab_enumerate(openmap_symtab, map_foreach, &cl);
+}
+
+void
+eclat_map_free_all()
+{
+ if (openmap_symtab) {
+ grecs_symtab_free(openmap_symtab);
+ openmap_symtab = NULL;
+ }
+}
+

Return to:

Send suggestions and report system problems to the System administrator.