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