Files
djhackersdev_bemanitools/src/main/util/fs.c
T
2019-09-27 22:36:50 +02:00

268 lines
4.9 KiB
C

#include <windows.h>
#include <shlobj.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "util/defs.h"
#include "util/fs.h"
#include "util/log.h"
#include "util/mem.h"
#include "util/str.h"
bool file_load(const char *filename, void **out_bytes, size_t *out_nbytes,
bool text_mode)
{
FILE *f;
void *bytes;
size_t nbytes;
int result;
log_assert(out_bytes != NULL);
*out_bytes = NULL;
f = fopen(filename, "rb");
if (f == NULL) {
log_warning("%s: Error opening file: %s", filename, strerror(errno));
goto open_fail;
}
fseek(f, 0, SEEK_END);
nbytes = ftell(f);
fseek(f, 0, SEEK_SET);
/* Add for null terminator */
if (text_mode) {
nbytes++;
}
bytes = malloc(nbytes);
if (bytes == NULL) {
log_warning("%s: malloc(%u) failed", filename, (unsigned int) nbytes);
goto malloc_fail;
}
if (text_mode) {
result = fread(bytes, nbytes - 1, 1, f);
} else {
result = fread(bytes, nbytes, 1, f);
}
if (result != 1) {
log_warning("%s: Error reading file: %s", filename, strerror(errno));
goto read_fail;
}
*out_bytes = bytes;
if (out_nbytes != NULL) {
*out_nbytes = nbytes;
}
fclose(f);
/* Add null terminator */
if (text_mode) {
((char*) bytes)[nbytes - 1] = '\0';
}
log_misc("File loaded %s, size %lu", filename,
(long unsigned int) *out_nbytes);
return true;
read_fail:
free(bytes);
malloc_fail:
fclose(f);
open_fail:
return false;
}
bool file_save(const char *filename, const void *bytes, size_t nbytes)
{
FILE *f;
int result;
f = fopen(filename, "wb");
if (f == NULL) {
log_warning("%s: Error creating file: %s", filename, strerror(errno));
goto open_fail;
}
result = fwrite(bytes, nbytes, 1, f);
if (result != 1) {
log_warning("%s: Error writing file: %s", filename, strerror(errno));
goto write_fail;
}
fclose(f);
return true;
write_fail:
fclose(f);
open_fail:
return false;
}
bool path_exists(const char* path)
{
DWORD attrib = GetFileAttributes(path);
return attrib != INVALID_FILE_ATTRIBUTES;
}
bool path_exists_wstr(const wchar_t* path)
{
DWORD attrib = GetFileAttributesW(path);
return attrib != INVALID_FILE_ATTRIBUTES;
}
FILE *fopen_appdata(const char *vendor, const char *filename,
const char *mode)
{
char root[MAX_PATH];
char path[MAX_PATH];
HRESULT hr;
FILE *f;
hr = SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, root);
if (FAILED(hr)) {
log_warning("Failed to get AppData folder: hr=%08x",
(unsigned int) hr);
return NULL;
}
str_format(path, sizeof(path), "%s\\%s", root, vendor);
if (!CreateDirectory(path, NULL)
&& GetLastError() != ERROR_ALREADY_EXISTS) {
log_warning("Failed to create %s: %08x",
path, (unsigned int) GetLastError());
return NULL;
}
str_format(path, sizeof(path), "%s\\%s\\%s", root, vendor, filename);
f = fopen(path, mode);
if (f == NULL) {
log_warning("fopen(\"%s\", \"%s\") failed: %s",
path, mode, strerror(errno));
}
return f;
}
bool path_mkdir(const char *path)
{
char buf[MAX_PATH];
char *pos;
str_cpy(buf, lengthof(buf), path);
for (pos = path_next_element(buf)
; pos
; pos = path_next_element(pos + 1)) {
*pos = '\0';
if (strlen(buf) != 2 || buf[1] != ':') {
CreateDirectory(buf, NULL);
if (GetLastError() != ERROR_ALREADY_EXISTS) {
log_warning("%s: Cannot create directory: %#x",
buf, (unsigned int) GetLastError());
return false;
}
}
*pos = '/';
}
CreateDirectory(buf, NULL);
if (GetLastError() != ERROR_ALREADY_EXISTS) {
log_warning("%s: Cannot create directory: %#x",
buf, (unsigned int) GetLastError());
return false;
}
return true;
}
char *path_next_element(char *path)
{
char *c;
for (c = path ; *c ; c++) {
if (*c == '/' || *c == '\\') {
return c;
}
}
return NULL;
}
bool read_str(FILE *f, char **str)
{
uint32_t len;
char *buf;
if (fread(&len, sizeof(len), 1, f) != 1) {
goto len_fail;
}
buf = malloc(len + 1);
if (buf == NULL) {
goto alloc_fail;
}
if (len > 0 && fread(buf, len, 1, f) != 1) {
goto body_fail;
}
buf[len] = '\0';
*str = buf;
return true;
body_fail:
free(buf);
alloc_fail:
len_fail:
return false;
}
void write_str(FILE *f, const char *str)
{
uint32_t len;
len = strlen(str);
fwrite(&len, sizeof(len), 1, f);
fwrite(str, len, 1, f);
}