1/******************************************************************************
2 *
3 * Module Name: osunixdir - Unix directory access interfaces
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2023, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include "acpi.h"
45
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <dirent.h>
50#include <fnmatch.h>
51#include <ctype.h>
52#include <sys/stat.h>
53
54/*
55 * Allocated structure returned from OsOpenDirectory
56 */
57typedef struct ExternalFindInfo
58{
59    char                        *DirPathname;
60    DIR                         *DirPtr;
61    char                        temp_buffer[256];
62    char                        *WildcardSpec;
63    char                        RequestedFileType;
64
65} EXTERNAL_FIND_INFO;
66
67
68/*******************************************************************************
69 *
70 * FUNCTION:    AcpiOsOpenDirectory
71 *
72 * PARAMETERS:  DirPathname         - Full pathname to the directory
73 *              WildcardSpec        - string of the form "*.c", etc.
74 *
75 * RETURN:      A directory "handle" to be used in subsequent search operations.
76 *              NULL returned on failure.
77 *
78 * DESCRIPTION: Open a directory in preparation for a wildcard search
79 *
80 ******************************************************************************/
81
82void *
83AcpiOsOpenDirectory (
84    char                    *DirPathname,
85    char                    *WildcardSpec,
86    char                    RequestedFileType)
87{
88    EXTERNAL_FIND_INFO      *ExternalInfo;
89    DIR                     *dir;
90
91
92    /* Allocate the info struct that will be returned to the caller */
93
94    ExternalInfo = calloc (1, sizeof (EXTERNAL_FIND_INFO));
95    if (!ExternalInfo)
96    {
97        return (NULL);
98    }
99
100    /* Get the directory stream */
101
102    dir = opendir (DirPathname);
103    if (!dir)
104    {
105        fprintf (stderr, "Cannot open directory - %s\n", DirPathname);
106        free (ExternalInfo);
107        return (NULL);
108    }
109
110    /* Save the info in the return structure */
111
112    ExternalInfo->WildcardSpec = WildcardSpec;
113    ExternalInfo->RequestedFileType = RequestedFileType;
114    ExternalInfo->DirPathname = DirPathname;
115    ExternalInfo->DirPtr = dir;
116    return (ExternalInfo);
117}
118
119
120/*******************************************************************************
121 *
122 * FUNCTION:    AcpiOsGetNextFilename
123 *
124 * PARAMETERS:  DirHandle           - Created via AcpiOsOpenDirectory
125 *
126 * RETURN:      Next filename matched. NULL if no more matches.
127 *
128 * DESCRIPTION: Get the next file in the directory that matches the wildcard
129 *              specification.
130 *
131 ******************************************************************************/
132
133char *
134AcpiOsGetNextFilename (
135    void                    *DirHandle)
136{
137    EXTERNAL_FIND_INFO      *ExternalInfo = DirHandle;
138    struct dirent           *dir_entry;
139    char                    *temp_str;
140    int                     str_len;
141    struct stat             temp_stat;
142    int                     err;
143
144
145    while ((dir_entry = readdir (ExternalInfo->DirPtr)))
146    {
147        if (!fnmatch (ExternalInfo->WildcardSpec, dir_entry->d_name, 0))
148        {
149            if (dir_entry->d_name[0] == '.')
150            {
151                continue;
152            }
153
154            str_len = strlen (dir_entry->d_name) +
155                        strlen (ExternalInfo->DirPathname) + 2;
156
157            temp_str = calloc (str_len, 1);
158            if (!temp_str)
159            {
160                fprintf (stderr,
161                    "Could not allocate buffer for temporary string\n");
162                return (NULL);
163            }
164
165            strcpy (temp_str, ExternalInfo->DirPathname);
166            strcat (temp_str, "/");
167            strcat (temp_str, dir_entry->d_name);
168
169            err = stat (temp_str, &temp_stat);
170            if (err == -1)
171            {
172                fprintf (stderr,
173                    "Cannot stat file (should not happen) - %s\n",
174                    temp_str);
175                free (temp_str);
176                return (NULL);
177            }
178
179            free (temp_str);
180
181            if ((S_ISDIR (temp_stat.st_mode)
182                && (ExternalInfo->RequestedFileType == REQUEST_DIR_ONLY))
183               ||
184               ((!S_ISDIR (temp_stat.st_mode)
185                && ExternalInfo->RequestedFileType == REQUEST_FILE_ONLY)))
186            {
187                /* copy to a temp buffer because dir_entry struct is on the stack */
188
189                strcpy (ExternalInfo->temp_buffer, dir_entry->d_name);
190                return (ExternalInfo->temp_buffer);
191            }
192        }
193    }
194
195    return (NULL);
196}
197
198
199/*******************************************************************************
200 *
201 * FUNCTION:    AcpiOsCloseDirectory
202 *
203 * PARAMETERS:  DirHandle           - Created via AcpiOsOpenDirectory
204 *
205 * RETURN:      None.
206 *
207 * DESCRIPTION: Close the open directory and cleanup.
208 *
209 ******************************************************************************/
210
211void
212AcpiOsCloseDirectory (
213    void                    *DirHandle)
214{
215    EXTERNAL_FIND_INFO      *ExternalInfo = DirHandle;
216
217
218    /* Close the directory and free allocations */
219
220    closedir (ExternalInfo->DirPtr);
221    free (DirHandle);
222}
223