Skip to content

Commit

Permalink
Add map to windows impl
Browse files Browse the repository at this point in the history
  • Loading branch information
madhurajayaraman committed May 28, 2024
1 parent 843cc08 commit 3d9fb01
Showing 1 changed file with 106 additions and 28 deletions.
134 changes: 106 additions & 28 deletions starboard/shared/win32/posix_emu/dirent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,88 @@
#include <dirent.h>

#include <windows.h>
#include <map>

#include "starboard/common/log.h"
#include "starboard/common/string.h"
#include "starboard/configuration_constants.h"
#include "starboard/shared/win32/directory_internal.h"
#include "starboard/shared/win32/file_internal.h"
#include "starboard/shared/win32/wchar_utils.h"
#include "starboard/types.h"

extern "C" {

struct CriticalSection {
CriticalSection() { InitializeCriticalSection(&critical_section_); }
CRITICAL_SECTION critical_section_;
};

static int gen_fd() {
static int fd = 100;
fd++;
if (fd == 0x7FFFFFFF) {
fd = 100;
}
return fd;
}

static std::map<int, std::deque<std::string>>* directory_map = nullptr;
static CriticalSection g_critical_section;

int handle_db_put(std::deque<std::string> next_directory_entry) {
EnterCriticalSection(&g_critical_section.critical_section_);
if (directory_map == nullptr) {
directory_map = new std::map<int, std::deque<std::string>>();
}

int fd = gen_fd();
// Go through the map and make sure there isn't duplicated index
// already.
while (directory_map->find(fd) != directory_map->end()) {
fd = gen_fd();
}

directory_map->insert({fd, next_directory_entry});

LeaveCriticalSection(&g_critical_section.critical_section_);
return fd;
}

static std::deque<std::string> handle_db_get(int handle, bool erase) {
std::deque<std::string> empty_deque;
if (handle < 0) {
return empty_deque;
}
EnterCriticalSection(&g_critical_section.critical_section_);
if (directory_map == nullptr) {
directory_map = new std::map<int, std::deque<std::string>>();
return empty_deque;
}

auto itr = directory_map->find(handle);
if (itr == directory_map->end()) {
return empty_deque;
}

std::deque<std::string> next_directory_entry = itr->second;
if (erase) {
directory_map->erase(handle);
}
LeaveCriticalSection(&g_critical_section.critical_section_);
return next_directory_entry;
}

void handle_db_replace(int fd, std::deque<std::string> next_directory_entry) {
EnterCriticalSection(&g_critical_section.critical_section_);
if (directory_map == nullptr) {
directory_map = new std::map<int, std::deque<std::string>>();
}
directory_map->erase(fd);
directory_map->insert({fd, next_directory_entry});
LeaveCriticalSection(&g_critical_section.critical_section_);
}

DIR* opendir(const char* path) {
using starboard::shared::win32::CStringToWString;
using starboard::shared::win32::NormalizeWin32Path;
Expand Down Expand Up @@ -59,11 +131,13 @@ DIR* opendir(const char* path) {

DIR* dir = reinterpret_cast<DIR*>(malloc(sizeof(DIR)));
dir->handle = directory_handle;
dir->fd = handle_db_put(std::deque<std::string>());
return dir;
}

int closedir(DIR* dir) {
bool success = CloseHandle(dir->handle);
handle_db_get(dir->fd, true);
delete dir;
return success ? 0 : -1;
}
Expand All @@ -80,37 +154,41 @@ int readdir_r(DIR* __restrict dir,
return -1;
}

std::deque<std::string> next_directory_entries;
alignas(sizeof(DWORDLONG)) std::vector<char> directory_info_buffer(
kDirectoryInfoBufferSize);
BOOL directory_info_success = GetFileInformationByHandleEx(
dir->handle, FileIdBothDirectoryInfo, directory_info_buffer.data(),
static_cast<int>(directory_info_buffer.size()));

if (!directory_info_success) {
return -1;
}
std::deque<std::string> next_directory_entries = handle_db_get(dir->fd, false);
if (next_directory_entries.empty()){
alignas(sizeof(DWORDLONG)) std::vector<char> directory_info_buffer(
kDirectoryInfoBufferSize);
BOOL directory_info_success = GetFileInformationByHandleEx(
dir->handle, FileIdBothDirectoryInfo, directory_info_buffer.data(),
static_cast<int>(directory_info_buffer.size()));

const char* directory_info_pointer = directory_info_buffer.data();
DWORD next_entry_offset = 0;
if (!directory_info_success) {
return -1;
}

do {
auto directory_info = reinterpret_cast<const FILE_ID_BOTH_DIR_INFO*>(
directory_info_pointer);
const char* directory_info_pointer = directory_info_buffer.data();
DWORD next_entry_offset = 0;

do {
auto directory_info = reinterpret_cast<const FILE_ID_BOTH_DIR_INFO*>(
directory_info_pointer);

// FileName is in Unicode, so divide by 2 to get the real length.
DWORD number_characters_in_filename = directory_info->FileNameLength / 2;
std::string ascii_path = starboard::shared::win32::wchar_tToUTF8(
directory_info->FileName, number_characters_in_filename);
SB_DCHECK(ascii_path.size() == number_characters_in_filename);
bool is_dotted_directory =
!ascii_path.compare(".") || !ascii_path.compare("..");
if (!is_dotted_directory) {
next_directory_entries.emplace_back(std::move(ascii_path));
}
next_entry_offset = directory_info->NextEntryOffset;
directory_info_pointer += next_entry_offset;
} while (next_entry_offset != 0);
handle_db_replace(dir->fd, next_directory_entries);
}

// FileName is in Unicode, so divide by 2 to get the real length.
DWORD number_characters_in_filename = directory_info->FileNameLength / 2;
std::string ascii_path = starboard::shared::win32::wchar_tToUTF8(
directory_info->FileName, number_characters_in_filename);
SB_DCHECK(ascii_path.size() == number_characters_in_filename);
bool is_dotted_directory =
!ascii_path.compare(".") || !ascii_path.compare("..");
if (!is_dotted_directory) {
next_directory_entries.emplace_back(std::move(ascii_path));
}
next_entry_offset = directory_info->NextEntryOffset;
directory_info_pointer += next_entry_offset;
} while (next_entry_offset != 0);

if (next_directory_entries.empty()) {
return -1;
Expand Down

0 comments on commit 3d9fb01

Please sign in to comment.