1 | /*
|
---|
2 | * Copyright 2004-2016 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | *
|
---|
4 | * Licensed under the OpenSSL license (the "License"). You may not use
|
---|
5 | * this file except in compliance with the License. You can obtain a copy
|
---|
6 | * in the file LICENSE in the source distribution or at
|
---|
7 | * https://www.openssl.org/source/license.html
|
---|
8 | */
|
---|
9 |
|
---|
10 | /*
|
---|
11 | * This file is dual-licensed and is also available under the following
|
---|
12 | * terms:
|
---|
13 | *
|
---|
14 | * Copyright (c) 2004, Richard Levitte <[email protected]>
|
---|
15 | * All rights reserved.
|
---|
16 | *
|
---|
17 | * Redistribution and use in source and binary forms, with or without
|
---|
18 | * modification, are permitted provided that the following conditions
|
---|
19 | * are met:
|
---|
20 | * 1. Redistributions of source code must retain the above copyright
|
---|
21 | * notice, this list of conditions and the following disclaimer.
|
---|
22 | * 2. Redistributions in binary form must reproduce the above copyright
|
---|
23 | * notice, this list of conditions and the following disclaimer in the
|
---|
24 | * documentation and/or other materials provided with the distribution.
|
---|
25 | *
|
---|
26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
---|
27 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
---|
28 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
---|
29 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
---|
30 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
---|
31 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
---|
32 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
---|
33 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
---|
34 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
---|
35 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
---|
36 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
---|
37 | */
|
---|
38 |
|
---|
39 | #include <windows.h>
|
---|
40 | #include <tchar.h>
|
---|
41 | #include "internal/numbers.h"
|
---|
42 | #ifndef LPDIR_H
|
---|
43 | # include "LPdir.h"
|
---|
44 | #endif
|
---|
45 |
|
---|
46 | /*
|
---|
47 | * We're most likely overcautious here, but let's reserve for broken WinCE
|
---|
48 | * headers and explicitly opt for UNICODE call. Keep in mind that our WinCE
|
---|
49 | * builds are compiled with -DUNICODE [as well as -D_UNICODE].
|
---|
50 | */
|
---|
51 | #if defined(LP_SYS_WINCE) && !defined(FindFirstFile)
|
---|
52 | # define FindFirstFile FindFirstFileW
|
---|
53 | #endif
|
---|
54 | #if defined(LP_SYS_WINCE) && !defined(FindNextFile)
|
---|
55 | # define FindNextFile FindNextFileW
|
---|
56 | #endif
|
---|
57 |
|
---|
58 | #ifndef NAME_MAX
|
---|
59 | # define NAME_MAX 255
|
---|
60 | #endif
|
---|
61 |
|
---|
62 | #ifdef CP_UTF8
|
---|
63 | # define CP_DEFAULT CP_UTF8
|
---|
64 | #else
|
---|
65 | # define CP_DEFAULT CP_ACP
|
---|
66 | #endif
|
---|
67 |
|
---|
68 | struct LP_dir_context_st {
|
---|
69 | WIN32_FIND_DATA ctx;
|
---|
70 | HANDLE handle;
|
---|
71 | char entry_name[NAME_MAX + 1];
|
---|
72 | };
|
---|
73 |
|
---|
74 | const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)
|
---|
75 | {
|
---|
76 | if (ctx == NULL || directory == NULL) {
|
---|
77 | errno = EINVAL;
|
---|
78 | return 0;
|
---|
79 | }
|
---|
80 |
|
---|
81 | errno = 0;
|
---|
82 | if (*ctx == NULL) {
|
---|
83 | size_t dirlen = strlen(directory);
|
---|
84 |
|
---|
85 | if (dirlen == 0 || dirlen > INT_MAX - 3) {
|
---|
86 | errno = ENOENT;
|
---|
87 | return 0;
|
---|
88 | }
|
---|
89 |
|
---|
90 | *ctx = malloc(sizeof(**ctx));
|
---|
91 | if (*ctx == NULL) {
|
---|
92 | errno = ENOMEM;
|
---|
93 | return 0;
|
---|
94 | }
|
---|
95 | memset(*ctx, 0, sizeof(**ctx));
|
---|
96 |
|
---|
97 | if (sizeof(TCHAR) != sizeof(char)) {
|
---|
98 | TCHAR *wdir = NULL;
|
---|
99 | /* len_0 denotes string length *with* trailing 0 */
|
---|
100 | size_t index = 0, len_0 = dirlen + 1;
|
---|
101 | #ifdef LP_MULTIBYTE_AVAILABLE
|
---|
102 | int sz = 0;
|
---|
103 | UINT cp;
|
---|
104 |
|
---|
105 | do {
|
---|
106 | # ifdef CP_UTF8
|
---|
107 | if ((sz = MultiByteToWideChar((cp = CP_UTF8), 0,
|
---|
108 | directory, len_0,
|
---|
109 | NULL, 0)) > 0 ||
|
---|
110 | GetLastError() != ERROR_NO_UNICODE_TRANSLATION)
|
---|
111 | break;
|
---|
112 | # endif
|
---|
113 | sz = MultiByteToWideChar((cp = CP_ACP), 0,
|
---|
114 | directory, len_0,
|
---|
115 | NULL, 0);
|
---|
116 | } while (0);
|
---|
117 |
|
---|
118 | if (sz > 0) {
|
---|
119 | /*
|
---|
120 | * allocate two additional characters in case we need to
|
---|
121 | * concatenate asterisk, |sz| covers trailing '\0'!
|
---|
122 | */
|
---|
123 | wdir = _alloca((sz + 2) * sizeof(TCHAR));
|
---|
124 | if (!MultiByteToWideChar(cp, 0, directory, len_0,
|
---|
125 | (WCHAR *)wdir, sz)) {
|
---|
126 | free(*ctx);
|
---|
127 | *ctx = NULL;
|
---|
128 | errno = EINVAL;
|
---|
129 | return 0;
|
---|
130 | }
|
---|
131 | } else
|
---|
132 | #endif
|
---|
133 | {
|
---|
134 | sz = len_0;
|
---|
135 | /*
|
---|
136 | * allocate two additional characters in case we need to
|
---|
137 | * concatenate asterisk, |sz| covers trailing '\0'!
|
---|
138 | */
|
---|
139 | wdir = _alloca((sz + 2) * sizeof(TCHAR));
|
---|
140 | for (index = 0; index < len_0; index++)
|
---|
141 | wdir[index] = (TCHAR)directory[index];
|
---|
142 | }
|
---|
143 |
|
---|
144 | sz--; /* wdir[sz] is trailing '\0' now */
|
---|
145 | if (wdir[sz - 1] != TEXT('*')) {
|
---|
146 | if (wdir[sz - 1] != TEXT('/') && wdir[sz - 1] != TEXT('\\'))
|
---|
147 | _tcscpy(wdir + sz, TEXT("/*"));
|
---|
148 | else
|
---|
149 | _tcscpy(wdir + sz, TEXT("*"));
|
---|
150 | }
|
---|
151 |
|
---|
152 | (*ctx)->handle = FindFirstFile(wdir, &(*ctx)->ctx);
|
---|
153 | } else {
|
---|
154 | if (directory[dirlen - 1] != '*') {
|
---|
155 | char *buf = _alloca(dirlen + 3);
|
---|
156 |
|
---|
157 | strcpy(buf, directory);
|
---|
158 | if (buf[dirlen - 1] != '/' && buf[dirlen - 1] != '\\')
|
---|
159 | strcpy(buf + dirlen, "/*");
|
---|
160 | else
|
---|
161 | strcpy(buf + dirlen, "*");
|
---|
162 |
|
---|
163 | directory = buf;
|
---|
164 | }
|
---|
165 |
|
---|
166 | (*ctx)->handle = FindFirstFile((TCHAR *)directory, &(*ctx)->ctx);
|
---|
167 | }
|
---|
168 |
|
---|
169 | if ((*ctx)->handle == INVALID_HANDLE_VALUE) {
|
---|
170 | free(*ctx);
|
---|
171 | *ctx = NULL;
|
---|
172 | errno = EINVAL;
|
---|
173 | return 0;
|
---|
174 | }
|
---|
175 | } else {
|
---|
176 | if (FindNextFile((*ctx)->handle, &(*ctx)->ctx) == FALSE) {
|
---|
177 | return 0;
|
---|
178 | }
|
---|
179 | }
|
---|
180 | if (sizeof(TCHAR) != sizeof(char)) {
|
---|
181 | TCHAR *wdir = (*ctx)->ctx.cFileName;
|
---|
182 | size_t index, len_0 = 0;
|
---|
183 |
|
---|
184 | while (wdir[len_0] && len_0 < (sizeof((*ctx)->entry_name) - 1))
|
---|
185 | len_0++;
|
---|
186 | len_0++;
|
---|
187 |
|
---|
188 | #ifdef LP_MULTIBYTE_AVAILABLE
|
---|
189 | if (!WideCharToMultiByte(CP_DEFAULT, 0, (WCHAR *)wdir, len_0,
|
---|
190 | (*ctx)->entry_name,
|
---|
191 | sizeof((*ctx)->entry_name), NULL, 0))
|
---|
192 | #endif
|
---|
193 | for (index = 0; index < len_0; index++)
|
---|
194 | (*ctx)->entry_name[index] = (char)wdir[index];
|
---|
195 | } else
|
---|
196 | strncpy((*ctx)->entry_name, (const char *)(*ctx)->ctx.cFileName,
|
---|
197 | sizeof((*ctx)->entry_name) - 1);
|
---|
198 |
|
---|
199 | (*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0';
|
---|
200 |
|
---|
201 | return (*ctx)->entry_name;
|
---|
202 | }
|
---|
203 |
|
---|
204 | int LP_find_file_end(LP_DIR_CTX **ctx)
|
---|
205 | {
|
---|
206 | if (ctx != NULL && *ctx != NULL) {
|
---|
207 | FindClose((*ctx)->handle);
|
---|
208 | free(*ctx);
|
---|
209 | *ctx = NULL;
|
---|
210 | return 1;
|
---|
211 | }
|
---|
212 | errno = EINVAL;
|
---|
213 | return 0;
|
---|
214 | }
|
---|