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 |