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(p: temp_str, q: external_info->dir_pathname); |
117 | strcat(p: temp_str, q: "/" ); |
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 | |