Home | History | Annotate | Line # | Download | only in crypto
      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 /*
     11  * This file is dual-licensed and is also available under the following
     12  * terms:
     13  *
     14  * Copyright (c) 2004, Richard Levitte <richard (at) levitte.org>
     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 }
    215