diff options
-rw-r--r-- | src/Storage.cpp | 73 |
1 files changed, 63 insertions, 10 deletions
diff --git a/src/Storage.cpp b/src/Storage.cpp index 8ef8e5f..50d1ffd 100644 --- a/src/Storage.cpp +++ b/src/Storage.cpp @@ -16,11 +16,57 @@ #include <sys/types.h> #include <fcntl.h> +#define EINTR_RETRY(ret, expr) \ + do { \ + errno = 0; \ + while(true) { \ + ret = (expr); \ + if(ret != -1 || errno != EINTR) \ + break; \ + } \ + } while(0) + static int makedir(const char *path) { return mkdir(path, S_IRWXU); } namespace QuickMedia { + static FILE* fopen_eintr(const char *filename, const char *modes) { + errno = 0; + while(true) { + FILE *f = fopen(filename, modes); + if(f || errno != EINTR) + return f; + } + } + + static size_t fwrite_eintr(const char *data, size_t size, FILE *f) { + errno = 0; + while(true) { + const size_t r = fwrite(data, 1, size, f); + if(r == size || errno != EINTR) + return r; + } + } + + static size_t fread_eintr(char *data, size_t size, FILE *f) { + errno = 0; + while(true) { + const size_t r = fread(data, 1, size, f); + if(r == size || errno != EINTR) + return r; + } + } + + static size_t fseek_eintr(FILE *f, long offset, int whence) { + errno = 0; + while(true) { + const int r = fseek(f, offset, whence); + if(r == 0 || errno != EINTR) + return r; + } + } + Path get_home_dir() { const char *homeDir = getenv("HOME"); @@ -81,37 +127,42 @@ namespace QuickMedia { FileType get_file_type(const Path &path) { struct stat file_stat; - if(stat(path.data.c_str(), &file_stat) == 0) + int ret; + EINTR_RETRY(ret, stat(path.data.c_str(), &file_stat)); + if(ret == 0) return S_ISREG(file_stat.st_mode) ? FileType::REGULAR : FileType::DIRECTORY; return FileType::FILE_NOT_FOUND; } int file_get_content(const Path &path, std::string &result) { - FILE *file = fopen(path.data.c_str(), "rb"); + FILE *file = fopen_eintr(path.data.c_str(), "rb"); if(!file) return -errno; - fseek(file, 0, SEEK_END); + fseek_eintr(file, 0, SEEK_END); long file_size = ftell(file); if(file_size == -1) { fprintf(stderr, "Error: attempted to read directory %s as a file\n", path.data.c_str()); fclose(file); return -1; } - fseek(file, 0, SEEK_SET); + fseek_eintr(file, 0, SEEK_SET); result.resize(file_size); - if(fread(&result[0], 1, file_size, file) != (size_t)file_size) { + if(fread_eintr(&result[0], file_size, file) != (size_t)file_size) { fclose(file); return -1; } - return fclose(file); + fclose(file); + return 0; } int file_get_size(const Path &path, size_t *size) { struct stat file_stat; - if(stat(path.data.c_str(), &file_stat) == 0 && S_ISREG(file_stat.st_mode)) { + int ret; + EINTR_RETRY(ret, stat(path.data.c_str(), &file_stat)); + if(ret == 0 && S_ISREG(file_stat.st_mode)) { *size = file_stat.st_size; return 0; } @@ -121,7 +172,9 @@ namespace QuickMedia { bool file_get_last_modified_time_seconds(const char *path, time_t *result) { struct stat file_stat; - if(stat(path, &file_stat) == 0) { + int ret; + EINTR_RETRY(ret, stat(path, &file_stat)); + if(ret == 0) { *result = file_stat.st_mtim.tv_sec; return true; } @@ -129,13 +182,13 @@ namespace QuickMedia { } static int file_overwrite(const Path &path, const char *str, size_t size) { - FILE *file = fopen(path.data.c_str(), "wb"); + FILE *file = fopen_eintr(path.data.c_str(), "wb"); if(!file) { perror(path.data.c_str()); return -1; } - if(fwrite(str, 1, size, file) != size) { + if(fwrite_eintr(str, size, file) != size) { fclose(file); return -1; } |