Files
libsst/libsst-os/SST_FileSys_Win32.c
2026-04-03 00:22:39 -05:00

165 lines
4.3 KiB
C

/*
SST_FileSys_Win32.c
Author: Patrick Baggett <ptbaggett@762studios.com>
Created: 3/29/2012
Purpose:
libsst-os file system querying for Win32
License:
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
*/
#include <SST/SST_FileSys.h>
#include <windows.h>
#include <string.h>
/*************************************************************************/
typedef struct SST_Dir_Win32
{
HANDLE hFind;
WIN32_FIND_DATAA data;
int once;
} SST_Dir_Win32;
/*************************************************************************/
/* Copy data from WIN32_FILE_DATAA structure to SST_FileInfo structure */
static void copyWin32FindData(SST_FileInfo* info, const WIN32_FIND_DATAA* data)
{
size_t len = strlen(data->cFileName);
if(len >= SST_FILENAME_MAX)
len = SST_FILENAME_MAX-1;
memcpy(info->name, data->cFileName, len);
info->name[len] = '\0';
info->size = (((uint64_t)data->nFileSizeHigh) << (8*sizeof(uint32_t))) | ((uint64_t)data->nFileSizeLow);
info->nameLen = len;
info->isDir = (data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
}
/*************************************************************************/
SST_Dir SST_OS_OpenDirectory(const char* path)
{
char findPath[MAX_PATH];
size_t len = strlen(path);
SST_Dir_Win32* win32dir;
/* Don't allow paths to end with a trailing slash */
if(path[len-1] == '/' || path[len-1] == '\\')
return NULL;
if(len > MAX_PATH-3)
len = MAX_PATH-3;
/* Append "/" and "*" to the end */
memcpy(findPath, path, len);
findPath[len] = '/';
findPath[len+1] = '*';
findPath[len+2] = '\0';
/* Allocate structure to use */
win32dir = (SST_Dir_Win32*)HeapAlloc(GetProcessHeap(), 0, sizeof(SST_Dir_Win32));
if(win32dir == NULL)
return (SST_Dir)NULL;
/* Attempt to find the first file */
win32dir->hFind = FindFirstFileA(findPath, &win32dir->data);
win32dir->once = 1;
/* Failed? */
if(win32dir->hFind == INVALID_HANDLE_VALUE)
{
/* FindFirstFile() returns ERROR_FILE_NOT_FOUND when no files are found.
If we didn't get that, then return NULL */
if(GetLastError() != ERROR_FILE_NOT_FOUND)
{
HeapFree(GetProcessHeap(), 0, (void*)win32dir);
return NULL;
}
}
return (SST_Dir)win32dir;
}
/*************************************************************************/
int SST_OS_ReadNextDirectoryEntry(SST_Dir dir, SST_FileInfo* fileInfoReturn)
{
SST_Dir_Win32* win32dir = (SST_Dir_Win32*)dir;
int result = 0;
/* Check if call to FindFirstFileA() returned 0 files found */
if(win32dir->hFind != INVALID_HANDLE_VALUE)
{
/* FindFirstFileA() copies the first file data automatically, so use the first time */
if(win32dir->once)
{
/* NOTE: data already copied to win32dir->data when FindFirstFileA() was called */
win32dir->once = 0;
result = 1;
}
else
result = FindNextFileA(win32dir->hFind, &win32dir->data);
/* If we have file data to copy, then do so now */
if(result)
{
if(strcmp(win32dir->data.cFileName, ".") == 0 || strcmp(win32dir->data.cFileName, "..") == 0)
return SST_OS_ReadNextDirectoryEntry(dir, fileInfoReturn);
else
copyWin32FindData(fileInfoReturn, &win32dir->data);
}
}
return result;
}
/*************************************************************************/
void SST_OS_CloseDirectory(SST_Dir dir)
{
SST_Dir_Win32* win32dir = (SST_Dir_Win32*)dir;
/* Close the handle if not invalid */
if(win32dir->hFind != INVALID_HANDLE_VALUE)
FindClose(win32dir->hFind);
/* Return heap memory */
HeapFree(GetProcessHeap(), 0, (void*)win32dir);
}
/*************************************************************************/
int SST_OS_CreateDirectory(const char* dir)
{
if(CreateDirectoryA(dir, NULL) == FALSE)
{
if(GetLastError() == ERROR_ALREADY_EXISTS)
return 1; /* positive == already exists */
else
return -1; /* negative == error */
}
return 0; /* zero == success */
}
/*************************************************************************/
int SST_OS_RemoveDirectory(const char* dir)
{
return (int)RemoveDirectory(dir);
}