Commit ad4df4af authored by Christopher Dykes's avatar Christopher Dykes Committed by Facebook Github Bot 8

Create the dirent.h portability header

Summary: We don't have dirent.h on Windows, but we can emulate its behavior.

Reviewed By: yfeldblum

Differential Revision: D2978570

fb-gh-sync-id: af5ade0ea64ba22900440250e7125aa039a77f62
fbshipit-source-id: af5ade0ea64ba22900440250e7125aa039a77f62
parent c63fe6c3
...@@ -270,6 +270,7 @@ nobase_follyinclude_HEADERS = \ ...@@ -270,6 +270,7 @@ nobase_follyinclude_HEADERS = \
portability/Asm.h \ portability/Asm.h \
portability/Config.h \ portability/Config.h \
portability/Constexpr.h \ portability/Constexpr.h \
portability/Dirent.h \
portability/Environment.h \ portability/Environment.h \
portability/GFlags.h \ portability/GFlags.h \
portability/IOVec.h \ portability/IOVec.h \
...@@ -416,6 +417,7 @@ libfolly_la_SOURCES = \ ...@@ -416,6 +417,7 @@ libfolly_la_SOURCES = \
detail/MemoryIdler.cpp \ detail/MemoryIdler.cpp \
MacAddress.cpp \ MacAddress.cpp \
MemoryMapping.cpp \ MemoryMapping.cpp \
portability/Dirent.cpp \
portability/Environment.cpp \ portability/Environment.cpp \
portability/Malloc.cpp \ portability/Malloc.cpp \
portability/String.cpp \ portability/String.cpp \
......
/*
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/portability/Dirent.h>
#ifdef _WIN32
#include <stdlib.h>
#include <string>
#include <folly/portability/Windows.h>
struct DIR {
dirent dir{};
HANDLE searchHandle{INVALID_HANDLE_VALUE};
int entriesRead{0};
char currentName[MAX_PATH * 3];
std::string pattern;
int close() {
return FindClose(searchHandle) ? 0 : -1;
}
DIR* open() {
wchar_t patternBuf[MAX_PATH + 2];
size_t len;
if (mbstowcs_s(&len, patternBuf, MAX_PATH, pattern.c_str(), MAX_PATH - 2)) {
return nullptr;
}
if (len && patternBuf[len - 1] != '/' && patternBuf[len - 1] != '\\') {
patternBuf[len++] = '\\';
}
patternBuf[len++] = '*';
patternBuf[len] = 0;
WIN32_FIND_DATAW fdata;
HANDLE h = FindFirstFileW(patternBuf, &fdata);
if (h == INVALID_HANDLE_VALUE) {
return nullptr;
}
searchHandle = h;
dir.d_name = currentName;
if (wcstombs(currentName, fdata.cFileName, MAX_PATH * 3) == (size_t)-1) {
return nullptr;
}
setEntryType(fdata.dwFileAttributes);
return this;
}
dirent* nextDir() {
if (entriesRead) {
WIN32_FIND_DATAW fdata;
if (!FindNextFileW(searchHandle, &fdata)) {
return nullptr;
}
if (wcstombs(currentName, fdata.cFileName, MAX_PATH * 3) == (size_t)-1) {
errno = EBADF;
return nullptr;
}
setEntryType(fdata.dwFileAttributes);
}
entriesRead++;
return &dir;
}
private:
void setEntryType(DWORD attr) {
if (attr & FILE_ATTRIBUTE_DIRECTORY) {
dir.d_type = DT_DIR;
} else {
dir.d_type = DT_REG;
}
}
};
extern "C" {
int closedir(DIR* dir) {
auto ret = dir->close();
delete dir;
return ret;
}
DIR* opendir(const char* name) {
auto dir = new DIR();
dir->pattern = name;
if (!dir->open()) {
delete dir;
return nullptr;
}
return dir;
}
dirent* readdir(DIR* dir) {
return dir->nextDir();
}
int readdir_r(DIR* dir, dirent* buf, dirent** ent) {
if (!dir || !buf || !ent) {
return EBADF;
}
*ent = dir->nextDir();
// Our normal readdir implementation is actually
// already reentrant, but we need to do this copy
// in case the caller expects buf to have the value.
if (*ent) {
*buf = dir->dir;
}
return 0;
}
void rewinddir(DIR* dir) {
dir->close();
dir->open();
}
}
#endif
/*
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#ifndef _WIN32
#include <dirent.h>
#else
#define DT_UNKNOWN 0
#define DT_DIR 1
#define DT_REG 2
#define DT_LNK 3
struct dirent {
unsigned char d_type;
char* d_name;
};
struct DIR;
extern "C" {
int closedir(DIR* dir);
DIR* opendir(const char* name);
dirent* readdir(DIR* dir);
int readdir_r(DIR* dir, dirent* buf, dirent** ent);
void rewinddir(DIR* dir);
}
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment