Cleaned up some of the parsing code: o Boolean got_xxx rather than GString * == NULL, which smacks of in-band signalling. o Tidier checking of duplicate / missing IDs; checking now occurs in the start element. o struct mount includes a struct credentials * rather than the ID of the credentials entry. - susmb - mounting of SMB/CIFS shares via FUSE
 (HTM) git clone git://git.codemadness.org/susmb
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit db77d112648c00a8456b39c1a5faa0ac061d14f7
 (DIR) parent abe38e627824e686da4c8aa101a1ac750ba9e2be
 (HTM) Author: geoff <devnull@localhost>
       Date:   Tue,  9 May 2006 23:31:22 +0000
       
       Cleaned up some of the parsing code:
        o Boolean got_xxx rather than GString * == NULL, which smacks of in-band
          signalling.
        o Tidier checking of duplicate / missing IDs; checking now occurs in the
          start element.
        o struct mount includes a struct credentials * rather than the ID of the
          credentials entry.
       
       Removed .mt-attrs from the tarballs.
       
       Diffstat:
         M Makefile                            |       2 +-
         M conffile.c                          |       9 +++++----
         M conffile.h                          |       5 +++--
         M doc/README                          |       2 +-
         M sax.c                               |     222 +++++++++++++++----------------
         M usmb.c                              |      13 ++++++-------
       
       6 files changed, 123 insertions(+), 130 deletions(-)
       ---
 (DIR) diff --git a/Makefile b/Makefile
       @@ -78,7 +78,7 @@ tar: STAGING=/tmp/usmb-$(VERSION)
        tar:
                mkdir $(STAGING)
                cp -a $(PWD)/* $(STAGING)/
       -        rm -rf $(STAGING)/MT
       +        rm -rf $(STAGING)/MT $(STAGING)/.mt-attrs
                (cd $(STAGING)/..; \
                 make -C $(STAGING) distclean ; \
                 tar jcf $(PWD)/usmb-$(VERSION).tar.bz2 usmb-$(VERSION) ; \
 (DIR) diff --git a/conffile.c b/conffile.c
       @@ -69,11 +69,14 @@ void credentials_destroy (struct credentials *creds)
        
        
        struct mount * mount_new (const char *server, const char *share,
       -                          const char *mountpoint, const char *credentials,
       +                          const char *mountpoint,
       +                          const struct credentials *credentials,
                                  const char *options)
        {
          struct mount *mount = malloc (sizeof (struct mount));
        
       +  assert (NULL != credentials);
       +
          if (NULL == mount)
            return NULL;
        
       @@ -81,12 +84,11 @@ struct mount * mount_new (const char *server, const char *share,
          mount->share = xstrdup (share);
          mount->mountpoint = xstrdup (mountpoint);
          mount->options = xstrdup (options);
       -  mount->credentials = xstrdup (credentials);
       +  mount->credentials = credentials;
        
          if ((NULL == mount->server) ||
              (NULL == mount->share) ||
              (NULL == mount->mountpoint) ||
       -      (NULL == mount->credentials) ||
              (NULL == mount->options))
          {
            mount_destroy (mount);
       @@ -101,7 +103,6 @@ void mount_destroy (struct mount *mount)
        {
          assert (NULL != mount);
        
       -  xfree (mount->credentials);
          xfree (mount->options);
          xfree (mount->mountpoint);
          xfree (mount->share);
 (DIR) diff --git a/conffile.h b/conffile.h
       @@ -32,7 +32,7 @@
            char *server;
            char *share;
            char *mountpoint;
       -    char *credentials;
       +    const struct credentials *credentials;
            char *options;
          };
        
       @@ -47,7 +47,8 @@
          void credentials_destroy (struct credentials *creds);
        
          struct mount * mount_new (const char *server, const char *share,
       -                            const char *mountpoint, const char *credentials,
       +                            const char *mountpoint,
       +                            const struct credentials *credentials,
                                    const char *options);
        
          void mount_destroy (struct mount *mount);
 (DIR) diff --git a/doc/README b/doc/README
       @@ -35,7 +35,7 @@ Configuration
        -------------
        
        You need an XML configuration file - ${HOME}/.usmb.conf by default. There's an
       -example doc/usmb.conf.
       +example in doc/usmb.conf.
        
        There are two main elements: credentials and mounts.
        
 (DIR) diff --git a/sax.c b/sax.c
       @@ -19,6 +19,7 @@
        #include <assert.h>
        #include <ctype.h>
        #include <stdarg.h>
       +#include <stdbool.h>
        #include <stdio.h>
        #include <string.h>
        #include <libxml/xmlreader.h>
       @@ -113,13 +114,25 @@ struct sax_parser {
          union {
            struct {
              char *id;
       +
       +      bool got_domain;
       +      bool got_username;
       +      bool got_password;
       +
              GString *domain;
              GString *username;
              GString *password;
            } credentials;
       +
            struct {
              char *id;
       -      char *creds;
       +      struct credentials *creds;
       +
       +      bool got_server;
       +      bool got_share;
       +      bool got_mountpoint;
       +      bool got_options;
       +
              GString *server;
              GString *share;
              GString *mountpoint;
       @@ -135,13 +148,13 @@ 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_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"
          };
       @@ -159,19 +172,6 @@ static void start_document (void *ctx)
          struct sax_parser *sp = ctx;
          assert (sp->state == START);
          sp->state = INITIAL;
       -
       -  // these four aren't strictly necessary as we're using a union
       -  sp->strs.credentials.id = NULL;
       -  sp->strs.credentials.domain = NULL;
       -  sp->strs.credentials.username = NULL;
       -  sp->strs.credentials.password = NULL;
       -
       -  sp->strs.mount.id = NULL;
       -  sp->strs.mount.creds = NULL;
       -  sp->strs.mount.server = NULL;
       -  sp->strs.mount.share = NULL;
       -  sp->strs.mount.mountpoint = NULL;
       -  sp->strs.mount.options = NULL;
        }
        
        
       @@ -209,18 +209,24 @@ static void error (void *ctx, const char *msg, ...)
        }
        
        
       -static bool set_string (char **out, const char *in, const char *dup_err)
       +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)
          {
       -    if (NULL != dup_err)
       -    {
       -      fputs (dup_err, stderr);
       -      return false;
       -    }
       +    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);
       @@ -237,10 +243,8 @@ static bool set_string (char **out, const char *in, const char *dup_err)
        
        static void start_mount (struct sax_parser *sp, const xmlChar **attrs)
        {
       -  assert (NULL == sp->strs.mount.server);
       -  assert (NULL == sp->strs.mount.share);
       -  assert (NULL == sp->strs.mount.mountpoint);
       -  assert (NULL == sp->strs.mount.options);
       +  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)
       @@ -249,8 +253,8 @@ static void start_mount (struct sax_parser *sp, const xmlChar **attrs)
        
            if (!strcmp (attrs[i], "id"))
            {
       -      if (!set_string (&sp->strs.mount.id, (const char *)attrs[i+1],
       -                       "Duplicate id attribute in <mount>\n"))
       +      if (!handle_id (&sp->strs.mount.id, (const char *)attrs[i+1],
       +                      (cf_get_fn)conffile_get_mount, sp->cf))
              {
                sp->state = ERROR;
                return;
       @@ -259,9 +263,19 @@ static void start_mount (struct sax_parser *sp, const xmlChar **attrs)
        
            else if (!strcmp (attrs[i], "credentials"))
            {
       -      if (!set_string (&sp->strs.mount.creds, (const char *)attrs[i+1],
       -                       "Duplicate credentials attribute in <mount>\n"))
       +      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;
              }
       @@ -283,6 +297,16 @@ static void start_mount (struct sax_parser *sp, const xmlChar **attrs)
            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;
        }
        
       @@ -293,6 +317,8 @@ static void start_creds (struct sax_parser *sp, const xmlChar **attrs)
          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)
          {
       @@ -300,8 +326,8 @@ static void start_creds (struct sax_parser *sp, const xmlChar **attrs)
        
            if (!strcmp (attrs[i], "id"))
            {
       -      if (!set_string (&sp->strs.credentials.id, (const char *)attrs[i+1],
       -                       "Duplicate id attribute in <credentials>\n"))
       +      if (!handle_id (&sp->strs.credentials.id, (const char *)attrs[i+1],
       +                      (cf_get_fn)conffile_get_credentials, sp->cf))
              {
                sp->state = ERROR;
                return;
       @@ -323,15 +349,26 @@ static void start_creds (struct sax_parser *sp, const xmlChar **attrs)
            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,
       +                              GString *target,
       +                              bool *got,
                                      const char *name,
                                      const xmlChar **attrs)
        {
       +  assert (NULL != target);
       +
          if (ERROR == sp->state)
            return;
        
       @@ -342,62 +379,63 @@ static void start_char_state (struct sax_parser *sp,
            return;
          }
        
       -  if (NULL != *target)
       +  if (false != *got)
          {
            fprintf (stderr, "Duplicate <%s>\n", name);
            sp->state = ERROR;
            return;
          }
        
       -  *target = g_string_new (NULL);
       -  if (NULL == *target)
       -  {
       -    fputs ("Out of memory\n", stderr);
       -    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, "server", 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, "share", 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, "mountpoint", 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, "options", 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, "domain", 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, "username", 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, "password", attrs);
       +  start_char_state (sp, sp->strs.credentials.password,
       +                    &sp->strs.credentials.got_password, "password", attrs);
        }
        
        
       @@ -455,32 +493,19 @@ static void end_mount (struct sax_parser *sp)
          assert (NULL != sp->strs.mount.id);
          assert (NULL != sp->strs.mount.creds);
        
       -  if (NULL == conffile_get_credentials (sp->cf, sp->strs.mount.creds))
       -  {
       -    fprintf (stderr, "Mount %s: credentials %s not found\n",
       -             sp->strs.mount.id, sp->strs.mount.creds);
       -    sp->state = ERROR;
       -  }
       -
       -  else if (NULL != conffile_get_mount (sp->cf, sp->strs.mount.id))
       -  {
       -    fprintf (stderr, "Duplicate mount ID: %s\n", sp->strs.mount.id);
       -    sp->state = ERROR;
       -  }
       -
       -  else if ((NULL == sp->strs.mount.server) || (0 == sp->strs.mount.server->len))
       +  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 ((NULL == sp->strs.mount.share) || (0 == sp->strs.mount.share->len))
       +  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 ((NULL == sp->strs.mount.mountpoint) ||
       +  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);
       @@ -490,43 +515,25 @@ static void end_mount (struct sax_parser *sp)
          else
          {
            struct mount *mount =
       -      mount_new (sp->strs.mount.server ? sp->strs.mount.server->str : "",
       -                 sp->strs.mount.share ? sp->strs.mount.share->str : "",
       -                 sp->strs.mount.mountpoint ?
       -                   sp->strs.mount.mountpoint->str : "",
       +      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 ?
       -                   sp->strs.mount.options->str : "");
       +                 sp->strs.mount.options->str);
        
            if ((NULL == mount) ||
                !conffile_add_mount (sp->cf, sp->strs.mount.id, mount))
              sp->state = ERROR;
          }
        
       -  if (sp->strs.mount.server)
       -    g_string_free (sp->strs.mount.server, TRUE);
       -  
       -  if (sp->strs.mount.share)
       -    g_string_free (sp->strs.mount.share, TRUE);
       -  
       -  if (sp->strs.mount.mountpoint)
       -    g_string_free (sp->strs.mount.mountpoint, TRUE);
       -  
       -  if (sp->strs.mount.options)
       -    g_string_free (sp->strs.mount.options, TRUE);
       -
       -  sp->strs.mount.server = NULL;
       -  sp->strs.mount.share = NULL;
       -  sp->strs.mount.mountpoint = NULL;
       -  sp->strs.mount.options = NULL;
       +  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);
       -
       -  xfree (sp->strs.mount.creds);
       -
       -  sp->strs.mount.id = NULL;
       -  sp->strs.mount.creds = NULL;
        }
        
        
       @@ -535,13 +542,7 @@ static void end_creds (struct sax_parser *sp)
          // must have username; domain and password are optional
          assert (NULL != sp->strs.credentials.id);
        
       -  if (NULL != conffile_get_credentials (sp->cf, sp->strs.credentials.id))
       -  {
       -    fprintf (stderr, "Duplicate credentials ID: %s\n", sp->strs.credentials.id);
       -    sp->state = ERROR;
       -  }
       -
       -  else if ((NULL == sp->strs.credentials.username) ||
       +  if (!sp->strs.credentials.got_username ||
                   (0 == sp->strs.credentials.username->len))
          {
            fprintf (stderr, "Credentials %s: no username given\n",
       @@ -552,12 +553,9 @@ static void end_creds (struct sax_parser *sp)
          else
          {
            struct credentials *creds =
       -      credentials_new (sp->strs.credentials.domain ?
       -                         sp->strs.credentials.domain->str : "",
       -                       sp->strs.credentials.username ?
       -                         sp->strs.credentials.username->str : "",
       -                       sp->strs.credentials.password ?
       -                         sp->strs.credentials.password->str : "");
       +      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))
       @@ -568,14 +566,8 @@ static void end_creds (struct sax_parser *sp)
          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);
       -
       -  sp->strs.credentials.id = NULL;
        }
        
        
 (DIR) diff --git a/usmb.c b/usmb.c
       @@ -178,10 +178,9 @@ static bool check_conf_perms (const char *conffile)
        }
        
        
       -static bool fix_up_conf_details (struct conffile *cf, struct mount *mount)
       +static bool fix_up_conf_details (struct mount *mount)
        {
       -  struct credentials *creds = conffile_get_credentials (cf, mount->credentials);
       -  assert (NULL != creds);
       +  assert (NULL != mount->credentials);
        
          size_t len = strlen ("smb:///") +
                       strlen (mount->server) +
       @@ -198,9 +197,9 @@ static bool fix_up_conf_details (struct conffile *cf, struct mount *mount)
          strcat (str, "/");
          strcat (str, mount->share);
        
       -  domain = xstrdup (creds->domain);
       -  username = xstrdup (creds->username);
       -  password = xstrdup (creds->password);
       +  domain = xstrdup (mount->credentials->domain);
       +  username = xstrdup (mount->credentials->username);
       +  password = xstrdup (mount->credentials->password);
        
          if ((NULL == domain) ||
              (NULL == username) ||
       @@ -264,7 +263,7 @@ int main (int argc, char **argv)
          }
        
          {
       -    bool ret = fix_up_conf_details (cf, mount);
       +    bool ret = fix_up_conf_details (mount);
            conffile_destroy (cf);
        
            if (false == ret)