181ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott/*
281ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
381ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    Implementation of POSIX directory browsing functions and types for Win32.
481ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
581ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    Author:  Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
681ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    History: Created March 1997. Updated June 2003 and July 2012.
781ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    Rights:  See end of file.
881ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
981ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott*/
10074e0d57090165249c35a135345959e36843a5e5Aaron Karp#include "dirent_on_windows.h"
1181ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott#include <errno.h>
1281ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott#include <io.h> /* _findfirst and _findnext set errno iff they return -1 */
1381ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott#include <stdlib.h>
1481ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott#include <string.h>
156fb9a531b82cc9e3c603486f70ef9f60e617c3aaJon Ashburn#include "vk_loader_platform.h"
16413d6587475294985134aa1f9052abd697b7a4e5Jon Ashburn#include "loader.h"
176fb9a531b82cc9e3c603486f70ef9f60e617c3aaJon Ashburn
1881ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott#ifdef __cplusplus
1944aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburnextern "C" {
2081ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott#endif
2181ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
2281ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliotttypedef ptrdiff_t handle_type; /* C99's intptr_t not sufficiently portable */
2381ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
2444aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburnstruct DIR {
2544aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    handle_type handle; /* -1 for failed rewind */
2644aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    struct _finddata_t info;
2744aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    struct dirent result; /* d_name null iff first time */
2844aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    char *name;           /* null-terminated char string */
2981ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott};
3081ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
3144aed66f451bb8cb72e233f704aa1dd68397ffbbJon AshburnDIR *opendir(const char *name) {
3281ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    DIR *dir = 0;
3381ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
3444aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    if (name && name[0]) {
3581ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott        size_t base_length = strlen(name);
3681ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott        const char *all = /* search pattern must end with suitable wildcard */
3781ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott            strchr("/\\", name[base_length - 1]) ? "*" : "/*";
3881ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
3974d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young        if ((dir = (DIR *)loader_instance_tls_heap_alloc(sizeof *dir)) != 0 &&
4074d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young            (dir->name = (char *)loader_instance_tls_heap_alloc(
4174d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young                 base_length + strlen(all) + 1)) != 0) {
4281ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott            strcat(strcpy(dir->name, name), all);
4381ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
4444aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn            if ((dir->handle =
4544aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn                     (handle_type)_findfirst(dir->name, &dir->info)) != -1) {
4681ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott                dir->result.d_name = 0;
4744aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn            } else /* rollback */
4881ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott            {
4974d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young                loader_instance_tls_heap_free(dir->name);
5074d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young                loader_instance_tls_heap_free(dir);
5181ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott                dir = 0;
5281ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott            }
5344aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn        } else /* rollback */
5481ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott        {
5574d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young            loader_instance_tls_heap_free(dir);
5644aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn            dir = 0;
5781ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott            errno = ENOMEM;
5881ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott        }
5944aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    } else {
6081ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott        errno = EINVAL;
6181ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    }
6281ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
6381ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    return dir;
6481ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott}
6581ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
6644aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburnint closedir(DIR *dir) {
6781ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    int result = -1;
6881ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
6944aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    if (dir) {
7044aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn        if (dir->handle != -1) {
7181ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott            result = _findclose(dir->handle);
7281ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott        }
7381ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
7474d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young        loader_instance_tls_heap_free(dir->name);
7574d013a5438f47a66a77d5375d1cdeef3f0beca7Mark Young        loader_instance_tls_heap_free(dir);
7681ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    }
7781ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
7844aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    if (result == -1) /* map all errors to EBADF */
7981ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    {
8081ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott        errno = EBADF;
8181ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    }
8281ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
8381ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    return result;
8481ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott}
8581ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
8644aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburnstruct dirent *readdir(DIR *dir) {
8781ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    struct dirent *result = 0;
8881ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
8944aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    if (dir && dir->handle != -1) {
9044aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn        if (!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) {
9144aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn            result = &dir->result;
9281ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott            result->d_name = dir->info.name;
9381ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott        }
9444aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    } else {
9581ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott        errno = EBADF;
9681ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    }
9781ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
9881ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    return result;
9981ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott}
10081ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
10144aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburnvoid rewinddir(DIR *dir) {
10244aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    if (dir && dir->handle != -1) {
10381ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott        _findclose(dir->handle);
10444aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn        dir->handle = (handle_type)_findfirst(dir->name, &dir->info);
10581ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott        dir->result.d_name = 0;
10644aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    } else {
10781ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott        errno = EBADF;
10881ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    }
10981ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott}
11081ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
11181ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott#ifdef __cplusplus
11281ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott}
11381ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott#endif
11481ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
11581ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott/*
11681ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
11781ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    Copyright Kevlin Henney, 1997, 2003, 2012. All rights reserved.
11844aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    Copyright (c) 2015 The Khronos Group Inc.
11944aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    Copyright (c) 2015 Valve Corporation
12044aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn    Copyright (c) 2015 LunarG, Inc.
12181ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    Permission to use, copy, modify, and distribute this software and its
12281ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    documentation for any purpose is hereby granted without fee, provided
12381ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    that this copyright and permissions notice appear in all copies and
12481ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    derivatives.
12544aed66f451bb8cb72e233f704aa1dd68397ffbbJon Ashburn
12681ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    This software is supplied "as is" without express or implied warranty.
12781ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
12881ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott    But that said, if there are any problems please get in touch.
12981ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott
13081ac44ce34f01f6462ce61ff44b34de5c44304abIan Elliott*/
131