From f6d4634c75a78526057f9aaa4e5e04a8332263e9 Mon Sep 17 00:00:00 2001 From: Lefteris Karapetsas Date: Tue, 14 Apr 2015 16:48:06 +0200 Subject: [PATCH] Move ethash_io_prepare to io.c - Platform specific io.c files now contain only the minimum amount of code they can. --- internal.c | 3 ++- io.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ io.h | 34 +++++++++++++++++++++++++++++--- io_posix.c | 58 ++++++++++++++---------------------------------------- io_win32.c | 56 ++++++++++++++-------------------------------------- 5 files changed, 121 insertions(+), 88 deletions(-) diff --git a/internal.c b/internal.c index 93fc3bbe9..fac5b7ae2 100644 --- a/internal.c +++ b/internal.c @@ -371,12 +371,13 @@ ethash_full_t ethash_full_new(char const *dirname, ret->file_size = (size_t)params->full_size; switch (ethash_io_prepare(dirname, *seed_hash, &f, (size_t)params->full_size)) { case ETHASH_IO_FAIL: + case ETHASH_IO_MEMO_SIZE_MISMATCH: goto fail_free_full; case ETHASH_IO_MEMO_MATCH: match = true; case ETHASH_IO_MEMO_MISMATCH: ret->file = f; - if ((fd = fileno(ret->file)) == -1) { + if ((fd = ethash_fileno(ret->file)) == -1) { goto fail_free_full; } ret->data = mmap( diff --git a/io.c b/io.c index 0a1b8731a..d444fc983 100644 --- a/io.c +++ b/io.c @@ -48,3 +48,61 @@ free_name: free(fullname); return ret; } + +enum ethash_io_rc ethash_io_prepare(char const *dirname, + ethash_h256_t const seedhash, + FILE **output_file, + size_t file_size) +{ + char mutable_name[DAG_MUTABLE_NAME_MAX_SIZE]; + enum ethash_io_rc ret = ETHASH_IO_FAIL; + + // assert directory exists + if (!ethash_mkdir(dirname)) { + goto end; + } + + ethash_io_mutable_name(REVISION, &seedhash, mutable_name); + char *tmpfile = ethash_io_create_filename(dirname, mutable_name, strlen(mutable_name)); + if (!tmpfile) { + goto end; + } + + // try to open the file + FILE *f = ethash_fopen(tmpfile, "rb+"); + if (f) { + size_t found_size; + if (!ethash_file_size(f, &found_size)) { + fclose(f); + goto free_memo; + } + if (file_size != found_size) { + fclose(f); + ret = ETHASH_IO_MEMO_SIZE_MISMATCH; + goto free_memo; + } + } else { + // file does not exist, will need to be created + f = ethash_fopen(tmpfile, "wb+"); + if (!f) { + goto free_memo; + } + // make sure it's of the proper size + if (fseek(f, file_size - 1, SEEK_SET) != 0) { + fclose(f); + goto free_memo; + } + fputc('\n', f); + fflush(f); + ret = ETHASH_IO_MEMO_MISMATCH; + goto set_file; + } + + ret = ETHASH_IO_MEMO_MATCH; +set_file: + *output_file = f; +free_memo: + free(tmpfile); +end: + return ret; +} diff --git a/io.h b/io.h index 736309971..c27344b7f 100644 --- a/io.h +++ b/io.h @@ -37,9 +37,10 @@ extern "C" { #define DAG_MUTABLE_NAME_MAX_SIZE (10 + 1 + 16 + 1) /// Possible return values of @see ethash_io_prepare enum ethash_io_rc { - ETHASH_IO_FAIL = 0, ///< There has been an IO failure - ETHASH_IO_MEMO_MISMATCH, ///< The DAG file did not exist or there was revision/hash mismatch - ETHASH_IO_MEMO_MATCH, ///< DAG file existed and revision/hash matched. No need to do anything + ETHASH_IO_FAIL = 0, ///< There has been an IO failure + ETHASH_IO_MEMO_SIZE_MISMATCH, ///< DAG with revision/hash match, but file size was wrong. + ETHASH_IO_MEMO_MISMATCH, ///< The DAG file did not exist or there was revision/hash mismatch + ETHASH_IO_MEMO_MATCH, ///< DAG file existed and revision/hash matched. No need to do anything }; /** @@ -78,6 +79,7 @@ enum ethash_io_rc ethash_io_prepare(char const *dirname, * @return The FILE* or NULL in failure */ FILE *ethash_fopen(const char *file_name, const char *mode); + /** * An strncat wrapper for no-warnings crossplatform strncat. * @@ -96,6 +98,32 @@ FILE *ethash_fopen(const char *file_name, const char *mode); */ char *ethash_strncat(char *dest, size_t dest_size, const char *src, size_t count); +/** + * A cross-platform mkdir wrapper to create a directory or assert it's there + * + * @param dirname The full path of the directory to create + * @return true if the directory was created or if it already + * existed + */ +bool ethash_mkdir(char const *dirname); + +/** + * Get a file's size + * + * @param[in] f The open file stream whose size to get + * @param[out] size Pass a size_t by reference to contain the file size + * @return true in success and false if there was a failure + */ +bool ethash_file_size(FILE *f, size_t *ret_size); + +/** + * Get a file descriptor number from a FILE stream + * + * @param f The file stream whose fd to get + * @return Platform specific fd handler + */ +int ethash_fileno(FILE *f); + static inline bool ethash_io_mutable_name(uint32_t revision, ethash_h256_t const* seed_hash, char* output) diff --git a/io_posix.c b/io_posix.c index 3aa28d3ad..fd4bdafbd 100644 --- a/io_posix.c +++ b/io_posix.c @@ -37,52 +37,24 @@ char *ethash_strncat(char *dest, size_t dest_size, const char *src, size_t count return strlen(dest) + count + 1 <= dest_size ? strncat(dest, src, count) : NULL; } -enum ethash_io_rc ethash_io_prepare(char const *dirname, - ethash_h256_t const seedhash, - FILE **output_file, - size_t file_size) +bool ethash_mkdir(char const *dirname) { - char mutable_name[DAG_MUTABLE_NAME_MAX_SIZE]; - enum ethash_io_rc ret = ETHASH_IO_FAIL; - - // assert directory exists, full owner permissions and read/search for others int rc = mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - if (rc == -1 && errno != EEXIST) { - goto end; - } + return rc != -1 || errno == EEXIST; +} - ethash_io_mutable_name(REVISION, &seedhash, mutable_name); - char *tmpfile = ethash_io_create_filename(dirname, mutable_name, strlen(mutable_name)); - if (!tmpfile) { - goto end; - } +int ethash_fileno(FILE *f) +{ + return fileno(f); +} - // try to open the file - FILE *f = ethash_fopen(tmpfile, "rb+"); - if (f) { - // TODO: check for file size - } else { - // file does not exist, will need to be created - f = ethash_fopen(tmpfile, "wb+"); - if (!f) { - goto free_memo; - } - // make sure it's of the proper size - if (fseek(f, file_size - 1, SEEK_SET) != 0) { - fclose(f); - goto free_memo; - } - fputc('\n', f); - fflush(f); - ret = ETHASH_IO_MEMO_MISMATCH; - goto set_file; +bool ethash_file_size(FILE *f, size_t *ret_size) +{ + struct stat st; + int fd; + if ((fd = fileno(f)) == -1 || fstat(fd, &st) != 0) { + return false; } - - ret = ETHASH_IO_MEMO_MATCH; -set_file: - *output_file = f; -free_memo: - free(tmpfile); -end: - return ret; + *ret_size = st.st_size; + return true; } diff --git a/io_win32.c b/io_win32.c index 17d0983b9..9906c359e 100644 --- a/io_win32.c +++ b/io_win32.c @@ -35,50 +35,24 @@ char *ethash_strncat(char *dest, size_t dest_size, const char *src, size_t count return strncat_s(dest, dest_size, src, count) == 0 ? dest : NULL; } -enum ethash_io_rc ethash_io_prepare(char const *dirname, - ethash_h256_t const seedhash, - FILE **output_file, - size_t file_size) +bool ethash_mkdir(char const *dirname) { - char mutable_name[DAG_MUTABLE_NAME_MAX_SIZE]; - enum ethash_io_rc ret = ETHASH_IO_FAIL; - - // assert directory exists int rc = _mkdir(dirname); - if (rc == -1 && errno != EEXIST) { - goto end; - } + return rc != -1 || errno == EEXIST; +} - ethash_io_mutable_name(REVISION, &seedhash, mutable_name); - char *tmpfile = ethash_io_create_filename(dirname, mutable_name, strlen(mutable_name)); - if (!tmpfile) { - goto end; - } +int ethash_fileno(FILE *f) +{ + return _fileno(f); +} - // try to open the file - FILE *f = ethash_fopen(tmpfile, "rb+"); - if (!f) { - // file does not exist, will need to be created - f = ethash_fopen(tmpfile, "wb+"); - if (!f) { - goto free_memo; - } - // make sure it's of the proper size - if (fseek(f, file_size - 1, SEEK_SET) != 0) { - fclose(f); - goto free_memo; - } - fputc('\n', f); - fflush(f); - ret = ETHASH_IO_MEMO_MISMATCH; - goto set_file; +bool ethash_file_size(FILE *f, size_t *ret_size) +{ + struct _stat st; + int fd; + if ((fd = _fileno(f)) == -1 || _fstat(fd, &st) != 0) { + return false; } - - ret = ETHASH_IO_MEMO_MATCH; -set_file: - *output_file = f; -free_memo: - free(tmpfile); -end: - return ret; + *ret_size = st.st_size; + return true; }