~registry/kmod/master

« back to all changes in this revision

Viewing changes to libkmod/libkmod.c

  • Committer: Lucas De Marchi
  • Date: 2011-12-12 12:30:01 UTC
  • mfrom: (161.1.30)
  • Revision ID: git-v1:2fee2f13ce5f6b17dd672389de422217c56105e2
Merge branch 'use-mmap'

Conflicts:
        libkmod/libkmod.c

Show diffs side-by-side

added added

removed removed

Lines of Context:
44
44
 * and is passed to all library operations.
45
45
 */
46
46
 
 
47
enum kmod_index {
 
48
        KMOD_INDEX_DEP = 0,
 
49
        KMOD_INDEX_ALIAS,
 
50
        KMOD_INDEX_SYMBOL,
 
51
        _KMOD_INDEX_LAST,
 
52
};
 
53
 
 
54
static const char* index_files[] = {
 
55
        [KMOD_INDEX_DEP] = "modules.dep",
 
56
        [KMOD_INDEX_ALIAS] = "modules.alias",
 
57
        [KMOD_INDEX_SYMBOL] = "modules.symbols",
 
58
};
 
59
 
 
60
static const char *default_config_paths[] = {
 
61
        "/run/modprobe.d",
 
62
        "/etc/modprobe.d",
 
63
        "/lib/modprobe.d",
 
64
        NULL
 
65
};
 
66
 
47
67
/**
48
68
 * kmod_ctx:
49
69
 *
60
80
        char *dirname;
61
81
        struct kmod_config *config;
62
82
        struct kmod_hash *modules_by_name;
 
83
        struct index_mm *indexes[_KMOD_INDEX_LAST];
63
84
};
64
85
 
65
86
void kmod_log(const struct kmod_ctx *ctx,
165
186
 * The initial refcount is 1, and needs to be decremented to
166
187
 * release the resources of the kmod library context.
167
188
 *
 
189
 * @dirname: what to consider as linux module's directory, if NULL
 
190
 *           defaults to /lib/modules/`uname -r`
 
191
 * @config_paths: ordered array of paths (directories or files) where
 
192
 *               to load user-defined configuration parameters such as
 
193
 *               alias, blacklists, commands (install, remove). If
 
194
 *               NULL defaults to /run/modprobe.d, /etc/modprobe.d and
 
195
 *               /lib/modprobe.d.  This array must be null terminated.
 
196
 *
168
197
 * Returns: a new kmod library context
169
198
 */
170
 
KMOD_EXPORT struct kmod_ctx *kmod_new(const char *dirname)
 
199
KMOD_EXPORT struct kmod_ctx *kmod_new(const char *dirname, const char * const *config_paths)
171
200
{
172
201
        const char *env;
173
202
        struct kmod_ctx *ctx;
189
218
        if (env != NULL)
190
219
                kmod_set_log_priority(ctx, log_priority(env));
191
220
 
192
 
        err = kmod_config_new(ctx, &ctx->config);
 
221
        if (config_paths == NULL)
 
222
                config_paths = default_config_paths;
 
223
        err = kmod_config_new(ctx, &ctx->config, config_paths);
193
224
        if (err < 0) {
194
225
                ERR(ctx, "could not create config\n");
195
226
                goto fail;
244
275
 
245
276
        if (--ctx->refcount > 0)
246
277
                return ctx;
 
278
 
247
279
        INFO(ctx, "context %p released\n", ctx);
 
280
 
 
281
        kmod_unload_resources(ctx);
248
282
        kmod_hash_free(ctx->modules_by_name);
249
283
        free(ctx->dirname);
250
284
        if (ctx->config)
251
285
                kmod_config_free(ctx->config);
 
286
 
252
287
        free(ctx);
253
288
        return NULL;
254
289
}
336
371
}
337
372
 
338
373
static int kmod_lookup_alias_from_alias_bin(struct kmod_ctx *ctx,
339
 
                                                const char *file,
 
374
                                                enum kmod_index index_number,
340
375
                                                const char *name,
341
376
                                                struct kmod_list **list)
