#include #include #include #include #include #include #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); }