1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /****************************************************************************** 3 * 4 * Module Name: osunixdir - Unix directory access interfaces 5 * 6 * Copyright (C) 2000 - 2023, Intel Corp. 7 * 8 *****************************************************************************/ 9 10 #include <acpi/acpi.h> 11 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <dirent.h> 16 #include <fnmatch.h> 17 #include <ctype.h> 18 #include <sys/stat.h> 19 20 /* 21 * Allocated structure returned from os_open_directory 22 */ 23 typedef struct external_find_info { 24 char *dir_pathname; 25 DIR *dir_ptr; 26 char temp_buffer[256]; 27 char *wildcard_spec; 28 char requested_file_type; 29 30 } external_find_info; 31 32 /******************************************************************************* 33 * 34 * FUNCTION: acpi_os_open_directory 35 * 36 * PARAMETERS: dir_pathname - Full pathname to the directory 37 * wildcard_spec - string of the form "*.c", etc. 38 * 39 * RETURN: A directory "handle" to be used in subsequent search operations. 40 * NULL returned on failure. 41 * 42 * DESCRIPTION: Open a directory in preparation for a wildcard search 43 * 44 ******************************************************************************/ 45 46 void *acpi_os_open_directory(char *dir_pathname, 47 char *wildcard_spec, char requested_file_type) 48 { 49 struct external_find_info *external_info; 50 DIR *dir; 51 52 /* Allocate the info struct that will be returned to the caller */ 53 54 external_info = calloc(1, sizeof(struct external_find_info)); 55 if (!external_info) { 56 return (NULL); 57 } 58 59 /* Get the directory stream */ 60 61 dir = opendir(dir_pathname); 62 if (!dir) { 63 fprintf(stderr, "Cannot open directory - %s\n", dir_pathname); 64 free(external_info); 65 return (NULL); 66 } 67 68 /* Save the info in the return structure */ 69 70 external_info->wildcard_spec = wildcard_spec; 71 external_info->requested_file_type = requested_file_type; 72 external_info->dir_pathname = dir_pathname; 73 external_info->dir_ptr = dir; 74 return (external_info); 75 } 76 77 /******************************************************************************* 78 * 79 * FUNCTION: acpi_os_get_next_filename 80 * 81 * PARAMETERS: dir_handle - Created via acpi_os_open_directory 82 * 83 * RETURN: Next filename matched. NULL if no more matches. 84 * 85 * DESCRIPTION: Get the next file in the directory that matches the wildcard 86 * specification. 87 * 88 ******************************************************************************/ 89 90 char *acpi_os_get_next_filename(void *dir_handle) 91 { 92 struct external_find_info *external_info = dir_handle; 93 struct dirent *dir_entry; 94 char *temp_str; 95 int str_len; 96 struct stat temp_stat; 97 int err; 98 99 while ((dir_entry = readdir(external_info->dir_ptr))) { 100 if (!fnmatch 101 (external_info->wildcard_spec, dir_entry->d_name, 0)) { 102 if (dir_entry->d_name[0] == '.') { 103 continue; 104 } 105 106 str_len = strlen(dir_entry->d_name) + 107 strlen(external_info->dir_pathname) + 2; 108 109 temp_str = calloc(str_len, 1); 110 if (!temp_str) { 111 fprintf(stderr, 112 "Could not allocate buffer for temporary string\n"); 113 return (NULL); 114 } 115 116 strcpy(temp_str, external_info->dir_pathname); 117 strcat(temp_str, "/"); 118 strcat(temp_str, dir_entry->d_name); 119 120 err = stat(temp_str, &temp_stat); 121 if (err == -1) { 122 fprintf(stderr, 123 "Cannot stat file (should not happen) - %s\n", 124 temp_str); 125 free(temp_str); 126 return (NULL); 127 } 128 129 free(temp_str); 130 131 if ((S_ISDIR(temp_stat.st_mode) 132 && (external_info->requested_file_type == 133 REQUEST_DIR_ONLY)) 134 || ((!S_ISDIR(temp_stat.st_mode) 135 && external_info->requested_file_type == 136 REQUEST_FILE_ONLY))) { 137 138 /* copy to a temp buffer because dir_entry struct is on the stack */ 139 140 strcpy(external_info->temp_buffer, 141 dir_entry->d_name); 142 return (external_info->temp_buffer); 143 } 144 } 145 } 146 147 return (NULL); 148 } 149 150 /******************************************************************************* 151 * 152 * FUNCTION: acpi_os_close_directory 153 * 154 * PARAMETERS: dir_handle - Created via acpi_os_open_directory 155 * 156 * RETURN: None. 157 * 158 * DESCRIPTION: Close the open directory and cleanup. 159 * 160 ******************************************************************************/ 161 162 void acpi_os_close_directory(void *dir_handle) 163 { 164 struct external_find_info *external_info = dir_handle; 165 166 /* Close the directory and free allocations */ 167 168 closedir(external_info->dir_ptr); 169 free(dir_handle); 170 } 171