/* * Copyright (C) Tristan Franssen, . * * This software is licensed under the Apache License, Version 2.0 (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License in the file LICENSE or at * http://www.apache.org/licenses/LICENSE-2.0 */ #include "cosms-core/file.h" #include #include #include #if defined(__GNUC__) #define _FILE_OFFSET_BITS_ 64 #include #include #include #include #elif defined(_WIN32) #include #endif CosmsCoreFileError cosms_core_file_read(const char *path, char **content, unsigned long long *size) { #if defined(__GNUC__) int file = open(path, O_RDONLY); if (file == -1) { switch(errno) { case ENOENT: return COSMS_CORE_FILE_NOT_FOUND; case EACCES: return COSMS_CORE_FILE_NO_ACCESS; case EMFILE: case ENFILE: return COSMS_CORE_FILE_LIMIT_REACHED; default: return COSMS_CORE_FILE_UNKOWN_ERROR; } } struct stat file_stat; if (stat(path, &file_stat) != 0) { close(file); return COSMS_CORE_FILE_COULD_NOT_READ_SIZE; } if (size != NULL) { *size = file_stat.st_size; } *content = (char*)malloc((file_stat.st_size + 1) * sizeof(char)); if (content == NULL) { close(file); return COSMS_CORE_FILE_FAILED_TO_ALLOCATE; } unsigned long long remaining_bytes = file_stat.st_size; while (remaining_bytes != 0) { unsigned int bytes_to_read; if (remaining_bytes > UINT_MAX) { bytes_to_read = UINT_MAX; } else { bytes_to_read = (unsigned int)remaining_bytes; } int read_bytes = read(file, (*content) + (file_stat.st_size - remaining_bytes), bytes_to_read); if (read_bytes == -1) { free(*content); close(file); return COSMS_CORE_FILE_FAILED_TO_READ; } remaining_bytes -= read_bytes; } (*content)[file_stat.st_size] = '\0'; close(file); #elif defined(_WIN32) HANDLE file = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (file == INVALID_HANDLE_VALUE) { switch(GetLastError()) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: return COSMS_CORE_FILE_NOT_FOUND; case ERROR_ACCESS_DENIED: case ERROR_SHARING_VIOLATION: case ERROR_LOCK_VIOLATION: return COSMS_CORE_FILE_NO_ACCESS; case ERROR_TOO_MANY_OPEN_FILES: return COSMS_CORE_FILE_LIMIT_REACHED; default: return COSMS_CORE_FILE_UNKOWN_ERROR; } } DWORD high_size; DWORD low_size = GetFileSize(file, &high_size); if (low_size == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) { CloseHandle(file); return COSMS_CORE_FILE_COULD_NOT_READ_SIZE; } unsigned long long file_size = ((unsigned long long)high_size << 32) | low_size; if (size != NULL) { *size = file_size; } *content = (char*)malloc((file_size + 1) * sizeof(char)); if (content == NULL) { CloseHandle(file); return COSMS_CORE_FILE_FAILED_TO_ALLOCATE; } unsigned long long remaining_bytes = file_size; while (remaining_bytes != 0) { DWORD bytes_to_read, read_bytes; if (remaining_bytes > UINT_MAX) { bytes_to_read = UINT_MAX; } else { bytes_to_read = (DWORD)remaining_bytes; } if (!ReadFile(file, (*content) + (file_size - remaining_bytes), bytes_to_read, &read_bytes, NULL)) { free(*content); CloseHandle(file); return COSMS_CORE_FILE_FAILED_TO_READ; } remaining_bytes -= read_bytes; } (*content)[file_size] = '\0'; CloseHandle(file); #endif return COSMS_CORE_FILE_OK; } CosmsCoreFileError cosms_core_file_write(const char *path, const char *content, unsigned long long size, bool override) { #if defined(__GNUC__) int file; if (override) { file = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); } else { file = open(path, O_WRONLY | O_CREAT | O_APPEND, 0644); } if (file == -1) { switch (errno) { case ENOENT: return COSMS_CORE_FILE_NOT_FOUND; case EACCES: return COSMS_CORE_FILE_NO_ACCESS; case EMFILE: case ENFILE: return COSMS_CORE_FILE_LIMIT_REACHED; default: return COSMS_CORE_FILE_UNKOWN_ERROR; } } unsigned long long remaining_bytes = size; while (remaining_bytes != 0) { unsigned int bytes_to_write; if (remaining_bytes > UINT_MAX) { bytes_to_write = UINT_MAX; } else { bytes_to_write = (unsigned int)remaining_bytes; } int written_bytes = write(file, content + (size - remaining_bytes), bytes_to_write); if (written_bytes == -1) { close(file); return COSMS_CORE_FILE_FAILED_TO_WRITE; } remaining_bytes -= written_bytes; } close(file); #elif defined(_WIN32) HANDLE file; if (override) { file = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); } else { file = CreateFile(path, FILE_APPEND_DATA, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); } if (file == INVALID_HANDLE_VALUE) { switch(GetLastError()) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: return COSMS_CORE_FILE_NOT_FOUND; case ERROR_ACCESS_DENIED: case ERROR_SHARING_VIOLATION: case ERROR_LOCK_VIOLATION: return COSMS_CORE_FILE_NO_ACCESS; case ERROR_TOO_MANY_OPEN_FILES: return COSMS_CORE_FILE_LIMIT_REACHED; default: return COSMS_CORE_FILE_UNKOWN_ERROR; } } unsigned long long remaining_bytes = size; while (remaining_bytes != 0) { DWORD bytes_to_write, written_bytes; if (remaining_bytes > UINT_MAX) { bytes_to_write = UINT_MAX; } else { bytes_to_write = (DWORD)remaining_bytes; } if (!WriteFile(file, content + (size - remaining_bytes), bytes_to_write, &written_bytes, NULL)) { CloseHandle(file); return COSMS_CORE_FILE_FAILED_TO_WRITE; } remaining_bytes -= written_bytes; } CloseHandle(file); #endif return COSMS_CORE_FILE_OK; } CosmsCoreFileError cosms_core_file_delete(const char *path) { #if defined(__GNUC__) if (unlink(path) == -1) { switch (errno) { case ENOENT: return COSMS_CORE_FILE_NOT_FOUND; case EACCES: return COSMS_CORE_FILE_NO_ACCESS; case EBUSY: return COSMS_CORE_FILE_STILL_OPEN; default: return COSMS_CORE_FILE_UNKOWN_ERROR; } } #elif defined(_WIN32) if (!DeleteFile(path)) { switch(GetLastError()) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: return COSMS_CORE_FILE_NOT_FOUND; case ERROR_ACCESS_DENIED: return COSMS_CORE_FILE_NO_ACCESS; case ERROR_LOCK_VIOLATION: case ERROR_SHARING_VIOLATION: return COSMS_CORE_FILE_STILL_OPEN; default: return COSMS_CORE_FILE_UNKOWN_ERROR; } } #endif return COSMS_CORE_FILE_OK; } const char *cosms_core_file_error_string(CosmsCoreFileError error) { switch(error) { case COSMS_CORE_FILE_OK: return "cosms-file everything ok"; case COSMS_CORE_FILE_NOT_FOUND: return "cosms-file path not found"; case COSMS_CORE_FILE_NO_ACCESS: return "cosms-file no access"; case COSMS_CORE_FILE_LIMIT_REACHED: return "cosms-file to many open files"; case COSMS_CORE_FILE_COULD_NOT_READ_SIZE: return "cosms-file failed to read size"; case COSMS_CORE_FILE_UNKOWN_ERROR: return "cosms-file unkown error occured"; case COSMS_CORE_FILE_FAILED_TO_ALLOCATE: return "cosms-file failed to allocate memory"; case COSMS_CORE_FILE_FAILED_TO_READ: return "cosms-file failed to read content of file"; case COSMS_CORE_FILE_FAILED_TO_WRITE: return "cosms-file failed to write content to file"; case COSMS_CORE_FILE_STILL_OPEN: return "cosms-file still open"; default: return NULL; } }