1 /* 2 * libkmod - interface to kernel module operations 3 * 4 * Copyright (C) 2011-2013 ProFUSION embedded systems 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include <assert.h> 21 #include <ctype.h> 22 #include <errno.h> 23 #include <fnmatch.h> 24 #include <limits.h> 25 #include <stdarg.h> 26 #include <stddef.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <unistd.h> 31 #include <sys/stat.h> 32 #include <sys/utsname.h> 33 34 #include <shared/hash.h> 35 #include <shared/util.h> 36 37 #include "libkmod.h" 38 #include "libkmod-internal.h" 39 #include "libkmod-index.h" 40 41 #define KMOD_HASH_SIZE (256) 42 #define KMOD_LRU_MAX (128) 43 #define _KMOD_INDEX_MODULES_SIZE KMOD_INDEX_MODULES_BUILTIN + 1 44 45 /** 46 * SECTION:libkmod 47 * @short_description: libkmod context 48 * 49 * The context contains the default values for the library user, 50 * and is passed to all library operations. 51 */ 52 53 static struct _index_files { 54 const char *fn; 55 const char *prefix; 56 } index_files[] = { 57 [KMOD_INDEX_MODULES_DEP] = { .fn = "modules.dep", .prefix = "" }, 58 [KMOD_INDEX_MODULES_ALIAS] = { .fn = "modules.alias", .prefix = "alias " }, 59 [KMOD_INDEX_MODULES_SYMBOL] = { .fn = "modules.symbols", .prefix = "alias "}, 60 [KMOD_INDEX_MODULES_BUILTIN] = { .fn = "modules.builtin", .prefix = ""}, 61 }; 62 63 static const char *default_config_paths[] = { 64 SYSCONFDIR "/modprobe.d", 65 "/run/modprobe.d", 66 "/lib/modprobe.d", 67 NULL 68 }; 69 70 /** 71 * kmod_ctx: 72 * 73 * Opaque object representing the library context. 74 */ 75 struct kmod_ctx { 76 int refcount; 77 int log_priority; 78 void (*log_fn)(void *data, 79 int priority, const char *file, int line, 80 const char *fn, const char *format, va_list args); 81 void *log_data; 82 const void *userdata; 83 char *dirname; 84 struct kmod_config *config; 85 struct hash *modules_by_name; 86 struct index_mm *indexes[_KMOD_INDEX_MODULES_SIZE]; 87 unsigned long long indexes_stamp[_KMOD_INDEX_MODULES_SIZE]; 88 }; 89 90 void kmod_log(const struct kmod_ctx *ctx, 91 int priority, const char *file, int line, const char *fn, 92 const char *format, ...) 93 { 94 va_list args; 95 96 if (ctx->log_fn == NULL) 97 return; 98 99 va_start(args, format); 100 ctx->log_fn(ctx->log_data, priority, file, line, fn, format, args); 101 va_end(args); 102 } 103 104 _printf_format_(6, 0) 105 static void log_filep(void *data, 106 int priority, const char *file, int line, 107 const char *fn, const char *format, va_list args) 108 { 109 FILE *fp = data; 110 #ifdef ENABLE_DEBUG 111 char buf[16]; 112 const char *priname; 113 switch (priority) { 114 case LOG_EMERG: 115 priname = "EMERGENCY"; 116 break; 117 case LOG_ALERT: 118 priname = "ALERT"; 119 break; 120 case LOG_CRIT: 121 priname = "CRITICAL"; 122 break; 123 case LOG_ERR: 124 priname = "ERROR"; 125 break; 126 case LOG_WARNING: 127 priname = "WARNING"; 128 break; 129 case LOG_NOTICE: 130 priname = "NOTICE"; 131 break; 132 case LOG_INFO: 133 priname = "INFO"; 134 break; 135 case LOG_DEBUG: 136 priname = "DEBUG"; 137 break; 138 default: 139 snprintf(buf, sizeof(buf), "L:%d", priority); 140 priname = buf; 141 } 142 fprintf(fp, "libkmod: %s %s:%d %s: ", priname, file, line, fn); 143 #else 144 fprintf(fp, "libkmod: %s: ", fn); 145 #endif 146 vfprintf(fp, format, args); 147 } 148 149 150 /** 151 * kmod_get_dirname: 152 * @ctx: kmod library context 153 * 154 * Retrieve the absolute path used for linux modules in this context. The path 155 * is computed from the arguments to kmod_new(). 156 */ 157 KMOD_EXPORT const char *kmod_get_dirname(const struct kmod_ctx *ctx) 158 { 159 return ctx->dirname; 160 } 161 162 /** 163 * kmod_get_userdata: 164 * @ctx: kmod library context 165 * 166 * Retrieve stored data pointer from library context. This might be useful 167 * to access from callbacks. 168 * 169 * Returns: stored userdata 170 */ 171 KMOD_EXPORT void *kmod_get_userdata(const struct kmod_ctx *ctx) 172 { 173 if (ctx == NULL) 174 return NULL; 175 return (void *)ctx->userdata; 176 } 177 178 /** 179 * kmod_set_userdata: 180 * @ctx: kmod library context 181 * @userdata: data pointer 182 * 183 * Store custom @userdata in the library context. 184 */ 185 KMOD_EXPORT void kmod_set_userdata(struct kmod_ctx *ctx, const void *userdata) 186 { 187 if (ctx == NULL) 188 return; 189 ctx->userdata = userdata; 190 } 191 192 static int log_priority(const char *priority) 193 { 194 char *endptr; 195 int prio; 196 197 prio = strtol(priority, &endptr, 10); 198 if (endptr[0] == '\0' || isspace(endptr[0])) 199 return prio; 200 if (strncmp(priority, "err", 3) == 0) 201 return LOG_ERR; 202 if (strncmp(priority, "info", 4) == 0) 203 return LOG_INFO; 204 if (strncmp(priority, "debug", 5) == 0) 205 return LOG_DEBUG; 206 return 0; 207 } 208 209 static const char *dirname_default_prefix = "/lib/modules"; 210 211 static char *get_kernel_release(const char *dirname) 212 { 213 struct utsname u; 214 char *p; 215 216 if (dirname != NULL) 217 return path_make_absolute_cwd(dirname); 218 219 if (uname(&u) < 0) 220 return NULL; 221 222 if (asprintf(&p, "%s/%s", dirname_default_prefix, u.release) < 0) 223 return NULL; 224 225 return p; 226 } 227 228 /** 229 * kmod_new: 230 * @dirname: what to consider as linux module's directory, if NULL 231 * defaults to /lib/modules/`uname -r`. If it's relative, 232 * it's treated as relative to the current working directory. 233 * Otherwise, give an absolute dirname. 234 * @config_paths: ordered array of paths (directories or files) where 235 * to load from user-defined configuration parameters such as 236 * alias, blacklists, commands (install, remove). If 237 * NULL defaults to /run/modprobe.d, /etc/modprobe.d and 238 * /lib/modprobe.d. Give an empty vector if configuration should 239 * not be read. This array must be null terminated. 240 * 241 * Create kmod library context. This reads the kmod configuration 242 * and fills in the default values. 243 * 244 * The initial refcount is 1, and needs to be decremented to 245 * release the resources of the kmod library context. 246 * 247 * Returns: a new kmod library context 248 */ 249 KMOD_EXPORT struct kmod_ctx *kmod_new(const char *dirname, 250 const char * const *config_paths) 251 { 252 const char *env; 253 struct kmod_ctx *ctx; 254 int err; 255 256 ctx = calloc(1, sizeof(struct kmod_ctx)); 257 if (!ctx) 258 return NULL; 259 260 ctx->refcount = 1; 261 ctx->log_fn = log_filep; 262 ctx->log_data = stderr; 263 ctx->log_priority = LOG_ERR; 264 265 ctx->dirname = get_kernel_release(dirname); 266 267 /* environment overwrites config */ 268 env = secure_getenv("KMOD_LOG"); 269 if (env != NULL) 270 kmod_set_log_priority(ctx, log_priority(env)); 271 272 if (config_paths == NULL) 273 config_paths = default_config_paths; 274 err = kmod_config_new(ctx, &ctx->config, config_paths); 275 if (err < 0) { 276 ERR(ctx, "could not create config\n"); 277 goto fail; 278 } 279 280 ctx->modules_by_name = hash_new(KMOD_HASH_SIZE, NULL); 281 if (ctx->modules_by_name == NULL) { 282 ERR(ctx, "could not create by-name hash\n"); 283 goto fail; 284 } 285 286 INFO(ctx, "ctx %p created\n", ctx); 287 DBG(ctx, "log_priority=%d\n", ctx->log_priority); 288 289 return ctx; 290 291 fail: 292 free(ctx->modules_by_name); 293 free(ctx->dirname); 294 free(ctx); 295 return NULL; 296 } 297 298 /** 299 * kmod_ref: 300 * @ctx: kmod library context 301 * 302 * Take a reference of the kmod library context. 303 * 304 * Returns: the passed kmod library context 305 */ 306 KMOD_EXPORT struct kmod_ctx *kmod_ref(struct kmod_ctx *ctx) 307 { 308 if (ctx == NULL) 309 return NULL; 310 ctx->refcount++; 311 return ctx; 312 } 313 314 /** 315 * kmod_unref: 316 * @ctx: kmod library context 317 * 318 * Drop a reference of the kmod library context. If the refcount 319 * reaches zero, the resources of the context will be released. 320 * 321 * Returns: the passed kmod library context or NULL if it's freed 322 */ 323 KMOD_EXPORT struct kmod_ctx *kmod_unref(struct kmod_ctx *ctx) 324 { 325 if (ctx == NULL) 326 return NULL; 327 328 if (--ctx->refcount > 0) 329 return ctx; 330 331 INFO(ctx, "context %p released\n", ctx); 332 333 kmod_unload_resources(ctx); 334 hash_free(ctx->modules_by_name); 335 free(ctx->dirname); 336 if (ctx->config) 337 kmod_config_free(ctx->config); 338 339 free(ctx); 340 return NULL; 341 } 342 343 /** 344 * kmod_set_log_fn: 345 * @ctx: kmod library context 346 * @log_fn: function to be called for logging messages 347 * @data: data to pass to log function 348 * 349 * The built-in logging writes to stderr. It can be 350 * overridden by a custom function, to plug log messages 351 * into the user's logging functionality. 352 */ 353 KMOD_EXPORT void kmod_set_log_fn(struct kmod_ctx *ctx, 354 void (*log_fn)(void *data, 355 int priority, const char *file, 356 int line, const char *fn, 357 const char *format, va_list args), 358 const void *data) 359 { 360 if (ctx == NULL) 361 return; 362 ctx->log_fn = log_fn; 363 ctx->log_data = (void *)data; 364 INFO(ctx, "custom logging function %p registered\n", log_fn); 365 } 366 367 /** 368 * kmod_get_log_priority: 369 * @ctx: kmod library context 370 * 371 * Returns: the current logging priority 372 */ 373 KMOD_EXPORT int kmod_get_log_priority(const struct kmod_ctx *ctx) 374 { 375 if (ctx == NULL) 376 return -1; 377 return ctx->log_priority; 378 } 379 380 /** 381 * kmod_set_log_priority: 382 * @ctx: kmod library context 383 * @priority: the new logging priority 384 * 385 * Set the current logging priority. The value controls which messages 386 * are logged. 387 */ 388 KMOD_EXPORT void kmod_set_log_priority(struct kmod_ctx *ctx, int priority) 389 { 390 if (ctx == NULL) 391 return; 392 ctx->log_priority = priority; 393 } 394 395 struct kmod_module *kmod_pool_get_module(struct kmod_ctx *ctx, 396 const char *key) 397 { 398 struct kmod_module *mod; 399 400 mod = hash_find(ctx->modules_by_name, key); 401 402 DBG(ctx, "get module name='%s' found=%p\n", key, mod); 403 404 return mod; 405 } 406 407 void kmod_pool_add_module(struct kmod_ctx *ctx, struct kmod_module *mod, 408 const char *key) 409 { 410 DBG(ctx, "add %p key='%s'\n", mod, key); 411 412 hash_add(ctx->modules_by_name, key, mod); 413 } 414 415 void kmod_pool_del_module(struct kmod_ctx *ctx, struct kmod_module *mod, 416 const char *key) 417 { 418 DBG(ctx, "del %p key='%s'\n", mod, key); 419 420 hash_del(ctx->modules_by_name, key); 421 } 422 423 static int kmod_lookup_alias_from_alias_bin(struct kmod_ctx *ctx, 424 enum kmod_index index_number, 425 const char *name, 426 struct kmod_list **list) 427 { 428 int err, nmatch = 0; 429 struct index_file *idx; 430 struct index_value *realnames, *realname; 431 432 if (ctx->indexes[index_number] != NULL) { 433 DBG(ctx, "use mmaped index '%s' for name=%s\n", 434 index_files[index_number].fn, name); 435 realnames = index_mm_searchwild(ctx->indexes[index_number], 436 name); 437 } else { 438 char fn[PATH_MAX]; 439 440 snprintf(fn, sizeof(fn), "%s/%s.bin", ctx->dirname, 441 index_files[index_number].fn); 442 443 DBG(ctx, "file=%s name=%s\n", fn, name); 444 445 idx = index_file_open(fn); 446 if (idx == NULL) 447 return -ENOSYS; 448 449 realnames = index_searchwild(idx, name); 450 index_file_close(idx); 451 } 452 453 for (realname = realnames; realname; realname = realname->next) { 454 struct kmod_module *mod; 455 456 err = kmod_module_new_from_alias(ctx, name, realname->value, &mod); 457 if (err < 0) { 458 ERR(ctx, "Could not create module for alias=%s realname=%s: %s\n", 459 name, realname->value, strerror(-err)); 460 goto fail; 461 } 462 463 *list = kmod_list_append(*list, mod); 464 nmatch++; 465 } 466 467 index_values_free(realnames); 468 return nmatch; 469 470 fail: 471 *list = kmod_list_remove_n_latest(*list, nmatch); 472 index_values_free(realnames); 473 return err; 474 475 } 476 477 int kmod_lookup_alias_from_symbols_file(struct kmod_ctx *ctx, const char *name, 478 struct kmod_list **list) 479 { 480 if (!strstartswith(name, "symbol:")) 481 return 0; 482 483 return kmod_lookup_alias_from_alias_bin(ctx, KMOD_INDEX_MODULES_SYMBOL, 484 name, list); 485 } 486 487 int kmod_lookup_alias_from_aliases_file(struct kmod_ctx *ctx, const char *name, 488 struct kmod_list **list) 489 { 490 return kmod_lookup_alias_from_alias_bin(ctx, KMOD_INDEX_MODULES_ALIAS, 491 name, list); 492 } 493 494 static char *lookup_builtin_file(struct kmod_ctx *ctx, const char *name) 495 { 496 char *line; 497 498 if (ctx->indexes[KMOD_INDEX_MODULES_BUILTIN]) { 499 DBG(ctx, "use mmaped index '%s' modname=%s\n", 500 index_files[KMOD_INDEX_MODULES_BUILTIN].fn, 501 name); 502 line = index_mm_search(ctx->indexes[KMOD_INDEX_MODULES_BUILTIN], 503 name); 504 } else { 505 struct index_file *idx; 506 char fn[PATH_MAX]; 507 508 snprintf(fn, sizeof(fn), "%s/%s.bin", ctx->dirname, 509 index_files[KMOD_INDEX_MODULES_BUILTIN].fn); 510 DBG(ctx, "file=%s modname=%s\n", fn, name); 511 512 idx = index_file_open(fn); 513 if (idx == NULL) { 514 DBG(ctx, "could not open builtin file '%s'\n", fn); 515 return NULL; 516 } 517 518 line = index_search(idx, name); 519 index_file_close(idx); 520 } 521 522 return line; 523 } 524 525 int kmod_lookup_alias_from_builtin_file(struct kmod_ctx *ctx, const char *name, 526 struct kmod_list **list) 527 { 528 char *line; 529 int err = 0; 530 531 assert(*list == NULL); 532 533 line = lookup_builtin_file(ctx, name); 534 if (line != NULL) { 535 struct kmod_module *mod; 536 537 err = kmod_module_new_from_name(ctx, name, &mod); 538 if (err < 0) { 539 ERR(ctx, "Could not create module from name %s: %s\n", 540 name, strerror(-err)); 541 goto finish; 542 } 543 544 /* already mark it as builtin since it's being created from 545 * this index */ 546 kmod_module_set_builtin(mod, true); 547 *list = kmod_list_append(*list, mod); 548 if (*list == NULL) 549 err = -ENOMEM; 550 } 551 552 finish: 553 free(line); 554 return err; 555 } 556 557 bool kmod_lookup_alias_is_builtin(struct kmod_ctx *ctx, const char *name) 558 { 559 _cleanup_free_ char *line; 560 561 line = lookup_builtin_file(ctx, name); 562 563 return line != NULL; 564 } 565 566 char *kmod_search_moddep(struct kmod_ctx *ctx, const char *name) 567 { 568 struct index_file *idx; 569 char fn[PATH_MAX]; 570 char *line; 571 572 if (ctx->indexes[KMOD_INDEX_MODULES_DEP]) { 573 DBG(ctx, "use mmaped index '%s' modname=%s\n", 574 index_files[KMOD_INDEX_MODULES_DEP].fn, name); 575 return index_mm_search(ctx->indexes[KMOD_INDEX_MODULES_DEP], 576 name); 577 } 578 579 snprintf(fn, sizeof(fn), "%s/%s.bin", ctx->dirname, 580 index_files[KMOD_INDEX_MODULES_DEP].fn); 581 582 DBG(ctx, "file=%s modname=%s\n", fn, name); 583 584 idx = index_file_open(fn); 585 if (idx == NULL) { 586 DBG(ctx, "could not open moddep file '%s'\n", fn); 587 return NULL; 588 } 589 590 line = index_search(idx, name); 591 index_file_close(idx); 592 593 return line; 594 } 595 596 int kmod_lookup_alias_from_moddep_file(struct kmod_ctx *ctx, const char *name, 597 struct kmod_list **list) 598 { 599 char *line; 600 int n = 0; 601 602 /* 603 * Module names do not contain ':'. Return early if we know it will 604 * not be found. 605 */ 606 if (strchr(name, ':')) 607 return 0; 608 609 line = kmod_search_moddep(ctx, name); 610 if (line != NULL) { 611 struct kmod_module *mod; 612 613 n = kmod_module_new_from_name(ctx, name, &mod); 614 if (n < 0) { 615 ERR(ctx, "Could not create module from name %s: %s\n", 616 name, strerror(-n)); 617 goto finish; 618 } 619 620 *list = kmod_list_append(*list, mod); 621 kmod_module_parse_depline(mod, line); 622 } 623 624 finish: 625 free(line); 626 627 return n; 628 } 629 630 int kmod_lookup_alias_from_config(struct kmod_ctx *ctx, const char *name, 631 struct kmod_list **list) 632 { 633 struct kmod_config *config = ctx->config; 634 struct kmod_list *l; 635 int err, nmatch = 0; 636 637 kmod_list_foreach(l, config->aliases) { 638 const char *aliasname = kmod_alias_get_name(l); 639 const char *modname = kmod_alias_get_modname(l); 640 641 if (fnmatch(aliasname, name, 0) == 0) { 642 struct kmod_module *mod; 643 644 err = kmod_module_new_from_alias(ctx, aliasname, 645 modname, &mod); 646 if (err < 0) { 647 ERR(ctx, "Could not create module for alias=%s modname=%s: %s\n", 648 name, modname, strerror(-err)); 649 goto fail; 650 } 651 652 *list = kmod_list_append(*list, mod); 653 nmatch++; 654 } 655 } 656 657 return nmatch; 658 659 fail: 660 *list = kmod_list_remove_n_latest(*list, nmatch); 661 return err; 662 } 663 664 int kmod_lookup_alias_from_commands(struct kmod_ctx *ctx, const char *name, 665 struct kmod_list **list) 666 { 667 struct kmod_config *config = ctx->config; 668 struct kmod_list *l, *node; 669 int err, nmatch = 0; 670 671 kmod_list_foreach(l, config->install_commands) { 672 const char *modname = kmod_command_get_modname(l); 673 674 if (streq(modname, name)) { 675 const char *cmd = kmod_command_get_command(l); 676 struct kmod_module *mod; 677 678 err = kmod_module_new_from_name(ctx, modname, &mod); 679 if (err < 0) { 680 ERR(ctx, "Could not create module from name %s: %s\n", 681 modname, strerror(-err)); 682 return err; 683 } 684 685 node = kmod_list_append(*list, mod); 686 if (node == NULL) { 687 ERR(ctx, "out of memory\n"); 688 return -ENOMEM; 689 } 690 691 *list = node; 692 nmatch = 1; 693 694 kmod_module_set_install_commands(mod, cmd); 695 696 /* 697 * match only the first one, like modprobe from 698 * module-init-tools does 699 */ 700 break; 701 } 702 } 703 704 if (nmatch) 705 return nmatch; 706 707 kmod_list_foreach(l, config->remove_commands) { 708 const char *modname = kmod_command_get_modname(l); 709 710 if (streq(modname, name)) { 711 const char *cmd = kmod_command_get_command(l); 712 struct kmod_module *mod; 713 714 err = kmod_module_new_from_name(ctx, modname, &mod); 715 if (err < 0) { 716 ERR(ctx, "Could not create module from name %s: %s\n", 717 modname, strerror(-err)); 718 return err; 719 } 720 721 node = kmod_list_append(*list, mod); 722 if (node == NULL) { 723 ERR(ctx, "out of memory\n"); 724 return -ENOMEM; 725 } 726 727 *list = node; 728 nmatch = 1; 729 730 kmod_module_set_remove_commands(mod, cmd); 731 732 /* 733 * match only the first one, like modprobe from 734 * module-init-tools does 735 */ 736 break; 737 } 738 } 739 740 return nmatch; 741 } 742 743 void kmod_set_modules_visited(struct kmod_ctx *ctx, bool visited) 744 { 745 struct hash_iter iter; 746 const void *v; 747 748 hash_iter_init(ctx->modules_by_name, &iter); 749 while (hash_iter_next(&iter, NULL, &v)) 750 kmod_module_set_visited((struct kmod_module *)v, visited); 751 } 752 753 void kmod_set_modules_required(struct kmod_ctx *ctx, bool required) 754 { 755 struct hash_iter iter; 756 const void *v; 757 758 hash_iter_init(ctx->modules_by_name, &iter); 759 while (hash_iter_next(&iter, NULL, &v)) 760 kmod_module_set_required((struct kmod_module *)v, required); 761 } 762 763 static bool is_cache_invalid(const char *path, unsigned long long stamp) 764 { 765 struct stat st; 766 767 if (stat(path, &st) < 0) 768 return true; 769 770 if (stamp != stat_mstamp(&st)) 771 return true; 772 773 return false; 774 } 775 776 /** 777 * kmod_validate_resources: 778 * @ctx: kmod library context 779 * 780 * Check if indexes and configuration files changed on disk and the current 781 * context is not valid anymore. 782 * 783 * Returns: KMOD_RESOURCES_OK if resources are still valid, 784 * KMOD_RESOURCES_MUST_RELOAD if it's sufficient to call 785 * kmod_unload_resources() and kmod_load_resources() or 786 * KMOD_RESOURCES_MUST_RECREATE if @ctx must be re-created. 787 */ 788 KMOD_EXPORT int kmod_validate_resources(struct kmod_ctx *ctx) 789 { 790 struct kmod_list *l; 791 size_t i; 792 793 if (ctx == NULL || ctx->config == NULL) 794 return KMOD_RESOURCES_MUST_RECREATE; 795 796 kmod_list_foreach(l, ctx->config->paths) { 797 struct kmod_config_path *cf = l->data; 798 799 if (is_cache_invalid(cf->path, cf->stamp)) 800 return KMOD_RESOURCES_MUST_RECREATE; 801 } 802 803 for (i = 0; i < _KMOD_INDEX_MODULES_SIZE; i++) { 804 char path[PATH_MAX]; 805 806 if (ctx->indexes[i] == NULL) 807 continue; 808 809 snprintf(path, sizeof(path), "%s/%s.bin", ctx->dirname, 810 index_files[i].fn); 811 812 if (is_cache_invalid(path, ctx->indexes_stamp[i])) 813 return KMOD_RESOURCES_MUST_RELOAD; 814 } 815 816 return KMOD_RESOURCES_OK; 817 } 818 819 /** 820 * kmod_load_resources: 821 * @ctx: kmod library context 822 * 823 * Load indexes and keep them open in @ctx. This way it's faster to lookup 824 * information within the indexes. If this function is not called before a 825 * search, the necessary index is always opened and closed. 826 * 827 * If user will do more than one or two lookups, insertions, deletions, most 828 * likely it's good to call this function first. Particularly in a daemon like 829 * udev that on bootup issues hundreds of calls to lookup the index, calling 830 * this function will speedup the searches. 831 * 832 * Returns: 0 on success or < 0 otherwise. 833 */ 834 KMOD_EXPORT int kmod_load_resources(struct kmod_ctx *ctx) 835 { 836 size_t i; 837 838 if (ctx == NULL) 839 return -ENOENT; 840 841 for (i = 0; i < _KMOD_INDEX_MODULES_SIZE; i++) { 842 char path[PATH_MAX]; 843 844 if (ctx->indexes[i] != NULL) { 845 INFO(ctx, "Index %s already loaded\n", 846 index_files[i].fn); 847 continue; 848 } 849 850 snprintf(path, sizeof(path), "%s/%s.bin", ctx->dirname, 851 index_files[i].fn); 852 ctx->indexes[i] = index_mm_open(ctx, path, 853 &ctx->indexes_stamp[i]); 854 if (ctx->indexes[i] == NULL) 855 goto fail; 856 } 857 858 return 0; 859 860 fail: 861 kmod_unload_resources(ctx); 862 return -ENOMEM; 863 } 864 865 /** 866 * kmod_unload_resources: 867 * @ctx: kmod library context 868 * 869 * Unload all the indexes. This will free the resources to maintain the index 870 * open and all subsequent searches will need to open and close the index. 871 * 872 * User is free to call kmod_load_resources() and kmod_unload_resources() as 873 * many times as wanted during the lifecycle of @ctx. For example, if a daemon 874 * knows that when starting up it will lookup a lot of modules, it could call 875 * kmod_load_resources() and after the first burst of searches is gone, it 876 * could free the resources by calling kmod_unload_resources(). 877 * 878 * Returns: 0 on success or < 0 otherwise. 879 */ 880 KMOD_EXPORT void kmod_unload_resources(struct kmod_ctx *ctx) 881 { 882 size_t i; 883 884 if (ctx == NULL) 885 return; 886 887 for (i = 0; i < _KMOD_INDEX_MODULES_SIZE; i++) { 888 if (ctx->indexes[i] != NULL) { 889 index_mm_close(ctx->indexes[i]); 890 ctx->indexes[i] = NULL; 891 ctx->indexes_stamp[i] = 0; 892 } 893 } 894 } 895 896 /** 897 * kmod_dump_index: 898 * @ctx: kmod library context 899 * @type: index to dump, valid indexes are 900 * KMOD_INDEX_MODULES_DEP: index of module dependencies; 901 * KMOD_INDEX_MODULES_ALIAS: index of module aliases; 902 * KMOD_INDEX_MODULES_SYMBOL: index of symbol aliases; 903 * KMOD_INDEX_MODULES_BUILTIN: index of builtin module. 904 * @fd: file descriptor to dump index to 905 * 906 * Dump index to file descriptor. Note that this function doesn't use stdio.h 907 * so call fflush() before calling this function to be sure data is written in 908 * order. 909 * 910 * Returns: 0 on success or < 0 otherwise. 911 */ 912 KMOD_EXPORT int kmod_dump_index(struct kmod_ctx *ctx, enum kmod_index type, 913 int fd) 914 { 915 if (ctx == NULL) 916 return -ENOSYS; 917 918 if (type < 0 || type >= _KMOD_INDEX_MODULES_SIZE) 919 return -ENOENT; 920 921 if (ctx->indexes[type] != NULL) { 922 DBG(ctx, "use mmaped index '%s'\n", index_files[type].fn); 923 index_mm_dump(ctx->indexes[type], fd, 924 index_files[type].prefix); 925 } else { 926 char fn[PATH_MAX]; 927 struct index_file *idx; 928 929 snprintf(fn, sizeof(fn), "%s/%s.bin", ctx->dirname, 930 index_files[type].fn); 931 932 DBG(ctx, "file=%s\n", fn); 933 934 idx = index_file_open(fn); 935 if (idx == NULL) 936 return -ENOSYS; 937 938 index_dump(idx, fd, index_files[type].prefix); 939 index_file_close(idx); 940 } 941 942 return 0; 943 } 944 945 const struct kmod_config *kmod_get_config(const struct kmod_ctx *ctx) 946 { 947 return ctx->config; 948 } 949