| 608 | } |
| 609 | |
| 610 | static void config_search(const char *boarddir, |
| 611 | config_callback callback, void *data) |
| 612 | { |
| 613 | DIR *dir; |
| 614 | struct dirent *dp; |
| 615 | struct stat buf; |
| 616 | char *parent; |
| 617 | char *child; |
| 618 | |
| 619 | /* Skip over any leading '/' or '\\'. This happens on the first second |
| 620 | * call because the starting boarddir is "" |
| 621 | */ |
| 622 | |
| 623 | if (boarddir[0] == g_delim) |
| 624 | { |
| 625 | boarddir++; |
| 626 | } |
| 627 | |
| 628 | /* Get the full directory path and open it */ |
| 629 | |
| 630 | snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", g_configtop, g_delim, boarddir); |
| 631 | dir = opendir(g_buffer); |
| 632 | if (!dir) |
| 633 | { |
| 634 | fprintf(stderr, "ERROR: Could not open %s: %s\n", |
| 635 | g_buffer, strerror(errno)); |
| 636 | return; |
| 637 | } |
| 638 | |
| 639 | /* Make a copy of the path to the directory */ |
| 640 | |
| 641 | parent = strdup(g_buffer); |
| 642 | |
| 643 | /* Visit each entry in the directory */ |
| 644 | |
| 645 | while ((dp = readdir(dir)) != NULL) |
| 646 | { |
| 647 | /* Ignore directory entries that start with '.' */ |
| 648 | |
| 649 | if (dp->d_name[0] == '.') |
| 650 | { |
| 651 | continue; |
| 652 | } |
| 653 | |
| 654 | /* Get a properly terminated copy of d_name (if d_name is long it may |
| 655 | * not include a NUL terminator. |
| 656 | */ |
| 657 | |
| 658 | child = strndup(dp->d_name, NAME_MAX); |
| 659 | |
| 660 | /* Get the full path to d_name and stat the file/directory */ |
| 661 | |
| 662 | snprintf(g_buffer, BUFFER_SIZE, "%s%c%s", parent, g_delim, child); |
| 663 | if (stat(g_buffer, &buf) < 0) |
| 664 | { |
| 665 | fprintf(stderr, "ERROR: stat of %s failed: %s\n", |
| 666 | g_buffer, strerror(errno)); |
| 667 | free(child); |