libkmod-module: split creation of new modules to share code
authorLucas De Marchi <lucas.demarchi@profusion.mobi>
Sun, 29 Jan 2012 17:40:58 +0000 (15:40 -0200)
committerLucas De Marchi <lucas.demarchi@profusion.mobi>
Mon, 30 Jan 2012 22:05:34 +0000 (20:05 -0200)
Share code of module creation among the several new functions. With this
we let the alias/modname/path parsing to the separate functions, and the
rest with the common one.

This fixes the issue of alias names not being able to contain dots.

libkmod/libkmod-module.c

index f320fc1..e1a04ba 100644 (file)
@@ -180,6 +180,76 @@ void kmod_module_set_visited(struct kmod_module *mod, bool visited)
        mod->visited = visited;
 }
 
+/*
+ * Memory layout with alias:
+ *
+ * struct kmod_module {
+ *        hashkey -----.
+ *        alias -----. |
+ *        name ----. | |
+ * }               | | |
+ * name <----------' | |
+ * alias <-----------' |
+ * name\alias <--------'
+ *
+ * Memory layout without alias:
+ *
+ * struct kmod_module {
+ *        hashkey ---.
+ *        alias -----|----> NULL
+ *        name ----. |
+ * }               | |
+ * name <----------'-'
+ *
+ * @key is "name\alias" or "name" (in which case alias == NULL)
+ */
+static int kmod_module_new(struct kmod_ctx *ctx, const char *key,
+                               const char *name, size_t namelen,
+                               const char *alias, size_t aliaslen,
+                               struct kmod_module **mod)
+{
+       struct kmod_module *m;
+       size_t keylen;
+
+       m = kmod_pool_get_module(ctx, key);
+       if (m != NULL) {
+               *mod = kmod_module_ref(m);
+               return 0;
+       }
+
+       if (alias == NULL)
+               keylen = namelen;
+       else
+               keylen = namelen + aliaslen + 1;
+
+       m = malloc(sizeof(*m) + (alias == NULL ? 1 : 2) * (keylen + 1));
+       if (m == NULL) {
+               free(m);
+               return -ENOMEM;
+       }
+
+       memset(m, 0, sizeof(*m));
+
+       m->ctx = kmod_ref(ctx);
+       m->name = (char *)m + sizeof(*m);
+       memcpy(m->name, key, keylen + 1);
+       if (alias == NULL) {
+               m->hashkey = m->name;
+               m->alias = NULL;
+       } else {
+               m->name[namelen] = '\0';
+               m->alias = m->name + namelen + 1;
+               m->hashkey = m->name + keylen + 1;
+               memcpy(m->hashkey, key, keylen + 1);
+       }
+
+       m->refcount = 1;
+       kmod_pool_add_module(ctx, m, m->hashkey);
+       *mod = m;
+
+       return 0;
+}
+
 /**
  * kmod_module_new_from_name:
  * @ctx: kmod library context
@@ -206,54 +276,15 @@ KMOD_EXPORT int kmod_module_new_from_name(struct kmod_ctx *ctx,
                                                const char *name,
                                                struct kmod_module **mod)
 {
-       struct kmod_module *m;
        size_t namelen;
        char name_norm[PATH_MAX];
-       char *namesep;
 
        if (ctx == NULL || name == NULL || mod == NULL)
                return -ENOENT;
 
-       if (alias_normalize(name, name_norm, &namelen) < 0) {
-               DBG(ctx, "invalid alias: %s\n", name);
-               return -EINVAL;
-       }
+       modname_normalize(name, name_norm, &namelen);
 
-       m = kmod_pool_get_module(ctx, name_norm);
-       if (m != NULL) {
-               *mod = kmod_module_ref(m);
-               return 0;
-       }
-
-       namesep = strchr(name_norm, '/');
-       m = malloc(sizeof(*m) + (namesep == NULL ? 1 : 2) * namelen + 2);
-       if (m == NULL) {
-               free(m);
-               return -ENOMEM;
-       }
-
-       memset(m, 0, sizeof(*m));
-
-       m->ctx = kmod_ref(ctx);
-       m->name = (char *)m + sizeof(*m);
-       memcpy(m->name, name_norm, namelen + 1);
-
-       if (namesep) {
-               size_t len = namesep - name_norm;
-
-               m->name[len] = '\0';
-               m->alias = m->name + len + 1;
-               m->hashkey = m->name + namelen + 1;
-               memcpy(m->hashkey, name_norm, namelen + 1);
-       } else {
-               m->hashkey = m->name;
-       }
-
-       m->refcount = 1;
-       kmod_pool_add_module(ctx, m, m->hashkey);
-       *mod = m;
-
-       return 0;
+       return kmod_module_new(ctx, name_norm, name_norm, namelen, NULL, 0, mod);
 }
 
 int kmod_module_new_from_alias(struct kmod_ctx *ctx, const char *alias,
@@ -269,9 +300,9 @@ int kmod_module_new_from_alias(struct kmod_ctx *ctx, const char *alias,
 
        memcpy(key, name, namelen);
        memcpy(key + namelen + 1, alias, aliaslen + 1);
-       key[namelen] = '/';
+       key[namelen] = '\\';
 
-       err = kmod_module_new_from_name(ctx, key, mod);
+       err = kmod_module_new(ctx, key, name, namelen, alias, aliaslen, mod);
        if (err < 0)
                return err;
 
@@ -341,7 +372,7 @@ KMOD_EXPORT int kmod_module_new_from_path(struct kmod_ctx *ctx,
                        free(abspath);
                else {
                        ERR(ctx, "kmod_module '%s' already exists with different path: new-path='%s' old-path='%s'\n",
-                                                                       name, abspath, m->path);
+                                                       name, abspath, m->path);
                        free(abspath);
                        return -EEXIST;
                }
@@ -350,21 +381,11 @@ KMOD_EXPORT int kmod_module_new_from_path(struct kmod_ctx *ctx,
                return 0;
        }
 
-       m = malloc(sizeof(*m) + namelen + 1);
-       if (m == NULL)
-               return -errno;
-
-       memset(m, 0, sizeof(*m));
+       err = kmod_module_new(ctx, name, name, namelen, NULL, 0, &m);
+       if (err < 0)
+               return err;
 
-       m->ctx = kmod_ref(ctx);
-       m->name = (char *)m + sizeof(*m);
-       memcpy(m->name, name, namelen + 1);
        m->path = abspath;
-       m->hashkey = m->name;
-       m->refcount = 1;
-
-       kmod_pool_add_module(ctx, m, m->hashkey);
-
        *mod = m;
 
        return 0;