LPdir_win.c 6.8 KB

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