diff --git a/CHANGES.md b/CHANGES.md index 1332b459c..c8bb1f535 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,14 @@ # Major changes to the IOCCC entry toolkit +## Release 1.5.1 2024-08-28 + +Move `open_json_dir_file()` from `chkentry.c` to `open_dir_file()` in +`jparse/util.c`. + +Updated `MKIOCCCENTRY_REPO_VERSION` version to "1.5.1 2024-08-28". + + ## Release 1.5 2024-08-27 Prep for "**Release 1.5 2024-08-27**". diff --git a/chkentry.c b/chkentry.c index 998036dc2..e9fdc91c7 100644 --- a/chkentry.c +++ b/chkentry.c @@ -3,11 +3,14 @@ * * "Because grammar and syntax alone do not make a complete language." :-) * - * This tool was improved by: + * This tool and the JSON parser were co-developed in 2022-2024 by Cody Boone + * Ferguson and Landon Curt Noll: * * @xexyl * https://xexyl.net Cody Boone Ferguson * https://ioccc.xexyl.net + * and: + * chongo (Landon Curt Noll, http://www.isthe.com/chongo/index.html) /\oo/\ * * "Because sometimes even the IOCCC Judges need some help." :-) * @@ -15,30 +18,6 @@ * * "Share and Enjoy!" * -- Sirius Cybernetics Corporation Complaints Division, JSON spec department. :-) - * - * Copyright (c) 2022-2024 by Landon Curt Noll. All Rights Reserved. - * - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby granted, - * provided that the above copyright, this permission notice and text - * this comment, and the disclaimer below appear in all of the following: - * - * supporting documentation - * source copies - * source works derived from this source - * binaries derived from this source or from derived source - * - * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO - * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - * - * chongo (Landon Curt Noll, http://www.isthe.com/chongo/index.html) /\oo/\ - * - * Share and enjoy! :-) */ @@ -50,7 +29,6 @@ #include #include #include -#include /* for open() */ /* * chkentry - check JSON files in an IOCCC submission @@ -105,144 +83,8 @@ static const char * const usage_msg = /* * functions */ -static FILE *open_json_dir_file(char const *dir, char const *file); static void usage(int exitcode, char const *prog, char const *str) __attribute__((noreturn)); - -/* - * open_json_dir_file - open a readable JSON file in a given directory - * - * Temporarily chdir to the directory, if non-NULL, try to open the file, - * and then chdir back to the current directory. - * - * If dir == NULL, just try to open the file without a chdir. - * - * given: - * dir directory into which we will temporarily chdir or - * NULL ==> do not chdir - * file path of readable JSON file to open - * - * returns: - * open readable JSON file stream - * - * NOTE: This function does not return if path is NULL, - * if we cannot chdir to a non-NULL dir, if not a readable file, - * or if unable to open file. - * - * NOTE: This function will NOT return NULL. - */ -static FILE * -open_json_dir_file(char const *dir, char const *file) -{ - FILE *ret_stream = NULL; /* open file stream to return */ - int ret = 0; /* libc function return */ - int cwd = -1; /* current working directory */ - - /* - * firewall - */ - if (file == NULL) { - err(10, __func__, "called with NULL file"); - not_reached(); - } - - /* - * note the current directory so we can restore it later, after the chdir(work_dir) below - */ - errno = 0; /* pre-clear errno for errp() */ - cwd = open(".", O_RDONLY|O_DIRECTORY|O_CLOEXEC); - if (cwd < 0) { - errp(11, __func__, "cannot open ."); - not_reached(); - } - - /* - * Temporarily chdir if dir is non-NULL - */ - if (dir != NULL && cwd >= 0) { - - /* - * check if we can search / work within the directory - */ - if (!exists(dir)) { - err(12, __func__, "directory does not exist: %s", dir); - not_reached(); - } - if (!is_dir(dir)) { - err(13, __func__, "is not a directory: %s", dir); - not_reached(); - } - if (!is_exec(dir)) { - err(14, __func__, "directory is not searchable: %s", dir); - not_reached(); - } - - /* - * chdir to to the directory - */ - errno = 0; /* pre-clear errno for errp() */ - ret = chdir(dir); - if (ret < 0) { - errp(15, __func__, "cannot cd %s", dir); - not_reached(); - } - } - - /* - * must be a readable file - */ - if (!exists(file)) { - err(16, __func__, "file does not exist: %s", file); - not_reached(); - } - if (!is_file(file)) { - err(17, __func__, "file is not a regular file: %s", file); - not_reached(); - } - if (!is_read(file)) { - err(18, __func__, "file is not a readable file: %s", file); - not_reached(); - } - - /* - * open the readable JSON file - */ - errno = 0; /* pre-clear errno for errp() */ - ret_stream = fopen(file, "r"); - if (ret_stream == NULL) { - errp(19, __func__, "cannot open file: %s", file); - not_reached(); - } - - /* - * if we did a chdir to dir, chdir back to cwd - */ - if (dir != NULL && cwd >= 0) { - - /* - * switch back to the previous current directory - */ - errno = 0; /* pre-clear errno for errp() */ - ret = fchdir(cwd); - if (ret < 0) { - errp(20, __func__, "cannot fchdir to the previous current directory"); - not_reached(); - } - errno = 0; /* pre-clear errno for errp() */ - ret = close(cwd); - if (ret < 0) { - errp(21, __func__, "close of previous current directory failed"); - not_reached(); - } - } - - /* - * return open stream - */ - return ret_stream; -} - - /* * usage - print usage to stderr * @@ -423,9 +265,9 @@ main(int argc, char *argv[]) * open the .info.json file under submission_dir */ info_filename = ".info.json"; - info_stream = open_json_dir_file(submission_dir, info_filename); + info_stream = open_dir_file(submission_dir, info_filename); if (info_stream == NULL) { /* paranoia */ - err(22, __func__, "info_stream = open_json_dir_file(%s, %s) returned NULL", submission_dir, info_filename); + err(22, __func__, "info_stream = open_dir_file(%s, %s) returned NULL", submission_dir, info_filename); not_reached(); } @@ -433,9 +275,9 @@ main(int argc, char *argv[]) * open the .auth.json file under submission_dir */ auth_filename = ".auth.json"; - auth_stream = open_json_dir_file(submission_dir, auth_filename); + auth_stream = open_dir_file(submission_dir, auth_filename); if (auth_stream == NULL) { /* paranoia */ - err(23, __func__, "auth_stream = open_json_dir_file(%s, %s) returned NULL", submission_dir, auth_filename); + err(23, __func__, "auth_stream = open_dir_file(%s, %s) returned NULL", submission_dir, auth_filename); not_reached(); } @@ -448,9 +290,9 @@ main(int argc, char *argv[]) * open the .info.json file unless it is . */ if (strcmp(info_filename, ".") != 0) { - info_stream = open_json_dir_file(NULL, info_filename); + info_stream = open_dir_file(NULL, info_filename); if (info_stream == NULL) { /* paranoia */ - err(24, __func__, "open_json_dir_file for returned NULL for .info.json path: %s", info_filename); + err(24, __func__, "open_dir_file returned NULL for .info.json path: %s", info_filename); not_reached(); } } else { @@ -461,9 +303,9 @@ main(int argc, char *argv[]) * open the .auth.json file unless it is . */ if (strcmp(auth_filename, ".") != 0) { - auth_stream = open_json_dir_file(NULL, auth_filename); + auth_stream = open_dir_file(NULL, auth_filename); if (auth_stream == NULL) { /* paranoia */ - err(25, __func__, "open_json_dir_file for returned NULL for .auth.json path: %s", auth_filename); + err(25, __func__, "open_dir_file returned NULL for .auth.json path: %s", auth_filename); not_reached(); } } else { diff --git a/chkentry.h b/chkentry.h index cd278bc7e..a3c5d8a95 100644 --- a/chkentry.h +++ b/chkentry.h @@ -3,11 +3,14 @@ * * "Because grammar and syntax alone do not make a complete language." :-) * - * This tool was improved by: + * This tool and the JSON parser were co-developed in 2022-2024 by Cody Boone + * Ferguson and Landon Curt Noll: * * @xexyl * https://xexyl.net Cody Boone Ferguson * https://ioccc.xexyl.net + * and: + * chongo (Landon Curt Noll, http://www.isthe.com/chongo/index.html) /\oo/\ * * "Because sometimes even the IOCCC Judges need some help." :-) * @@ -15,30 +18,6 @@ * * "Share and Enjoy!" * -- Sirius Cybernetics Corporation Complaints Division, JSON spec department. :-) - * - * Copyright (c) 2022-2024 by Landon Curt Noll. All Rights Reserved. - * - * Permission to use, copy, modify, and distribute this software and - * its documentation for any purpose and without fee is hereby granted, - * provided that the above copyright, this permission notice and text - * this comment, and the disclaimer below appear in all of the following: - * - * supporting documentation - * source copies - * source works derived from this source - * binaries derived from this source or from derived source - * - * LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO - * EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - * - * chongo (Landon Curt Noll, http://www.isthe.com/chongo/index.html) /\oo/\ - * - * Share and enjoy! :-) */ diff --git a/jparse/util.c b/jparse/util.c index 109fabd80..f11271271 100644 --- a/jparse/util.c +++ b/jparse/util.c @@ -44,6 +44,7 @@ #include #include #include +#include /* for open() */ /* * dbg - info, debug, warning, error, and usage message facility @@ -4423,6 +4424,141 @@ calloc_path(char const *dirname, char const *filename) return buf; } +/* + * open_dir_file - open a readable file in a given directory + * + * Temporarily chdir to the directory, if non-NULL, try to open the file, + * and then chdir back to the current directory. + * + * If dir == NULL, just try to open the file without a chdir. + * + * given: + * dir directory into which we will temporarily chdir or + * NULL ==> do not chdir + * file path of readable file to open + * + * returns: + * open readable file stream + * + * NOTE: This function does not return if path is NULL, + * if we cannot chdir to a non-NULL dir, if not a readable file, + * or if unable to open file. + * + * NOTE: This function will NOT return NULL. + */ +FILE * +open_dir_file(char const *dir, char const *file) +{ + FILE *ret_stream = NULL; /* open file stream to return */ + int ret = 0; /* libc function return */ + int cwd = -1; /* current working directory */ + + /* + * firewall + */ + if (file == NULL) { + err(158, __func__, "called with NULL file"); + not_reached(); + } + + /* + * note the current directory so we can restore it later, after the chdir(work_dir) below + */ + errno = 0; /* pre-clear errno for errp() */ + cwd = open(".", O_RDONLY|O_DIRECTORY|O_CLOEXEC); + if (cwd < 0) { + errp(159, __func__, "cannot open ."); + not_reached(); + } + + /* + * Temporarily chdir if dir is non-NULL + */ + if (dir != NULL && cwd >= 0) { + + /* + * check if we can search / work within the directory + */ + if (!exists(dir)) { + err(160, __func__, "directory does not exist: %s", dir); + not_reached(); + } + if (!is_dir(dir)) { + err(161, __func__, "is not a directory: %s", dir); + not_reached(); + } + if (!is_exec(dir)) { + err(162, __func__, "directory is not searchable: %s", dir); + not_reached(); + } + + /* + * chdir to to the directory + */ + errno = 0; /* pre-clear errno for errp() */ + ret = chdir(dir); + if (ret < 0) { + errp(163, __func__, "cannot cd %s", dir); + not_reached(); + } + } + + /* + * must be a readable file + */ + if (!exists(file)) { + err(164, __func__, "file does not exist: %s", file); + not_reached(); + } + if (!is_file(file)) { + err(165, __func__, "file is not a regular file: %s", file); + not_reached(); + } + if (!is_read(file)) { + err(166, __func__, "file is not a readable file: %s", file); + not_reached(); + } + + /* + * open the readable file + */ + errno = 0; /* pre-clear errno for errp() */ + ret_stream = fopen(file, "r"); + if (ret_stream == NULL) { + errp(167, __func__, "cannot open file: %s", file); + not_reached(); + } + + /* + * if we did a chdir to dir, chdir back to cwd + */ + if (dir != NULL && cwd >= 0) { + + /* + * switch back to the previous current directory + */ + errno = 0; /* pre-clear errno for errp() */ + ret = fchdir(cwd); + if (ret < 0) { + errp(168, __func__, "cannot fchdir to the previous current directory"); + not_reached(); + } + errno = 0; /* pre-clear errno for errp() */ + ret = close(cwd); + if (ret < 0) { + errp(169, __func__, "close of previous current directory failed"); + not_reached(); + } + } + + /* + * return open stream + */ + return ret_stream; +} + + + /* * count_char - count the number of instances of a char in the string @@ -4444,7 +4580,7 @@ count_char(char const *str, int ch) * firewall */ if (str == NULL) { - err(158, __func__, "given NULL str"); + err(170, __func__, "given NULL str"); not_reached(); } diff --git a/jparse/util.h b/jparse/util.h index 0ffe6f190..bf6d63c75 100644 --- a/jparse/util.h +++ b/jparse/util.h @@ -221,6 +221,7 @@ extern void clearerr_or_fclose(FILE *stream); extern ssize_t fprint_line_buf(FILE *stream, const void *buf, size_t len, int start, int end); extern ssize_t fprint_line_str(FILE *stream, char *str, size_t *retlen, int start, int end); extern char *calloc_path(char const *dirname, char const *filename); +extern FILE *open_dir_file(char const *dir, char const *file); extern size_t count_char(char const *str, int ch); diff --git a/soup/version.h b/soup/version.h index b518994d8..36e65edfc 100644 --- a/soup/version.h +++ b/soup/version.h @@ -66,7 +66,7 @@ * * NOTE: This should match the latest Release string in CHANGES.md */ -#define MKIOCCCENTRY_REPO_VERSION "1.5 2024-08-27" /* special release format: major.minor.patch YYYY-MM-DD */ +#define MKIOCCCENTRY_REPO_VERSION "1.5.1 2024-08-28" /* special release format: major.minor.patch YYYY-MM-DD */ /* * official soup version (aka recipe :-) )