summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/filesystem/windows/SDL_sysfsops.c
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
committer3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
commit5a079a2d114f96d4847d1ee305d5b7c16eeec50e (patch)
tree8926ab44f168acf787d8e19608857b3af0f82758 /contrib/SDL-3.2.8/src/filesystem/windows/SDL_sysfsops.c
Initial commit
Diffstat (limited to 'contrib/SDL-3.2.8/src/filesystem/windows/SDL_sysfsops.c')
-rw-r--r--contrib/SDL-3.2.8/src/filesystem/windows/SDL_sysfsops.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/filesystem/windows/SDL_sysfsops.c b/contrib/SDL-3.2.8/src/filesystem/windows/SDL_sysfsops.c
new file mode 100644
index 0000000..9c48ba9
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/filesystem/windows/SDL_sysfsops.c
@@ -0,0 +1,231 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21
22#include "SDL_internal.h"
23
24#if defined(SDL_FSOPS_WINDOWS)
25
26/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
27// System dependent filesystem routines
28
29#include "../../core/windows/SDL_windows.h"
30#include "../SDL_sysfilesystem.h"
31
32bool SDL_SYS_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback cb, void *userdata)
33{
34 SDL_EnumerationResult result = SDL_ENUM_CONTINUE;
35 if (*path == '\0') { // if empty (completely at the root), we need to enumerate drive letters.
36 const DWORD drives = GetLogicalDrives();
37 char name[] = { 0, ':', '\\', '\0' };
38 for (int i = 'A'; (result == SDL_ENUM_CONTINUE) && (i <= 'Z'); i++) {
39 if (drives & (1 << (i - 'A'))) {
40 name[0] = (char) i;
41 result = cb(userdata, "", name);
42 }
43 }
44 } else {
45 // you need a wildcard to enumerate through FindFirstFileEx(), but the wildcard is only checked in the
46 // filename element at the end of the path string, so always tack on a "\\*" to get everything, and
47 // also prevent any wildcards inserted by the app from being respected.
48 char *pattern = NULL;
49 int patternlen = SDL_asprintf(&pattern, "%s\\\\", path); // we'll replace that second '\\' in the trimdown.
50 if ((patternlen == -1) || (!pattern)) {
51 return false;
52 }
53
54 // trim down to a single path separator at the end, in case the caller added one or more.
55 patternlen--;
56 while ((patternlen >= 0) && ((pattern[patternlen] == '\\') || (pattern[patternlen] == '/'))) {
57 pattern[patternlen--] ='\0';
58 }
59 pattern[++patternlen] = '\\';
60 pattern[++patternlen] = '*';
61 pattern[++patternlen] = '\0';
62
63 WCHAR *wpattern = WIN_UTF8ToStringW(pattern);
64 if (!wpattern) {
65 SDL_free(pattern);
66 return false;
67 }
68
69 pattern[--patternlen] = '\0'; // chop off the '*' so we just have the dirname with a path separator.
70
71 WIN32_FIND_DATAW entw;
72 HANDLE dir = FindFirstFileExW(wpattern, FindExInfoStandard, &entw, FindExSearchNameMatch, NULL, 0);
73 SDL_free(wpattern);
74 if (dir == INVALID_HANDLE_VALUE) {
75 SDL_free(pattern);
76 return WIN_SetError("Failed to enumerate directory");
77 }
78
79 do {
80 const WCHAR *fn = entw.cFileName;
81
82 if (fn[0] == '.') { // ignore "." and ".."
83 if ((fn[1] == '\0') || ((fn[1] == '.') && (fn[2] == '\0'))) {
84 continue;
85 }
86 }
87
88 char *utf8fn = WIN_StringToUTF8W(fn);
89 if (!utf8fn) {
90 result = SDL_ENUM_FAILURE;
91 } else {
92 result = cb(userdata, pattern, utf8fn);
93 SDL_free(utf8fn);
94 }
95 } while ((result == SDL_ENUM_CONTINUE) && (FindNextFileW(dir, &entw) != 0));
96
97 FindClose(dir);
98 SDL_free(pattern);
99 }
100
101 return (result != SDL_ENUM_FAILURE);
102}
103
104bool SDL_SYS_RemovePath(const char *path)
105{
106 WCHAR *wpath = WIN_UTF8ToStringW(path);
107 if (!wpath) {
108 return false;
109 }
110
111 WIN32_FILE_ATTRIBUTE_DATA info;
112 if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &info)) {
113 SDL_free(wpath);
114 if (GetLastError() == ERROR_FILE_NOT_FOUND) {
115 // Note that ERROR_PATH_NOT_FOUND means a parent dir is missing, and we consider that an error.
116 return true; // thing is already gone, call it a success.
117 }
118 return WIN_SetError("Couldn't get path's attributes");
119 }
120
121 const int isdir = (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
122 const BOOL rc = isdir ? RemoveDirectoryW(wpath) : DeleteFileW(wpath);
123 SDL_free(wpath);
124 if (!rc) {
125 return WIN_SetError("Couldn't remove path");
126 }
127 return true;
128}
129
130bool SDL_SYS_RenamePath(const char *oldpath, const char *newpath)
131{
132 WCHAR *woldpath = WIN_UTF8ToStringW(oldpath);
133 if (!woldpath) {
134 return false;
135 }
136
137 WCHAR *wnewpath = WIN_UTF8ToStringW(newpath);
138 if (!wnewpath) {
139 SDL_free(woldpath);
140 return false;
141 }
142
143 const BOOL rc = MoveFileExW(woldpath, wnewpath, MOVEFILE_REPLACE_EXISTING);
144 SDL_free(wnewpath);
145 SDL_free(woldpath);
146 if (!rc) {
147 return WIN_SetError("Couldn't rename path");
148 }
149 return true;
150}
151
152bool SDL_SYS_CopyFile(const char *oldpath, const char *newpath)
153{
154 WCHAR *woldpath = WIN_UTF8ToStringW(oldpath);
155 if (!woldpath) {
156 return false;
157 }
158
159 WCHAR *wnewpath = WIN_UTF8ToStringW(newpath);
160 if (!wnewpath) {
161 SDL_free(woldpath);
162 return false;
163 }
164
165 const BOOL rc = CopyFileExW(woldpath, wnewpath, NULL, NULL, NULL, COPY_FILE_ALLOW_DECRYPTED_DESTINATION|COPY_FILE_NO_BUFFERING);
166 SDL_free(wnewpath);
167 SDL_free(woldpath);
168 if (!rc) {
169 return WIN_SetError("Couldn't copy path");
170 }
171 return true;
172}
173
174bool SDL_SYS_CreateDirectory(const char *path)
175{
176 WCHAR *wpath = WIN_UTF8ToStringW(path);
177 if (!wpath) {
178 return false;
179 }
180
181 DWORD rc = CreateDirectoryW(wpath, NULL);
182 if (!rc && (GetLastError() == ERROR_ALREADY_EXISTS)) {
183 WIN32_FILE_ATTRIBUTE_DATA winstat;
184 if (GetFileAttributesExW(wpath, GetFileExInfoStandard, &winstat)) {
185 if (winstat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
186 rc = 1; // exists and is already a directory: cool.
187 }
188 }
189 }
190
191 SDL_free(wpath);
192 if (!rc) {
193 return WIN_SetError("Couldn't create directory");
194 }
195 return true;
196}
197
198bool SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info)
199{
200 WCHAR *wpath = WIN_UTF8ToStringW(path);
201 if (!wpath) {
202 return false;
203 }
204
205 WIN32_FILE_ATTRIBUTE_DATA winstat;
206 const BOOL rc = GetFileAttributesExW(wpath, GetFileExInfoStandard, &winstat);
207 SDL_free(wpath);
208 if (!rc) {
209 return WIN_SetError("Can't stat");
210 }
211
212 if (winstat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
213 info->type = SDL_PATHTYPE_DIRECTORY;
214 info->size = 0;
215 } else if (winstat.dwFileAttributes & (FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_DEVICE)) {
216 info->type = SDL_PATHTYPE_OTHER;
217 info->size = ((((Uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow);
218 } else {
219 info->type = SDL_PATHTYPE_FILE;
220 info->size = ((((Uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow);
221 }
222
223 info->create_time = SDL_TimeFromWindows(winstat.ftCreationTime.dwLowDateTime, winstat.ftCreationTime.dwHighDateTime);
224 info->modify_time = SDL_TimeFromWindows(winstat.ftLastWriteTime.dwLowDateTime, winstat.ftLastWriteTime.dwHighDateTime);
225 info->access_time = SDL_TimeFromWindows(winstat.ftLastAccessTime.dwLowDateTime, winstat.ftLastAccessTime.dwHighDateTime);
226
227 return true;
228}
229
230#endif // SDL_FSOPS_WINDOWS
231