Atlas - SDL_sysfsops.c

Home / ext / SDL / src / filesystem / windows Lines: 1 | Size: 7925 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 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 32#ifndef COPY_FILE_NO_BUFFERING 33#define COPY_FILE_NO_BUFFERING 0x00001000 34#endif 35 36bool SDL_SYS_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback cb, void *userdata) 37{ 38 SDL_EnumerationResult result = SDL_ENUM_CONTINUE; 39 if (*path == '\0') { // if empty (completely at the root), we need to enumerate drive letters. 40 const DWORD drives = GetLogicalDrives(); 41 char name[] = { 0, ':', '\\', '\0' }; 42 for (int i = 'A'; (result == SDL_ENUM_CONTINUE) && (i <= 'Z'); i++) { 43 if (drives & (1 << (i - 'A'))) { 44 name[0] = (char) i; 45 result = cb(userdata, "", name); 46 } 47 } 48 } else { 49 // you need a wildcard to enumerate through FindFirstFileEx(), but the wildcard is only checked in the 50 // filename element at the end of the path string, so always tack on a "\\*" to get everything, and 51 // also prevent any wildcards inserted by the app from being respected. 52 char *pattern = NULL; 53 int patternlen = SDL_asprintf(&pattern, "%s\\\\", path); // we'll replace that second '\\' in the trimdown. 54 if ((patternlen == -1) || (!pattern)) { 55 return false; 56 } 57 58 // trim down to a single path separator at the end, in case the caller added one or more. 59 patternlen--; 60 while ((patternlen > 0) && ((pattern[patternlen] == '\\') || (pattern[patternlen] == '/'))) { 61 pattern[patternlen--] ='\0'; 62 } 63 pattern[++patternlen] = '\\'; 64 pattern[++patternlen] = '*'; 65 pattern[++patternlen] = '\0'; 66 67 WCHAR *wpattern = WIN_UTF8ToStringW(pattern); 68 if (!wpattern) { 69 SDL_free(pattern); 70 return false; 71 } 72 73 pattern[--patternlen] = '\0'; // chop off the '*' so we just have the dirname with a path separator. 74 75 WIN32_FIND_DATAW entw; 76 HANDLE dir = FindFirstFileExW(wpattern, FindExInfoStandard, &entw, FindExSearchNameMatch, NULL, 0); 77 SDL_free(wpattern); 78 if (dir == INVALID_HANDLE_VALUE) { 79 SDL_free(pattern); 80 return WIN_SetError("Failed to enumerate directory"); 81 } 82 83 do { 84 const WCHAR *fn = entw.cFileName; 85 86 if (fn[0] == '.') { // ignore "." and ".." 87 if ((fn[1] == '\0') || ((fn[1] == '.') && (fn[2] == '\0'))) { 88 continue; 89 } 90 } 91 92 char *utf8fn = WIN_StringToUTF8W(fn); 93 if (!utf8fn) { 94 result = SDL_ENUM_FAILURE; 95 } else { 96 result = cb(userdata, pattern, utf8fn); 97 SDL_free(utf8fn); 98 } 99 } while ((result == SDL_ENUM_CONTINUE) && (FindNextFileW(dir, &entw) != 0)); 100 101 FindClose(dir); 102 SDL_free(pattern); 103 } 104 105 return (result != SDL_ENUM_FAILURE); 106} 107 108bool SDL_SYS_RemovePath(const char *path) 109{ 110 WCHAR *wpath = WIN_UTF8ToStringW(path); 111 if (!wpath) { 112 return false; 113 } 114 115 WIN32_FILE_ATTRIBUTE_DATA info; 116 if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &info)) { 117 SDL_free(wpath); 118 if (GetLastError() == ERROR_FILE_NOT_FOUND) { 119 // Note that ERROR_PATH_NOT_FOUND means a parent dir is missing, and we consider that an error. 120 return true; // thing is already gone, call it a success. 121 } 122 return WIN_SetError("Couldn't get path's attributes"); 123 } 124 125 const int isdir = (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); 126 const BOOL rc = isdir ? RemoveDirectoryW(wpath) : DeleteFileW(wpath); 127 SDL_free(wpath); 128 if (!rc) { 129 return WIN_SetError("Couldn't remove path"); 130 } 131 return true; 132} 133 134bool SDL_SYS_RenamePath(const char *oldpath, const char *newpath) 135{ 136 WCHAR *woldpath = WIN_UTF8ToStringW(oldpath); 137 if (!woldpath) { 138 return false; 139 } 140 141 WCHAR *wnewpath = WIN_UTF8ToStringW(newpath); 142 if (!wnewpath) { 143 SDL_free(woldpath); 144 return false; 145 } 146 147 const BOOL rc = MoveFileExW(woldpath, wnewpath, MOVEFILE_REPLACE_EXISTING); 148 SDL_free(wnewpath); 149 SDL_free(woldpath); 150 if (!rc) { 151 return WIN_SetError("Couldn't rename path"); 152 } 153 return true; 154} 155 156bool SDL_SYS_CopyFile(const char *oldpath, const char *newpath) 157{ 158 WCHAR *woldpath = WIN_UTF8ToStringW(oldpath); 159 if (!woldpath) { 160 return false; 161 } 162 163 WCHAR *wnewpath = WIN_UTF8ToStringW(newpath); 164 if (!wnewpath) { 165 SDL_free(woldpath); 166 return false; 167 } 168 169 const BOOL rc = CopyFileExW(woldpath, wnewpath, NULL, NULL, NULL, COPY_FILE_ALLOW_DECRYPTED_DESTINATION|COPY_FILE_NO_BUFFERING); 170 SDL_free(wnewpath); 171 SDL_free(woldpath); 172 if (!rc) { 173 return WIN_SetError("Couldn't copy path"); 174 } 175 return true; 176} 177 178bool SDL_SYS_CreateDirectory(const char *path) 179{ 180 WCHAR *wpath = WIN_UTF8ToStringW(path); 181 if (!wpath) { 182 return false; 183 } 184 185 DWORD rc = CreateDirectoryW(wpath, NULL); 186 if (!rc && (GetLastError() == ERROR_ALREADY_EXISTS)) { 187 WIN32_FILE_ATTRIBUTE_DATA winstat; 188 if (GetFileAttributesExW(wpath, GetFileExInfoStandard, &winstat)) { 189 if (winstat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 190 rc = 1; // exists and is already a directory: cool. 191 } 192 } 193 } 194 195 SDL_free(wpath); 196 if (!rc) { 197 return WIN_SetError("Couldn't create directory"); 198 } 199 return true; 200} 201 202bool SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info) 203{ 204 WCHAR *wpath = WIN_UTF8ToStringW(path); 205 if (!wpath) { 206 return false; 207 } 208 209 WIN32_FILE_ATTRIBUTE_DATA winstat; 210 const BOOL rc = GetFileAttributesExW(wpath, GetFileExInfoStandard, &winstat); 211 SDL_free(wpath); 212 if (!rc) { 213 return WIN_SetError("Can't stat"); 214 } 215 216 if (winstat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 217 info->type = SDL_PATHTYPE_DIRECTORY; 218 info->size = 0; 219 } else if (winstat.dwFileAttributes & (FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_DEVICE)) { 220 info->type = SDL_PATHTYPE_OTHER; 221 info->size = ((((Uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow); 222 } else { 223 info->type = SDL_PATHTYPE_FILE; 224 info->size = ((((Uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow); 225 } 226 227 info->create_time = SDL_TimeFromWindows(winstat.ftCreationTime.dwLowDateTime, winstat.ftCreationTime.dwHighDateTime); 228 info->modify_time = SDL_TimeFromWindows(winstat.ftLastWriteTime.dwLowDateTime, winstat.ftLastWriteTime.dwHighDateTime); 229 info->access_time = SDL_TimeFromWindows(winstat.ftLastAccessTime.dwLowDateTime, winstat.ftLastAccessTime.dwHighDateTime); 230 231 return true; 232} 233 234#endif // SDL_FSOPS_WINDOWS 235 236
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.