Introduction
Introduction Statistics Contact Development Disclaimer Help
Replaced the SAX parser with DOM + XPath. Added RelaxNG schema validation of th…
git clone git://git.codemadness.org/susmb
Log
Files
Refs
README
LICENSE
---
commit 3f2aa4880ce666e10ff6bafe46d4041e7e49fe8b
parent d83453ae77a122ee32d410edd113b6915252e9df
Author: geoff <devnull@localhost>
Date: Tue, 2 Jan 2007 22:19:03 +0000
Replaced the SAX parser with DOM + XPath.
Added RelaxNG schema validation of the configuration file.
Made domain and mount options elements optional.
Diffstat:
M Makefile | 14 ++++++++++----
M conffile.c | 204 +++++++++++++++++------------…
M conffile.h | 41 ++++++++---------------------…
A config.rng | 46 +++++++++++++++++++++++++++++…
M doc/README | 1 +
D doc/sax_model.mdzip | 0
D doc/sax_state_machine.png | 0
M options.c | 8 ++++----
M options.h | 4 ++--
D sax.c | 720 -----------------------------…
D sax.h | 27 ---------------------------
M usmb.c | 88 ++++++++---------------------…
M usmb.h | 2 +-
M usmb_dir.c | 2 +-
M usmb_dir.h | 2 +-
M usmb_file.c | 2 +-
M usmb_file.h | 2 +-
M utils.c | 2 +-
M utils.h | 2 +-
M version.c | 4 ++--
M version.h | 4 ++--
A xml.c | 158 +++++++++++++++++++++++++++++…
A xml.h | 35 +++++++++++++++++++++++++++++…
23 files changed, 410 insertions(+), 958 deletions(-)
---
diff --git a/Makefile b/Makefile
@@ -1,5 +1,5 @@
# usmb - mount SMB shares via FUSE and Samba
-# Copyright (C) 2006 Geoff Johnstone
+# Copyright (C) 2006-2007 Geoff Johnstone
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -36,8 +36,8 @@ CFLAGS += $(shell pkg-config --cflags $(PACKAGES))
LDLIBS += $(shell pkg-config --libs-only-l $(PACKAGES))
LDFLAGS += $(shell pkg-config --libs-only-L $(PACKAGES))
-SOURCES = conffile.c options.c sax.c usmb.c usmb_dir.c usmb_file.c utils.c \
- version.c
+SOURCES = conffile.c options.c usmb.c usmb_dir.c usmb_file.c utils.c \
+ version.c xml.c
OBJECTS = $(SOURCES:.c=.o)
PROGRAM = usmb
@@ -45,6 +45,12 @@ PROGRAM = usmb
all: $(PROGRAM)
+conffile.c: config.rng.h
+config.rng.h: config.rng
+ sed -e 's/"/\\"/g' -e 's/\(.*\)/ "\1" \\/' \
+ -e '1istatic const char *rng_$(^:.rng=) =' $^ > config.rng.h
+ echo ' "";' >> config.rng.h
+
debug: CFLAGS += -ggdb -DDEBUG
debug: all
@@ -58,7 +64,7 @@ clean:
distclean: clean
- $(RM) core usmb-*.tar.bz2 usmb-*.tar.gz doc/*.mdzip.bak
+ $(RM) core usmb-*.tar.bz2 usmb-*.tar.gz doc/*.mdzip.bak config.rng.h
install-strip: STRIPFLAGS = -s
diff --git a/conffile.c b/conffile.c
@@ -1,5 +1,5 @@
/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
+ * Copyright (C) 2006-2007 Geoff Johnstone
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,17 +17,18 @@
*/
#include <assert.h>
-#include <glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "conffile.h"
#include "utils.h"
+#include "xml.h"
+#include "config.rng.h"
struct conffile {
- GHashTable *credentials;
- GHashTable *mounts;
+ xmlDocPtr doc;
+ xmlXPathContextPtr ctx;
};
@@ -40,17 +41,9 @@ struct credentials * credentials_new (const char *domain,
if (NULL == creds)
return NULL;
- creds->domain = xstrdup (domain);
- creds->username = xstrdup (username);
- creds->password = xstrdup (password);
-
- if ((NULL == creds->domain) ||
- (NULL == creds->username) ||
- (NULL == creds->password))
- {
- credentials_destroy (creds);
- creds = NULL;
- }
+ creds->domain = domain;
+ creds->username = username;
+ creds->password = password;
return creds;
}
@@ -59,11 +52,6 @@ struct credentials * credentials_new (const char *domain,
void credentials_destroy (struct credentials *creds)
{
assert (creds != NULL);
-
- xfree (creds->password);
- xfree (creds->username);
- xfree (creds->domain);
-
free (creds);
}
@@ -80,21 +68,12 @@ struct mount * mount_new (const char *server, const char *s…
if (NULL == mount)
return NULL;
- mount->server = xstrdup (server);
- mount->share = xstrdup (share);
- mount->mountpoint = xstrdup (mountpoint);
- mount->options = xstrdup (options);
+ mount->server = server;
+ mount->share = share;
+ mount->mountpoint = mountpoint;
+ mount->options = options;
mount->credentials = credentials;
- if ((NULL == mount->server) ||
- (NULL == mount->share) ||
- (NULL == mount->mountpoint) ||
- (NULL == mount->options))
- {
- mount_destroy (mount);
- mount = NULL;
- }
-
return mount;
}
@@ -102,35 +81,50 @@ struct mount * mount_new (const char *server, const char *…
void mount_destroy (struct mount *mount)
{
assert (NULL != mount);
-
- xfree (mount->options);
- xfree (mount->mountpoint);
- xfree (mount->share);
- xfree (mount->server);
-
free (mount);
}
-struct conffile * conffile_new (void)
+struct conffile * conffile_new (const char *filename)
{
- struct conffile *cf = malloc (sizeof (struct conffile));
-
- if (NULL == cf)
+ xmlDocPtr doc;
+ xmlXPathContextPtr ctx;
+ struct conffile *cf;
+
+ doc = xmlParseFile (filename);
+ if (NULL == doc)
+ {
+ fprintf (stderr, "Cannot parse %s\n", filename);
return NULL;
+ }
+ if (!xml_validate_relaxng (doc, rng_config))
+ {
+ fprintf (stderr, "%s isn't a valid USMB configuration\n", filename);
+ xmlFreeDoc (doc);
+ return NULL;
+ }
- cf->credentials = g_hash_table_new_full (g_str_hash, g_str_equal, free,
- (GDestroyNotify)credentials_destroy…
- cf->mounts = g_hash_table_new_full (g_str_hash, g_str_equal,
- free, (GDestroyNotify)mount_destroy);
+ ctx = xmlXPathNewContext (doc);
+ if (NULL == ctx)
+ {
+ fputs ("Cannot create XPath context\n", stderr);
+ xmlFreeDoc (doc);
+ return NULL;
+ }
+
+ cf = malloc (sizeof (struct conffile));
- if ((NULL == cf->credentials) || (NULL == cf->mounts))
+ if (NULL == cf)
{
- conffile_destroy (cf);
- cf = NULL;
+ xmlXPathFreeContext (ctx);
+ xmlFreeDoc (doc);
+ return NULL;
}
+ cf->doc = doc;
+ cf->ctx = ctx;
+
return cf;
}
@@ -139,69 +133,93 @@ void conffile_destroy (struct conffile *cf)
{
assert (NULL != cf);
- if (NULL != cf->mounts)
- g_hash_table_destroy (cf->mounts);
-
- if (NULL != cf->credentials)
- g_hash_table_destroy (cf->credentials);
-
+ xmlXPathFreeContext (cf->ctx);
+ xmlFreeDoc (cf->doc);
free (cf);
}
-bool conffile_add_mount (struct conffile *cf, char *key, struct mount *mount)
+struct mount * conffile_get_mount (struct conffile *cf, const char *key)
{
+ char xpath[2048];
+ char *creds = NULL;
+ void *server = NULL, *share = NULL, *mountpoint = NULL, *options = NULL;
+ void *domain = NULL, *username = NULL, *password = NULL;
+ bool ok = true;
+ struct credentials *credentials = NULL;
+ struct mount *ret = NULL;
+
assert (NULL != cf);
assert (NULL != key);
- assert (NULL != mount);
- DEBUG (fprintf (stderr, "add_mount (%s)\n", key));
+ if (strchr (key, '\''))
+ return NULL;
- if (NULL != g_hash_table_lookup (cf->mounts, key))
- {
- fprintf (stderr, "Duplicate mount name: %s\n", key);
- return false;
- }
+ snprintf (xpath, sizeof (xpath),
+ "/usmbconfig/mount[@id='%s']/server/text()", key);
+ xml_xpath_text (cf->ctx, BAD_CAST xpath, (void *)&server) || (ok = false);
- g_hash_table_insert (cf->mounts, key, mount);
- return true;
-}
+ snprintf (xpath, sizeof (xpath),
+ "/usmbconfig/mount[@id='%s']/share/text()", key);
+ xml_xpath_text (cf->ctx, BAD_CAST xpath, (void *)&share) || (ok = false);
+ snprintf (xpath, sizeof (xpath),
+ "/usmbconfig/mount[@id='%s']/mountpoint/text()", key);
+ xml_xpath_text (cf->ctx, BAD_CAST xpath, (void *)&mountpoint) || (ok = false…
-bool conffile_add_credentials (struct conffile *cf, char *key,
- struct credentials *credentials)
-{
- assert (NULL != cf);
- assert (NULL != key);
- assert (NULL != credentials);
-
- DEBUG (fprintf (stderr, "add_credentials (%s)\n", key));
+ snprintf (xpath, sizeof (xpath), "/usmbconfig/mount[@id='%s']", key);
+ xml_xpath_attr_value (cf->ctx, BAD_CAST xpath, BAD_CAST "credentials",
+ (xmlChar **)&creds) || (ok = false);
- if (NULL != g_hash_table_lookup (cf->credentials, key))
+ if (!ok)
{
- fprintf (stderr, "Duplicate credentials name: %s\n", key);
- return false;
+ xfree (creds);
+ xfree (mountpoint);
+ xfree (share);
+ xfree (server);
+
+ return NULL;
}
- g_hash_table_insert (cf->credentials, key, credentials);
- return true;
-}
+ snprintf (xpath, sizeof (xpath),
+ "/usmbconfig/credentials[@id='%s']/domain/text()", creds);
+ (void)xml_xpath_text (cf->ctx, BAD_CAST xpath, (void *)&domain);
+ snprintf (xpath, sizeof (xpath),
+ "/usmbconfig/credentials[@id='%s']/username/text()", creds);
+ xml_xpath_text (cf->ctx, BAD_CAST xpath, (void *)&username) || (ok = false);
-struct mount * conffile_get_mount (struct conffile *cf, const char *key)
-{
- assert (NULL != cf);
- assert (NULL != key);
+ snprintf (xpath, sizeof (xpath),
+ "/usmbconfig/credentials[@id='%s']/password/text()", creds);
+ xml_xpath_text (cf->ctx, BAD_CAST xpath, (void *)&password) || (ok = false);
- return g_hash_table_lookup (cf->mounts, key);
-}
+ if (ok)
+ {
+ credentials = credentials_new (domain, username, password);
+ if (NULL != credentials)
+ {
+ ret = mount_new (server, share, mountpoint, credentials, options);
+ ok = (NULL != ret);
+ }
+ }
-struct credentials * conffile_get_credentials (struct conffile *cf,
- const char *key)
-{
- assert (NULL != cf);
- assert (NULL != key);
+ if (!ok)
+ {
+ if (NULL != credentials)
+ credentials_destroy (credentials);
- return g_hash_table_lookup (cf->credentials, key);
+ xfree (password);
+ xfree (domain);
+ xfree (username);
+ xfree (creds);
+ xfree (mountpoint);
+ xfree (share);
+ xfree (server);
+
+ return NULL;
+ }
+
+ return ret;
}
+
diff --git a/conffile.h b/conffile.h
@@ -1,5 +1,5 @@
/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
+ * Copyright (C) 2006-2007 Geoff Johnstone
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,49 +22,28 @@
#include <stdbool.h>
struct credentials {
- char *domain;
- char *username;
- char *password;
+ const char *domain;
+ const char *username;
+ const char *password;
};
struct mount {
- char *server;
- char *share;
- char *mountpoint;
+ const char *server;
+ const char *share;
+ const char *mountpoint;
const struct credentials *credentials;
- char *options;
+ const char *options;
};
struct conffile;
- struct credentials * credentials_new (const char *domain,
- const char *username,
- const char *password);
-
- void credentials_destroy (struct credentials *creds);
-
- struct mount * mount_new (const char *server, const char *share,
- const char *mountpoint,
- const struct credentials *credentials,
- const char *options);
-
- void mount_destroy (struct mount *mount);
-
- struct conffile * conffile_new (void);
-
+ struct conffile * conffile_new (const char *filename);
void conffile_destroy (struct conffile *cf);
- bool conffile_add_mount (struct conffile *cf, char *key, struct mount *mount…
-
- bool conffile_add_credentials (struct conffile *cf, char *key,
- struct credentials *credentials);
-
struct mount * conffile_get_mount (struct conffile *cf, const char *key);
-
- struct credentials * conffile_get_credentials (struct conffile *cf,
- const char *key);
+ void mount_destroy (struct mount *mount);
#endif
diff --git a/config.rng b/config.rng
@@ -0,0 +1,46 @@
+<grammar xmlns="http://relaxng.org/ns/structure/1.0">
+
+ <start>
+ <ref name="usmbconfig" />
+ </start>
+
+
+ <define name="usmbconfig">
+ <element name="usmbconfig">
+ <zeroOrMore>
+ <choice>
+ <ref name="credentials" />
+ <ref name="mount" />
+ </choice>
+ </zeroOrMore>
+ </element>
+ </define>
+
+
+ <define name="credentials">
+ <element name="credentials">
+ <attribute name="id" />
+ <optional>
+ <element name="domain"> <text /> </element>
+ </optional>
+ <element name="username"> <text /> </element>
+ <element name="password"> <text /> </element>
+ </element>
+ </define>
+
+
+ <define name="mount">
+ <element name="mount">
+ <attribute name="id" />
+ <attribute name="credentials" />
+ <element name="server"> <text /> </element>
+ <element name="share"> <text /> </element>
+ <element name="mountpoint"> <text /> </element>
+ <optional>
+ <element name="options"> <text /> </element>
+ </optional>
+ </element>
+ </define>
+
+</grammar>
+
diff --git a/doc/README b/doc/README
@@ -43,6 +43,7 @@ Installation
------------
Sorry, no autoconf yet.
+You need GNU sed.
Edit the Makefile with brain engaged.
Run make.
Run make install (maybe as root).
diff --git a/doc/sax_model.mdzip b/doc/sax_model.mdzip
Binary files differ.
diff --git a/doc/sax_state_machine.png b/doc/sax_state_machine.png
Binary files differ.
diff --git a/options.c b/options.c
@@ -1,5 +1,5 @@
/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
+ * Copyright (C) 2006-2007 Geoff Johnstone
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -133,7 +133,7 @@ bool parse_args (int *argc, char ***argv,
* mount point
*/
#define MAXARGS 12
-void build_fuse_args (char *options, char *mountpoint,
+void build_fuse_args (const char *options, const char *mountpoint,
int *out_argc, char ***out_argv)
{
assert (NULL != mountpoint);
@@ -159,10 +159,10 @@ void build_fuse_args (char *options, char *mountpoint,
if ((NULL != options) && ('\0' != options[0]))
{
argv[argc++] = "-o";
- argv[argc++] = options;
+ argv[argc++] = (char *)options;
}
- argv[argc++] = mountpoint;
+ argv[argc++] = (char *)mountpoint;
argv[argc] = NULL; // for good measure...
assert (argc < MAXARGS);
diff --git a/options.h b/options.h
@@ -1,5 +1,5 @@
/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
+ * Copyright (C) 2006-2007 Geoff Johnstone
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
bool parse_args (int *argc, char ***argv,
const char **mountid, const char **out_conffile);
- void build_fuse_args (char *options, char *mountpoint,
+ void build_fuse_args (const char *options, const char *mountpoint,
int *out_argc, char ***out_argv);
#endif
diff --git a/sax.c b/sax.c
@@ -1,720 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
- *
- * This program 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 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <assert.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-#include <libxml/xmlreader.h>
-#include <glib.h>
-#include "conffile.h"
-#include "sax.h"
-#include "utils.h"
-
-
-/* Configuration file format
- * -------------------------
- *
- * usmbconfig section
- * Any number of credentials and mount sections
- *
- * credentials section
- * domain
- * username
- * password
- *
- * mount section
- * server
- * share
- * mountpoint
- * options
- *
- * Example:
- * <usmbconfig>
- *
- * <credentials id="workgroup">
- * <domain>WORKGROUP</domain>
- * <username>user</username>
- * <password>password</password>
- * </credentials>
- *
- * <mount id="home" credentials="workgroup">
- * <server>127.0.0.1</server>
- * <share>home</share>
- * <mountpoint>/tmp/smb</mountpoint>
- * <options>readonly</options>
- * </mount>
- *
- * </usmbconfig>
- */
-
-
-/* SAX state machine
- * -----------------
- *
- * See doc/sax_state_machine.png or the MagicDraw model doc/sax_model.mdzip.
- */
-
-
-enum sax_state {
- START,
- INITIAL,
- USMBCFG,
- DONE,
- FINISH,
- CREDS,
- MOUNT,
- SERVER,
- SHARE,
- MOUNTPT,
- OPTIONS,
- DOMAIN,
- USER,
- PASS,
- ERROR
-};
-
-
-enum element {
- ELT_USMBCFG,
- ELT_CREDS,
- ELT_DOMAIN,
- ELT_USER,
- ELT_PASS,
- ELT_MOUNT,
- ELT_SERVER,
- ELT_SHARE,
- ELT_MOUNTPT,
- ELT_OPTIONS,
- ELT_UNKNOWN
-};
-
-
-// passed as the ctx pointer into SAX callbacks
-struct sax_parser {
- enum sax_state state;
-
- union {
- struct {
- char *id;
-
- bool got_domain;
- bool got_username;
- bool got_password;
-
- GString *domain;
- GString *username;
- GString *password;
- } credentials;
-
- struct {
- char *id;
- struct credentials *creds;
-
- bool got_server;
- bool got_share;
- bool got_mountpoint;
- bool got_options;
-
- GString *server;
- GString *share;
- GString *mountpoint;
- GString *options;
- } mount;
- } strs;
-
- struct conffile *cf;
-};
-
-
-static enum element get_element (const char *elt)
-{
- const char *elts[] = {
- [ ELT_USMBCFG ] = "usmbconfig",
- [ ELT_CREDS ] = "credentials",
- [ ELT_DOMAIN ] = "domain",
- [ ELT_USER ] = "username",
- [ ELT_PASS ] = "password",
- [ ELT_MOUNT ] = "mount",
- [ ELT_SERVER ] = "server",
- [ ELT_SHARE ] = "share",
- [ ELT_MOUNTPT ] = "mountpoint",
- [ ELT_OPTIONS ] = "options"
- };
-
- for (size_t i = 0; i < sizeof (elts) / sizeof (elts[0]); ++i)
- if (!strcmp (elt, elts[i]))
- return i;
-
- return ELT_UNKNOWN;
-}
-
-
-static void start_document (void *ctx)
-{
- struct sax_parser *sp = ctx;
- assert (sp->state == START);
- sp->state = INITIAL;
-}
-
-
-static void end_document (void *ctx)
-{
- struct sax_parser *sp = ctx;
-
- if (ERROR == sp->state)
- return;
-
- if (sp->state != DONE)
- {
- fputs ("Unexpected end of configuration file\n", stderr);
- sp->state = ERROR;
- }
-
- sp->state = FINISH;
-}
-
-
-static void error (void *ctx, const char *msg, ...)
-{
- struct sax_parser *sp = ctx;
-
- if (ERROR == sp->state)
- return;
-
- va_list ap;
-
- fputs ("Parse error: ", stderr);
- va_start (ap, msg);
- vfprintf (stderr, msg ,ap);
- va_end (ap);
- sp->state = ERROR;
-}
-
-
-typedef void * (* cf_get_fn) (struct conffile *, const char *);
-static bool handle_id (char **out, const char *in, cf_get_fn func,
- struct conffile *cf)
-{
- assert (NULL != out);
- assert (NULL != in);
-
- if (NULL != *out)
- {
- fprintf (stderr,
- "Multiple ID attributes in <mount> or <credentials>: %s\n", in);
- return false;
- }
-
- if (NULL != func (cf, in))
- {
- fprintf (stderr, "Duplicate ID: %s\n", in);
- return false;
- }
-
- *out = xstrdup (in);
-
- if (NULL == *out)
- {
- fputs ("Out of memory\n", stderr);
- return false;
- }
-
- return true;
-}
-
-
-static void start_mount (struct sax_parser *sp, const xmlChar **attrs)
-{
- sp->strs.mount.id = NULL;
- sp->strs.mount.creds = NULL;
-
- // must have id and credentials attributes
- for (int i = 0; NULL != attrs[i]; i += 2)
- {
- assert (NULL != attrs[i+1]);
-
- if (!strcmp (attrs[i], "id"))
- {
- if (!handle_id (&sp->strs.mount.id, (const char *)attrs[i+1],
- (cf_get_fn)conffile_get_mount, sp->cf))
- {
- sp->state = ERROR;
- return;
- }
- }
-
- else if (!strcmp (attrs[i], "credentials"))
- {
- if (NULL != sp->strs.mount.creds)
- {
- fputs ("Duplicate credentials attribute in <mount>\n", stderr);
- sp->state = ERROR;
- return;
- }
-
- sp->strs.mount.creds =
- conffile_get_credentials (sp->cf, (const char *)attrs[i+1]);
-
- if (NULL == sp->strs.mount.creds)
- {
- fprintf (stderr, "Credentials %s not found for <mount>\n", attrs[i+1]);
- sp->state = ERROR;
- return;
- }
- }
-
- else
- {
- fprintf (stderr, "Unrecognised <mount> attribute %s\n", attrs[i]);
- sp->state = ERROR;
- return;
- }
- }
-
- if ((NULL == sp->strs.mount.id) ||
- (NULL == sp->strs.mount.creds))
- {
- fputs ("<mount> must have id and credentials attributes\n", stderr);
- sp->state = ERROR;
- return;
- }
-
- sp->strs.mount.server = g_string_new (NULL);
- sp->strs.mount.share = g_string_new (NULL);
- sp->strs.mount.mountpoint = g_string_new (NULL);
- sp->strs.mount.options = g_string_new (NULL);
-
- sp->strs.mount.got_server = false;
- sp->strs.mount.got_share = false;
- sp->strs.mount.got_mountpoint = false;
- sp->strs.mount.got_options = false;
-
- sp->state = MOUNT;
-}
-
-
-static void start_creds (struct sax_parser *sp, const xmlChar **attrs)
-{
- assert (NULL == sp->strs.credentials.domain);
- assert (NULL == sp->strs.credentials.username);
- assert (NULL == sp->strs.credentials.password);
-
- sp->strs.credentials.id = NULL;
-
- // must have an id attribute
- for (int i = 0; NULL != attrs[i]; i += 2)
- {
- assert (NULL != attrs[i+1]);
-
- if (!strcmp (attrs[i], "id"))
- {
- if (!handle_id (&sp->strs.credentials.id, (const char *)attrs[i+1],
- (cf_get_fn)conffile_get_credentials, sp->cf))
- {
- sp->state = ERROR;
- return;
- }
- }
-
- else
- {
- fprintf (stderr, "Unrecognised <credentials> attribute %s\n", attrs[i]);
- sp->state = ERROR;
- return;
- }
- }
-
- if (NULL == sp->strs.credentials.id)
- {
- fputs ("<credentials> must have an id attribute\n", stderr);
- sp->state = ERROR;
- return;
- }
-
- sp->strs.credentials.domain = g_string_new (NULL);
- sp->strs.credentials.username = g_string_new (NULL);
- sp->strs.credentials.password = g_string_new (NULL);
-
- sp->strs.credentials.got_domain = false;
- sp->strs.credentials.got_username = false;
- sp->strs.credentials.got_password = false;
-
- sp->state = CREDS;
-}
-
-
-static void start_char_state (struct sax_parser *sp,
- GString *target,
- bool *got,
- const char *name,
- const xmlChar **attrs)
-{
- assert (NULL != target);
-
- if (ERROR == sp->state)
- return;
-
- if ((NULL != attrs) && (NULL != attrs[0]))
- {
- fprintf (stderr, "Spurious attributes on <%s>\n", name);
- sp->state = ERROR;
- return;
- }
-
- if (false != *got)
- {
- fprintf (stderr, "Duplicate <%s>\n", name);
- sp->state = ERROR;
- return;
- }
-
- *got = true;
-}
-
-
-static void start_server (struct sax_parser *sp, const xmlChar **attrs)
-{
- start_char_state (sp, sp->strs.mount.server, &sp->strs.mount.got_server,
- "server", attrs);
-}
-
-
-static void start_share (struct sax_parser *sp, const xmlChar **attrs)
-{
- start_char_state (sp, sp->strs.mount.share, &sp->strs.mount.got_share,
- "share", attrs);
-}
-
-
-static void start_mtpt (struct sax_parser *sp, const xmlChar **attrs)
-{
- start_char_state (sp, sp->strs.mount.mountpoint,
- &sp->strs.mount.got_mountpoint, "mountpoint", attrs);
-}
-
-
-static void start_options (struct sax_parser *sp, const xmlChar **attrs)
-{
- start_char_state (sp, sp->strs.mount.options, &sp->strs.mount.got_options,
- "options", attrs);
-}
-
-
-static void start_domain (struct sax_parser *sp, const xmlChar **attrs)
-{
- start_char_state (sp, sp->strs.credentials.domain,
- &sp->strs.credentials.got_domain, "domain", attrs);
-}
-
-
-static void start_username (struct sax_parser *sp, const xmlChar **attrs)
-{
- start_char_state (sp, sp->strs.credentials.username,
- &sp->strs.credentials.got_username, "username", attrs);
-}
-
-
-static void start_password (struct sax_parser *sp, const xmlChar **attrs)
-{
- start_char_state (sp, sp->strs.credentials.password,
- &sp->strs.credentials.got_password, "password", attrs);
-}
-
-
-static void start_element (void *ctx,
- const xmlChar *name, const xmlChar **attrs)
-{
- struct sax_parser *sp = ctx;
-
- if (ERROR == sp->state)
- return;
-
- /* all valid transitions on <element> */
- const struct {
- enum sax_state to, from;
- enum element on;
- void (*fn) (struct sax_parser *, const xmlChar **attrs);
- } transitions[] = {
- { .from = INITIAL, .on = ELT_USMBCFG, .to = USMBCFG, .fn = NULL …
- { .from = USMBCFG, .on = ELT_MOUNT, .to = MOUNT, .fn = start_mount …
- { .from = USMBCFG, .on = ELT_CREDS, .to = CREDS, .fn = start_creds …
- { .from = MOUNT, .on = ELT_SERVER, .to = SERVER, .fn = start_server …
- { .from = MOUNT, .on = ELT_SHARE, .to = SHARE, .fn = start_share …
- { .from = MOUNT, .on = ELT_MOUNTPT, .to = MOUNTPT, .fn = start_mtpt …
- { .from = MOUNT, .on = ELT_OPTIONS, .to = OPTIONS, .fn = start_options …
- { .from = CREDS, .on = ELT_DOMAIN, .to = DOMAIN, .fn = start_domain …
- { .from = CREDS, .on = ELT_USER, .to = USER, .fn = start_username …
- { .from = CREDS, .on = ELT_PASS, .to = PASS, .fn = start_password }
- };
-
-
- enum element elt = get_element ((const char *)name);
-
- for (size_t i = 0; i < sizeof (transitions) / sizeof (transitions[0]); ++i)
- {
- if ((transitions[i].from == sp->state) &&
- (transitions[i].on == elt))
- {
- if (NULL != transitions[i].fn)
- transitions[i].fn (sp, attrs);
-
- if (ERROR != sp->state)
- sp->state = transitions[i].to;
- return;
- }
- }
-
- fprintf (stderr, "Unexpected <%s>\n", name);
- sp->state = ERROR;
-}
-
-
-static void end_mount (struct sax_parser *sp)
-{
- // must have id, creds, server, share and mountpoint; options are optional
- assert (NULL != sp->strs.mount.id);
- assert (NULL != sp->strs.mount.creds);
-
- if (!sp->strs.mount.got_server || (0 == sp->strs.mount.server->len))
- {
- fprintf (stderr, "Mount %s: no server given\n", sp->strs.mount.id);
- sp->state = ERROR;
- }
-
- else if (!sp->strs.mount.got_share || (0 == sp->strs.mount.share->len))
- {
- fprintf (stderr, "Mount %s: no share given\n", sp->strs.mount.id);
- sp->state = ERROR;
- }
-
- else if (!sp->strs.mount.got_mountpoint ||
- (0 == sp->strs.mount.mountpoint->len))
- {
- fprintf (stderr, "Mount %s: no mount point given\n", sp->strs.mount.id);
- sp->state = ERROR;
- }
-
- else
- {
- struct mount *mount =
- mount_new (sp->strs.mount.server->str,
- sp->strs.mount.share->str,
- sp->strs.mount.mountpoint->str,
- sp->strs.mount.creds,
- sp->strs.mount.options->str);
-
- if ((NULL == mount) ||
- !conffile_add_mount (sp->cf, sp->strs.mount.id, mount))
- sp->state = ERROR;
- }
-
- g_string_free (sp->strs.mount.server, TRUE);
- g_string_free (sp->strs.mount.share, TRUE);
- g_string_free (sp->strs.mount.mountpoint, TRUE);
- g_string_free (sp->strs.mount.options, TRUE);
-
- // we need the mount ID (for the hashtable key) if parsing succeeded
- if (ERROR == sp->state)
- xfree (sp->strs.mount.id);
-}
-
-
-static void end_creds (struct sax_parser *sp)
-{
- // must have username; domain and password are optional
- assert (NULL != sp->strs.credentials.id);
-
- if (!sp->strs.credentials.got_username ||
- (0 == sp->strs.credentials.username->len))
- {
- fprintf (stderr, "Credentials %s: no username given\n",
- sp->strs.credentials.id);
- sp->state = ERROR;
- }
-
- else
- {
- struct credentials *creds =
- credentials_new (sp->strs.credentials.domain->str,
- sp->strs.credentials.username->str,
- sp->strs.credentials.password->str);
-
- if ((NULL == creds) ||
- !conffile_add_credentials (sp->cf, sp->strs.credentials.id, creds))
- sp->state = ERROR;
- }
-
- g_string_free (sp->strs.credentials.domain, TRUE);
- g_string_free (sp->strs.credentials.username, TRUE);
- g_string_free (sp->strs.credentials.password, TRUE);
-
- sp->strs.credentials.domain = NULL;
- sp->strs.credentials.username = NULL;
- sp->strs.credentials.password = NULL;
-
- if (ERROR == sp->state)
- xfree (sp->strs.credentials.id);
-}
-
-
-static void end_element (void *ctx, const xmlChar *name)
-{
- struct sax_parser *sp = ctx;
-
- if (ERROR == sp->state)
- return;
-
- /* all valid transitions on </element> */
- const struct {
- enum sax_state to, from;
- enum element on;
- void (*fn) (struct sax_parser *);
- } transitions[] = {
- { .from = USMBCFG, .on = ELT_USMBCFG, .to = DONE, .fn = NULL },
- { .from = MOUNT, .on = ELT_MOUNT, .to = USMBCFG, .fn = end_mount },
- { .from = CREDS, .on = ELT_CREDS, .to = USMBCFG, .fn = end_creds },
- { .from = SERVER, .on = ELT_SERVER, .to = MOUNT, .fn = NULL },
- { .from = SHARE, .on = ELT_SHARE, .to = MOUNT, .fn = NULL },
- { .from = MOUNTPT, .on = ELT_MOUNTPT, .to = MOUNT, .fn = NULL },
- { .from = OPTIONS, .on = ELT_OPTIONS, .to = MOUNT, .fn = NULL },
- { .from = DOMAIN, .on = ELT_DOMAIN, .to = CREDS, .fn = NULL },
- { .from = USER, .on = ELT_USER, .to = CREDS, .fn = NULL },
- { .from = PASS, .on = ELT_PASS, .to = CREDS, .fn = NULL }
- };
-
-
- enum element elt = get_element ((const char *)name);
-
- for (size_t i = 0; i < sizeof (transitions) / sizeof (transitions[0]); ++i)
- {
- if ((transitions[i].from == sp->state) &&
- (transitions[i].on == elt))
- {
- if (NULL != transitions[i].fn)
- transitions[i].fn (sp);
-
- if (ERROR != sp->state)
- sp->state = transitions[i].to;
- return;
- }
- }
-
- fprintf (stderr, "Unexpected </%s>\n", name);
- sp->state = ERROR;
-}
-
-
-// strips leading and trailing whitespace; returns true iff characters remain
-static bool strip_whitespace (const char **str, int *len)
-{
- assert (NULL != str);
- assert (NULL != len);
-
- /* leading whitespace */
- while ((*len > 0) && isspace (**str))
- {
- ++(*str);
- --(*len);
- }
-
- /* trailing whitespace */
- while ((*len > 0) && (isspace ((*str)[*len - 1])))
- --(*len);
-
- return (0 != *len);
-}
-
-
-static inline void append_chars (GString *target, const xmlChar *str, int len)
-{
- assert (NULL != target);
- assert (NULL != str);
-
- g_string_append_len (target, (const char *)str, len);
-}
-
-
-static void chars (void *ctx, const xmlChar *str, int len)
-{
- struct sax_parser *sp = ctx;
-
- if (ERROR == sp->state)
- return;
-
- // all states admit whitespace characters
- if (!strip_whitespace ((const char **)&str, &len))
- return;
-
- // these states admit non-whitespace characters
- switch (sp->state)
- {
- case SERVER: append_chars (sp->strs.mount.server, str, len); brea…
- case SHARE: append_chars (sp->strs.mount.share, str, len); brea…
- case MOUNTPT: append_chars (sp->strs.mount.mountpoint, str, len); brea…
- case OPTIONS: append_chars (sp->strs.mount.options, str, len); brea…
- case DOMAIN: append_chars (sp->strs.credentials.domain, str, len); brea…
- case USER: append_chars (sp->strs.credentials.username, str, len); brea…
- case PASS: append_chars (sp->strs.credentials.password, str, len); brea…
-
- default:
- fputs ("Unexpected characters: ", stderr);
- while (len--)
- fputc (*str++, stderr);
- fputc ('\n', stderr);
- sp->state = ERROR;
- break;
- }
-}
-
-
-struct conffile * parse_xml_conf (const char *file)
-{
- LIBXML_TEST_VERSION;
-
- struct _xmlSAXHandler sax = {
- .startDocument = start_document,
- .endDocument = end_document,
- .startElement = start_element,
- .endElement = end_element,
- .error = error,
- .characters = chars,
- };
-
-
- struct sax_parser user_data = {
- .state = START
- };
-
- user_data.cf = conffile_new();
-
- if (NULL != user_data.cf)
- {
- if ((0 != xmlSAXUserParseFile (&sax, &user_data, file)) ||
- (user_data.state != FINISH))
- {
- fputs ("Parse error\n", stderr);
- conffile_destroy (user_data.cf);
- user_data.cf = NULL;
- }
- }
-
- return user_data.cf;
-}
diff --git a/sax.h b/sax.h
@@ -1,27 +0,0 @@
-/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
- *
- * This program 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 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef SAX_H
- #define SAX_H
-
- #include "conffile.h"
-
- struct conffile * parse_xml_conf (const char *file);
-
-#endif
-
diff --git a/usmb.c b/usmb.c
@@ -1,5 +1,5 @@
/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
+ * Copyright (C) 2006-2007 Geoff Johnstone
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -32,7 +32,6 @@
#include <string.h>
#include "conffile.h"
#include "options.h"
-#include "sax.h"
#include "usmb.h"
#include "usmb_dir.h"
#include "usmb_file.h"
@@ -41,7 +40,7 @@
SMBCCTX *ctx;
-static const char *share = NULL;
+static char *share = NULL;
char * make_url (const char *path)
@@ -62,9 +61,7 @@ static inline void do_strncpy (char *to, const char *from, in…
}
-static char *domain = NULL;
-static char *username = NULL;
-static char *password = NULL;
+static struct mount *mount;
static void auth_fn (const char *srv, const char *shr, char *wg, int wglen,
char *un, int unlen, char *pw, int pwlen)
@@ -73,13 +70,11 @@ static void auth_fn (const char *srv, const char *shr, char…
(void)shr;
DEBUG (fprintf (stderr, "Authenticating for \\\\%s\\%s\n", srv, shr));
- assert (NULL != domain);
- assert (NULL != username);
- assert (NULL != password);
+ if (NULL != mount->credentials->domain)
+ do_strncpy (wg, mount->credentials->domain, wglen);
- do_strncpy (wg, domain, wglen);
- do_strncpy (un, username, unlen);
- do_strncpy (pw, password, pwlen);
+ do_strncpy (un, mount->credentials->username, unlen);
+ do_strncpy (pw, mount->credentials->password, pwlen);
}
@@ -205,45 +200,22 @@ static bool check_conf_perms (const char *conffile)
}
-static bool fix_up_conf_details (struct mount *mount)
+static bool create_share_name (struct mount *mount)
{
assert (NULL != mount->credentials);
size_t len = strlen ("smb:///") +
strlen (mount->server) +
strlen (mount->share) + 1;
- char *str;
- if (NULL == (str = malloc (len)))
- {
- perror ("Cannot allocate share name");
- return false;
- }
-
- strcpy (str, "smb://");
- strcat (str, mount->server);
- strcat (str, "/");
- strcat (str, mount->share);
- domain = xstrdup (mount->credentials->domain);
- username = xstrdup (mount->credentials->username);
- password = xstrdup (mount->credentials->password);
-
- if ((NULL == domain) ||
- (NULL == username) ||
- (NULL == password))
+ if (NULL == (share = malloc (len)))
{
- fputs ("Out of memory\n", stderr);
- xfree (password);
- xfree (username);
- xfree (domain);
- free (str);
+ perror ("Cannot allocate share name");
return false;
}
- share = str;
-
+ snprintf (share, len, "smb://%s/%s", mount->server, mount->share);
DEBUG (fprintf (stderr, "Share URL: %s\n", share));
- DEBUG (fprintf (stderr, "Username: %s\\%s\n", domain, username));
return true;
}
@@ -265,12 +237,11 @@ int main (int argc, char **argv)
if (!check_conf_perms (conffile))
return EXIT_FAILURE;
- struct conffile *cf = parse_xml_conf (conffile);
+ struct conffile *cf = conffile_new (conffile);
if (NULL == cf)
return EXIT_FAILURE;
struct mount *mount = conffile_get_mount (cf, mountid);
-
if (NULL == mount)
{
fprintf (stderr, "Mount %s not defined in configuration file %s\n",
@@ -279,42 +250,27 @@ int main (int argc, char **argv)
return EXIT_FAILURE;
}
- char *mountpoint = xstrdup (mount->mountpoint);
- char *options = xstrdup (mount->options);
-
- if ((NULL == mountpoint) ||
- (mount->options && (NULL == options)))
+ if (!create_share_name (mount) ||
+ !create_smb_context ((char *)mount->credentials->domain,
+ (char *)mount->credentials->username, &ctx))
{
- perror ("Cannot allocate mountpoint");
- return EXIT_FAILURE;
- }
-
- {
- bool ret = fix_up_conf_details (mount);
+ mount_destroy (mount);
conffile_destroy (cf);
-
- if (false == ret)
- return EXIT_FAILURE;
- }
-
- if (!create_smb_context (domain, username, &ctx))
return EXIT_FAILURE;
+ }
+ DEBUG (fprintf (stderr, "Username: %s\\%s\n",
+ mount->credentials->domain, mount->credentials->username));
show_about (stdout);
int fuse_argc;
char **fuse_argv;
- build_fuse_args (options, mountpoint, &fuse_argc, &fuse_argv);
+ build_fuse_args (mount->options, mount->mountpoint, &fuse_argc, &fuse_argv);
int ret = fuse_main (fuse_argc, fuse_argv, &fuse_ops);
smbc_free_context (ctx, 1);
-
- xfree (mountpoint);
- xfree (options);
- xfree (domain);
- xfree (username);
- xfree (password);
- xfree (share);
+ mount_destroy (mount);
+ conffile_destroy (cf);
return ret;
}
diff --git a/usmb.h b/usmb.h
@@ -1,5 +1,5 @@
/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
+ * Copyright (C) 2006-2007 Geoff Johnstone
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/usmb_dir.c b/usmb_dir.c
@@ -1,5 +1,5 @@
/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
+ * Copyright (C) 2006-2007 Geoff Johnstone
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/usmb_dir.h b/usmb_dir.h
@@ -1,5 +1,5 @@
/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
+ * Copyright (C) 2006-2007 Geoff Johnstone
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/usmb_file.c b/usmb_file.c
@@ -1,5 +1,5 @@
/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
+ * Copyright (C) 2006-2007 Geoff Johnstone
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/usmb_file.h b/usmb_file.h
@@ -1,5 +1,5 @@
/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
+ * Copyright (C) 2006-2007 Geoff Johnstone
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/utils.c b/utils.c
@@ -1,5 +1,5 @@
/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
+ * Copyright (C) 2006-2007 Geoff Johnstone
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/utils.h b/utils.h
@@ -1,5 +1,5 @@
/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
+ * Copyright (C) 2006-2007 Geoff Johnstone
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff --git a/version.c b/version.c
@@ -1,5 +1,5 @@
/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
+ * Copyright (C) 2006-2007 Geoff Johnstone
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -35,7 +35,7 @@ void show_about (FILE *fp)
{
fputs ("usmb - mount SMB shares via FUSE and Samba\n"
"\n"
- "Copyright (C) 2006 Geoff Johnstone.\n"
+ "Copyright (C) 2006-2007 Geoff Johnstone.\n"
"Licensed under the GNU General Public License.\n"
"usmb comes with ABSOLUTELY NO WARRANTY; for details please see\n"
"http://www.gnu.org/licenses/gpl.txt\n", fp);
diff --git a/version.h b/version.h
@@ -1,5 +1,5 @@
/* usmb - mount SMB shares via FUSE and Samba
- * Copyright (C) 2006 Geoff Johnstone
+ * Copyright (C) 2006-2007 Geoff Johnstone
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
#include <stdio.h>
- #define USMB_VERSION 0x20060708
+ #define USMB_VERSION 0x20070102
// a - alpha, b - beta, p - pre-release, s - stable
#define USMB_VERSION_STATUS 'a'
diff --git a/xml.c b/xml.c
@@ -0,0 +1,158 @@
+#include <libxml/xmlreader.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include "xml.h"
+#include "utils.h"
+
+
+bool xml_validate_relaxng (xmlDocPtr doc, const char *schema)
+{
+ xmlRelaxNGParserCtxtPtr rngpcptr = NULL;
+ xmlRelaxNGPtr rngptr = NULL;
+ xmlRelaxNGValidCtxtPtr rngvptr = NULL;
+ bool ret = false;
+
+ assert (NULL != doc);
+
+ if ((rngpcptr = xmlRelaxNGNewMemParserCtxt (schema, strlen (schema))) &&
+ ((rngptr = xmlRelaxNGParse (rngpcptr))) &&
+ ((rngvptr = xmlRelaxNGNewValidCtxt (rngptr))))
+ {
+ ret = (0 == xmlRelaxNGValidateDoc (rngvptr, doc));
+ }
+
+ if (NULL != rngvptr)
+ xmlRelaxNGFreeValidCtxt (rngvptr);
+
+ if (NULL != rngptr)
+ xmlRelaxNGFree (rngptr);
+
+ if (NULL != rngpcptr)
+ xmlRelaxNGFreeParserCtxt (rngpcptr);
+
+ return ret;
+}
+
+
+bool xml_xpath_attr_value (xmlXPathContextPtr ctx,
+ xmlChar *xpath,
+ const xmlChar *attribute,
+ xmlChar **out)
+{
+ xmlXPathObjectPtr obj;
+ xmlChar *tmp;
+
+ assert (NULL != ctx);
+ assert (NULL != xpath);
+ assert (NULL != out);
+
+ *out = NULL;
+
+ obj = xmlXPathEval (xpath, ctx);
+ if (NULL == obj)
+ {
+ DEBUG (fputs ("XPath evaluation error\n", stderr));
+ return false;
+ }
+
+ do {
+ if (XPATH_NODESET != obj->type)
+ {
+ DEBUG (fputs ("XPath evaluation didn't return a nodeset\n", stderr));
+ break;
+ }
+
+ if (NULL == obj->nodesetval)
+ {
+ DEBUG (fputs ("nodesetval is NULL\n", stderr));
+ break;
+ }
+
+ if (1 != obj->nodesetval->nodeNr)
+ {
+ DEBUG (fprintf (stderr, "Nodeset has %d elements\n",
+ obj->nodesetval->nodeNr));
+ break;
+ }
+
+ tmp = xmlGetProp (obj->nodesetval->nodeTab[0], attribute);
+ if (NULL == tmp)
+ break;
+
+ *out = (xmlChar *)xstrdup ((char *)tmp);
+ if (NULL == *out)
+ break;
+
+ xmlXPathFreeObject (obj);
+ return true;
+ /*NOTREACHED*/
+ } while (false);
+
+ *out = NULL;
+ xmlXPathFreeObject (obj);
+ return false;
+}
+
+
+bool xml_xpath_text (xmlXPathContextPtr ctx, xmlChar *xpath, xmlChar **out)
+{
+ xmlXPathObjectPtr obj;
+
+ assert (NULL != ctx);
+ assert (NULL != xpath);
+ assert (NULL != out);
+
+ *out = NULL;
+
+ DEBUG (fprintf (stderr, "xml_xpath_text (%s)\n", xpath));
+
+ obj = xmlXPathEval (xpath, ctx);
+ if (NULL == obj)
+ {
+ DEBUG (fputs ("XPath evaluation error\n", stderr));
+ return false;
+ }
+
+ do {
+ if (XPATH_NODESET != obj->type)
+ {
+ DEBUG (fputs ("XPath evaluation didn't return a nodeset\n", stderr));
+ break;
+ }
+
+ if (NULL == obj->nodesetval)
+ {
+ DEBUG (fputs ("nodesetval is NULL\n", stderr));
+ break;
+ }
+
+ if (1 != obj->nodesetval->nodeNr)
+ {
+ DEBUG (fprintf (stderr, "Nodeset has %d elements\n",
+ obj->nodesetval->nodeNr));
+ break;
+ }
+
+ if (NULL == obj->nodesetval->nodeTab[0]->content)
+ {
+ DEBUG (fputs ("Node has no text\n", stderr));
+ break;
+ }
+
+ *out = (xmlChar *)xstrdup ((char *)obj->nodesetval->nodeTab[0]->content);
+ if (NULL == *out)
+ break;
+
+ xmlXPathFreeObject (obj);
+ return true;
+ /*NOTREACHED*/
+ } while (false);
+
+ *out = NULL;
+ xmlXPathFreeObject (obj);
+ return false;
+}
+
diff --git a/xml.h b/xml.h
@@ -0,0 +1,35 @@
+/* usmb - mount SMB shares via FUSE and Samba
+ * Copyright (C) 2006-2007 Geoff Johnstone
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef XML_H
+ #define XML_H
+
+ #include <libxml/xmlreader.h>
+ #include <libxml/xpath.h>
+ #include <libxml/xpathInternals.h>
+ #include <stdbool.h>
+
+
+ bool xml_validate_relaxng (xmlDocPtr doc, const char *schema);
+ bool xml_xpath_attr_value (xmlXPathContextPtr ctx,
+ xmlChar *xpath,
+ const xmlChar *attribute,
+ xmlChar **out);
+ bool xml_xpath_text (xmlXPathContextPtr ctx, xmlChar *xpath, xmlChar **out);
+
+#endif
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.