342
377
{
343
 
        char *fn;
344
378
        int err, nmatch = 0;
345
379
        struct index_file *idx;
346
380
        struct index_value *realnames, *realname;
347
381
 
348
 
        if (asprintf(&fn, "%s/%s.bin", ctx->dirname, file) < 0)
349
 
                return -ENOMEM;
350
 
 
351
 
        DBG(ctx, "file=%s name=%s\n", fn, name);
352
 
 
353
 
        idx = index_file_open(fn);
354
 
        if (idx == NULL) {
355
 
                free(fn);
356
 
                return -ENOSYS;
 
382
        if (ctx->indexes[index_number] != NULL) {
 
383
                DBG(ctx, "use mmaped index '%s' for name=%s\n",
 
384
                        index_files[index_number], name);
 
385
                realnames = index_mm_searchwild(ctx->indexes[index_number],
 
386
                                                                        name);
 
387
        } else{
 
388
                char fn[PATH_MAX];
 
389
 
 
390
                snprintf(fn, sizeof(fn), "%s/%s.bin", ctx->dirname,
 
391
                                                index_files[index_number]);
 
392
 
 
393
                DBG(ctx, "file=%s name=%s\n", fn, name);
 
394
 
 
395
                idx = index_file_open(fn);
 
396
                if (idx == NULL)
 
397
                        return -ENOSYS;
 
398
 
 
399
                realnames = index_searchwild(idx, name);
 
400
                index_file_close(idx);
357
401
        }
358
402
 
359
 
        realnames = index_searchwild(idx, name);
360
403
        for (realname = realnames; realname; realname = realnames->next) {
361
404
                struct kmod_module *mod;
362
405
 
371
414
        }
372
415
 
373
416
        index_values_free(realnames);
374
 
        index_file_close(idx);
375
 
        free(fn);
376
 
 
377
417
        return nmatch;
378
418
 
379
419
fail:
382
422
 
383
423
}
384
424
 
385
 
static const char *symbols_file = "modules.symbols";
386
 
 
387
425
int kmod_lookup_alias_from_symbols_file(struct kmod_ctx *ctx, const char *name,
388
426
                                                struct kmod_list **list)
389
427
{
390
428
        if (!startswith(name, "symbol:"))
391
429
                return 0;
392
430
 
393
 
        return kmod_lookup_alias_from_alias_bin(ctx, symbols_file, name, list);
 
431
        return kmod_lookup_alias_from_alias_bin(ctx, KMOD_INDEX_SYMBOL, name,
 
432
                                                                        list);
394
433
}
395
434
 
396
 
 
397
 
static const char *aliases_file = "modules.alias";
398
 
 
399
435
int kmod_lookup_alias_from_aliases_file(struct kmod_ctx *ctx, const char *name,
400
436
                                                struct kmod_list **list)
401
437
{
402
 
        return kmod_lookup_alias_from_alias_bin(ctx, aliases_file, name, list);
 
438
        return kmod_lookup_alias_from_alias_bin(ctx, KMOD_INDEX_ALIAS, name,
 
439
                                                                        list);
403
440
}
404
441
 
405
 
static const char *moddep_file = "modules.dep";
406
 
 
407
442
char *kmod_search_moddep(struct kmod_ctx *ctx, const char *name)
408
443
{
409
444
        struct index_file *idx;
410
445
        char fn[PATH_MAX];
411
446
        char *line;
412
447
 
413
 
        snprintf(fn, sizeof(fn), "%s/%s.bin", ctx->dirname, moddep_file);
 
448
        if (ctx->indexes[KMOD_INDEX_DEP]) {
 
449
                DBG(ctx, "use mmaped index '%s' modname=%s\n",
 
450
                        index_files[KMOD_INDEX_DEP], name);
 
451
                return index_mm_search(ctx->indexes[KMOD_INDEX_DEP], name);
 
452
        }
 
453
 
 
454
        snprintf(fn, sizeof(fn), "%s/%s.bin", ctx->dirname,
 
455
                                                index_files[KMOD_INDEX_DEP]);
414
456
 
415
457
        DBG(ctx, "file=%s modname=%s\n", fn, name);
416
458
 
417
459
        idx = index_file_open(fn);
418
460
        if (idx == NULL) {
419
 
                ERR(ctx, "Could not open moddep file '%s'", fn);
 
461
                ERR(ctx, "Could not open moddep file '%s'\n", fn);
420
462
                return NULL;
421
463
        }
422
464
 
475
517
 
476
518
                        err = kmod_module_new_from_name(ctx, modname, &mod);
477
519
                        if (err < 0) {
478
 
                                ERR(ctx, "%s", strerror(-err));
 
520
                                ERR(ctx, "%s\n", strerror(-err));
479
521
                                goto fail;
480
522
                        }
481
523
 
544
586
        *output = NULL;
545
587
        return -ENOMEM;
546
588
}
 
589
 
 
590
KMOD_EXPORT int kmod_load_resources(struct kmod_ctx *ctx)
 
591
{
 
592
        char path[PATH_MAX];
 
593
        size_t i;
 
594
 
 
595
        if (ctx == NULL)
 
596
                return -ENOENT;
 
597
 
 
598
        for (i = 0; i < ARRAY_SIZE(index_files); i++) {
 
599
                if (ctx->indexes[i] == NULL) {
 
600
                        const char *fn = index_files[i];
 
601
                        size_t fnlen = strlen(fn);
 
602
                        const char *prefix = "";
 
603
                        const char *suffix = "";
 
604
 
 
605
                        if (fn[0] != '/')
 
606
                                prefix = ctx->dirname;
 
607
 
 
608
                        if (fnlen < 4 || !streq(fn + fnlen - 4, ".bin"))
 
609
                                suffix = ".bin";
 
610
 
 
611
                        snprintf(path, sizeof(path), "%s/%s%s",
 
612
                                 prefix, fn, suffix);
 
613
                        fn = path;
 
614
 
 
615
                        ctx->indexes[i] = index_mm_open(ctx, fn, true);
 
616
                        if (ctx->indexes[i] == NULL)
 
617
                                goto fail;
 
618
                }
 
619
        }
 
620
 
 
621
        return 0;
 
622
 
 
623
fail:
 
624
        kmod_unload_resources(ctx);
 
625
        return -ENOMEM;
 
626
}
 
627
 
 
628
KMOD_EXPORT void kmod_unload_resources(struct kmod_ctx *ctx)
 
629
{
 
630
        size_t i;
 
631
 
 
632
        if (ctx == NULL)
 
633
                return;
 
634
 
 
635
        for (i = 0; i < ARRAY_SIZE(index_files); i++) {
 
636
                if (ctx->indexes[i] != NULL) {
 
637
                        index_mm_close(ctx->indexes[i]);
 
638
                        ctx->indexes[i] = NULL;
 
639
                }
 
640
        }
 
641
}
 
642
 
 
643
KMOD_EXPORT int kmod_resolve_alias_options(struct kmod_ctx *ctx, const char *given_alias, char **options)
 
644
{
 
645
        struct kmod_list *modules = NULL, *l;
 
646
        char alias[NAME_MAX];
 
647
        char *opts = NULL;
 
648
        size_t optslen = 0;
 
649
        int err;
 
650
 
 
651
        if (ctx == NULL || options == NULL)
 
652
                return -ENOENT;
 
653
 
 
654
        modname_normalize(given_alias, alias, NULL);
 
655
 
 
656
        err = kmod_module_new_from_lookup(ctx, alias, &modules);
 
657
        if (err >= 0) {
 
658
                kmod_list_foreach(l, modules) {
 
659
                        const char *str = kmod_module_get_options(l->data);
 
660
                        size_t len;
 
661
                        void *tmp;
 
662
 
 
663
                        if (str == NULL)
 
664
                                continue;
 
665
                        len = strlen(str);
 
666
 
 
667
                        tmp = realloc(opts, optslen + len + 2);
 
668
                        if (tmp == NULL)
 
669
                                goto failed;
 
670
                        opts = tmp;
 
671
                        if (optslen > 0) {
 
672
                                opts[optslen] = ' ';
 
673
                                optslen++;
 
674
                        }
 
675
                        memcpy(opts + optslen, str, len);
 
676
                        optslen += len;
 
677
                        opts[optslen] = '\0';
 
678
                }
 
679
        }
 
680
 
 
681
        kmod_list_foreach(l, ctx->config->options) {
 
682
                const struct kmod_list *ml;
 
683
                const char *modname = kmod_option_get_modname(l);
 
684
                const char *str;
 
685
                bool already_done = false;
 
686
                size_t len;
 
687
                void *tmp;
 
688
 
 
689
                if (fnmatch(modname, alias, 0) != 0)
 
690
                        continue;
 
691
 
 
692
                kmod_list_foreach(ml, modules) {
 
693
                        const char *mln = kmod_module_get_name(ml->data);
 
694
                        if (fnmatch(modname, mln, 0) == 0) {
 
695
                                already_done = true;
 
696
                                break;
 
697
                        }
 
698
                }
 
699
                if (already_done)
 
700
                        continue;
 
701
 
 
702
                str = kmod_option_get_options(l);
 
703
                len = strlen(str);
 
704
                tmp = realloc(opts, optslen + len + 2);
 
705
                if (tmp == NULL)
 
706
                        goto failed;
 
707
                opts = tmp;
 
708
                if (optslen > 0) {
 
709
                        opts[optslen] = ' ';
 
710
                        optslen++;
 
711
                }
 
712
                memcpy(opts + optslen, str, len);
 
713
                optslen += len;
 
714
                opts[optslen] = '\0';
 
715
        }
 
716
 
 
717
        DBG(ctx, "alias=%s  options='%s'\n", alias, opts);
 
718
        kmod_module_unref_list(modules);
 
719
        *options = opts;
 
720
        return 0;
 
721
 
 
722
failed:
 
723
        kmod_module_unref_list(modules);
 
724
        free(opts);
 
725
        ERR(ctx, "out of memory\n");
 
726
        *options = NULL;
 
727
        return -ENOMEM;
 
728
}
 
729
 
 
730
const struct kmod_list *kmod_get_options(const struct kmod_ctx *ctx)
 
731
{
 
732
        return ctx->config->options;
 
733
}
 
734
 
 
735
const struct kmod_list *kmod_get_install_commands(const struct kmod_ctx *ctx)
 
736
{
 
737
        return ctx->config->install_commands;
 
738
}
 
739
 
 
740
const struct kmod_list *kmod_get_remove_commands(const struct kmod_ctx *ctx)
 
741
{
 
742
        return ctx->config->remove_commands;
 
743
}