OXYGENHUB
◆ main openmsx / src / utils / win32-dirent.cc
3.3 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
/* Copyright (C) 2001, 2006 Free Software Foundation, Inc.
2
 *
3
 * This library is free software; you can redistribute it and/or
4
 * modify it under the terms of the GNU Lesser General Public
5
 * License as published by the Free Software Foundation; either
6
 * version 2.1 of the License, or (at your option) any later version.
7
 *
8
 * This library is distributed in the hope that it will be useful,
9
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
 * Lesser General Public License for more details.
12
 *
13
 * You should have received a copy of the GNU Lesser General Public
14
 * License along with this library; if not, write to the Free Software
15
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
 */
17
18
// NB: Taken from http://www.koders.com/c/fidB38A2E97F60B8A0C903631F8C60078DE8C6C8433.aspx
19
// Also modified to use Unicode calls explicitly
20
// Slightly reformatted/simplified to fit openMSX coding style.
21
22
#ifdef _WIN32
23
24
#include "win32-dirent.hh"
25
#include "utf8_checked.hh"
26
#include "MSXException.hh"
27
#include "xrange.hh"
28
#include "zstring_view.hh"
29
#include <windows.h>
30
#include <cstring>
31
#include <cstdlib>
32
#include <exception>
33
#include <iterator>
34
35
namespace openmsx {
36
37
DIR* opendir(const char* name)
38
{
39
	if (!name || !*name) return nullptr;
40
41
	zstring_view name2 = name;
42
	std::wstring nameW = utf8::utf8to16(name2);
43
	if (!name2.ends_with('/') && !name2.ends_with("\\")) {
44
		nameW += L"\\*";
45
	} else {
46
		nameW += L"*";
47
	}
48
49
	HANDLE hnd;
50
	WIN32_FIND_DATAW find;
51
	if ((hnd = FindFirstFileW(nameW.c_str(), &find)) == INVALID_HANDLE_VALUE) {
52
		return nullptr;
53
	}
54
55
	auto* dir = new DIR;
56
	dir->mask = nameW;
57
	dir->fd = reinterpret_cast<INT_PTR>(hnd);
58
	dir->data = new WIN32_FIND_DATAW;
59
	dir->filepos = 0;
60
	memcpy(dir->data, &find, sizeof(find));
61
	return dir;
62
}
63
64
dirent* readdir(DIR* dir)
65
{
66
	static dirent entry;
67
	entry.d_ino = 0;
68
	entry.d_type = DT_UNKNOWN;
69
70
	auto find = static_cast<WIN32_FIND_DATAW*>(dir->data);
71
	if (dir->filepos) {
72
		if (!FindNextFileW(reinterpret_cast<HANDLE>(dir->fd), find)) {
73
			return nullptr;
74
		}
75
	}
76
77
	std::string d_name = utf8::utf16to8(find->cFileName);
78
	strncpy(entry.d_name, d_name.c_str(), std::size(entry.d_name));
79
80
	entry.d_off = dir->filepos;
81
	entry.d_reclen = static_cast<unsigned short>(strlen(entry.d_name));
82
	dir->filepos++;
83
	return &entry;
84
}
85
86
int closedir(DIR* dir)
87
{
88
	auto hnd = reinterpret_cast<HANDLE>(dir->fd);
89
	delete static_cast<WIN32_FIND_DATAW*>(dir->data);
90
	delete dir;
91
	return FindClose(hnd) ? 0 : -1;
92
}
93
94
void rewinddir(DIR* dir)
95
{
96
	auto hnd = reinterpret_cast<HANDLE>(dir->fd);
97
	auto find = static_cast<WIN32_FIND_DATAW*>(dir->data);
98
99
	FindClose(hnd);
100
	hnd = FindFirstFileW(dir->mask.c_str(), find);
101
	dir->fd = reinterpret_cast<INT_PTR>(hnd);
102
	dir->filepos = 0;
103
}
104
105
void seekdir(DIR* dir, off_t offset)
106
{
107
	rewinddir(dir);
108
	repeat(offset, [&]{
109
		if (FindNextFileW(reinterpret_cast<HANDLE>(dir->fd),
110
		                  static_cast<WIN32_FIND_DATAW*>(dir->data))) {
111
			dir->filepos++;
112
		}
113
	});
114
}
115
116
off_t telldir(DIR* dir)
117
{
118
	return dir->filepos;
119
}
120
121
// For correctness on 64-bit Windows, this function would need to maintain an
122
// internal map of ints to HANDLEs, since HANDLEs are sizeof(void*). It's not
123
// used at the moment in the openMSX sources, so let's not bother for now.
124
/*int dirfd(DIR* dir)
125
{
126
	return dir->fd;
127
}*/
128
129
} // namespace openmsx
130
131
#endif