LPdir_win.c 6.9 KB

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