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 - 2022, 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
acpi_os_open_directory(char * dir_pathname,char * wildcard_spec,char requested_file_type)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
acpi_os_get_next_filename(void * dir_handle)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
acpi_os_close_directory(void * dir_handle)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