diff options
Diffstat (limited to 'util/compress/libdeflate/programs/prog_util.c')
-rw-r--r-- | util/compress/libdeflate/programs/prog_util.c | 496 |
1 files changed, 0 insertions, 496 deletions
diff --git a/util/compress/libdeflate/programs/prog_util.c b/util/compress/libdeflate/programs/prog_util.c deleted file mode 100644 index 343828143..000000000 --- a/util/compress/libdeflate/programs/prog_util.c +++ /dev/null @@ -1,496 +0,0 @@ -/* - * prog_util.c - utility functions for programs - * - * Copyright 2016 Eric Biggers - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include "prog_util.h" - -#include <errno.h> -#include <fcntl.h> -#include <stdarg.h> -#ifdef _WIN32 -# include <windows.h> -#else -# include <unistd.h> -# include <sys/mman.h> -#endif - -#ifndef O_BINARY -# define O_BINARY 0 -#endif -#ifndef O_SEQUENTIAL -# define O_SEQUENTIAL 0 -#endif -#ifndef O_NOFOLLOW -# define O_NOFOLLOW 0 -#endif -#ifndef O_NONBLOCK -# define O_NONBLOCK 0 -#endif -#ifndef O_NOCTTY -# define O_NOCTTY 0 -#endif - -/* The invocation name of the program (filename component only) */ -const tchar *prog_invocation_name; - -static void -do_msg(const char *format, bool with_errno, va_list va) -{ - int saved_errno = errno; - - fprintf(stderr, "%"TS": ", prog_invocation_name); - vfprintf(stderr, format, va); - if (with_errno) - fprintf(stderr, ": %s\n", strerror(saved_errno)); - else - fprintf(stderr, "\n"); - - errno = saved_errno; -} - -/* Print a message to standard error */ -void -msg(const char *format, ...) -{ - va_list va; - - va_start(va, format); - do_msg(format, false, va); - va_end(va); -} - -/* Print a message to standard error, including a description of errno */ -void -msg_errno(const char *format, ...) -{ - va_list va; - - va_start(va, format); - do_msg(format, true, va); - va_end(va); -} - -/* malloc() wrapper */ -void * -xmalloc(size_t size) -{ - void *p = malloc(size); - if (p == NULL && size == 0) - p = malloc(1); - if (p == NULL) - msg("Out of memory"); - return p; -} - -/* - * Retrieve a pointer to the filename component of the specified path. - * - * Note: this does not modify the path. Therefore, it is not guaranteed to work - * properly for directories, since a path to a directory might have trailing - * slashes. - */ -static const tchar * -get_filename(const tchar *path) -{ - const tchar *slash = tstrrchr(path, '/'); -#ifdef _WIN32 - const tchar *backslash = tstrrchr(path, '\\'); - if (backslash != NULL && (slash == NULL || backslash > slash)) - slash = backslash; -#endif - if (slash != NULL) - return slash + 1; - return path; -} - -void -begin_program(tchar *argv[]) -{ - prog_invocation_name = get_filename(argv[0]); - -#ifdef FREESTANDING - /* This allows testing freestanding library builds. */ - libdeflate_set_memory_allocator(malloc, free); -#endif -} - -/* Create a copy of 'path' surrounded by double quotes */ -static tchar * -quote_path(const tchar *path) -{ - size_t len = tstrlen(path); - tchar *result; - - result = xmalloc((1 + len + 1 + 1) * sizeof(tchar)); - if (result == NULL) - return NULL; - result[0] = '"'; - tmemcpy(&result[1], path, len); - result[1 + len] = '"'; - result[1 + len + 1] = '\0'; - return result; -} - -/* Open a file for reading, or set up standard input for reading */ -int -xopen_for_read(const tchar *path, bool symlink_ok, struct file_stream *strm) -{ - strm->mmap_token = NULL; - strm->mmap_mem = NULL; - - if (path == NULL) { - strm->is_standard_stream = true; - strm->name = T("standard input"); - strm->fd = STDIN_FILENO; - #ifdef _WIN32 - _setmode(strm->fd, O_BINARY); - #endif - return 0; - } - - strm->is_standard_stream = false; - - strm->name = quote_path(path); - if (strm->name == NULL) - return -1; - - strm->fd = topen(path, O_RDONLY | O_BINARY | O_NONBLOCK | O_NOCTTY | - (symlink_ok ? 0 : O_NOFOLLOW) | O_SEQUENTIAL); - if (strm->fd < 0) { - msg_errno("Can't open %"TS" for reading", strm->name); - free(strm->name); - return -1; - } - -#if defined(HAVE_POSIX_FADVISE) && (O_SEQUENTIAL == 0) - (void)posix_fadvise(strm->fd, 0, 0, POSIX_FADV_SEQUENTIAL); -#endif - - return 0; -} - -/* Open a file for writing, or set up standard output for writing */ -int -xopen_for_write(const tchar *path, bool overwrite, struct file_stream *strm) -{ - int ret = -1; - - strm->mmap_token = NULL; - strm->mmap_mem = NULL; - - if (path == NULL) { - strm->is_standard_stream = true; - strm->name = T("standard output"); - strm->fd = STDOUT_FILENO; - #ifdef _WIN32 - _setmode(strm->fd, O_BINARY); - #endif - return 0; - } - - strm->is_standard_stream = false; - - strm->name = quote_path(path); - if (strm->name == NULL) - goto err; -retry: - strm->fd = topen(path, O_WRONLY | O_BINARY | O_NOFOLLOW | - O_CREAT | O_EXCL, 0644); - if (strm->fd < 0) { - if (errno != EEXIST) { - msg_errno("Can't open %"TS" for writing", strm->name); - goto err; - } - if (!overwrite) { - if (!isatty(STDERR_FILENO) || !isatty(STDIN_FILENO)) { - msg("%"TS" already exists; use -f to overwrite", - strm->name); - ret = -2; /* warning only */ - goto err; - } - fprintf(stderr, "%"TS": %"TS" already exists; " - "overwrite? (y/n) ", - prog_invocation_name, strm->name); - if (getchar() != 'y') { - msg("Not overwriting."); - goto err; - } - } - if (tunlink(path) != 0) { - msg_errno("Unable to delete %"TS, strm->name); - goto err; - } - goto retry; - } - - return 0; - -err: - free(strm->name); - return ret; -} - -/* Read the full contents of a file into memory */ -static int -read_full_contents(struct file_stream *strm) -{ - size_t filled = 0; - size_t capacity = 4096; - char *buf; - int ret; - - buf = xmalloc(capacity); - if (buf == NULL) - return -1; - do { - if (filled == capacity) { - char *newbuf; - - if (capacity == SIZE_MAX) - goto oom; - capacity += MIN(SIZE_MAX - capacity, capacity); - newbuf = realloc(buf, capacity); - if (newbuf == NULL) - goto oom; - buf = newbuf; - } - ret = xread(strm, &buf[filled], capacity - filled); - if (ret < 0) - goto err; - filled += ret; - } while (ret != 0); - - strm->mmap_mem = buf; - strm->mmap_size = filled; - return 0; - -err: - free(buf); - return ret; -oom: - msg("Out of memory! %"TS" is too large to be processed by " - "this program as currently implemented.", strm->name); - ret = -1; - goto err; -} - -/* Map the contents of a file into memory */ -int -map_file_contents(struct file_stream *strm, u64 size) -{ - if (size == 0) /* mmap isn't supported on empty files */ - return read_full_contents(strm); - - if (size > SIZE_MAX) { - msg("%"TS" is too large to be processed by this program", - strm->name); - return -1; - } -#ifdef _WIN32 - strm->mmap_token = CreateFileMapping( - (HANDLE)(intptr_t)_get_osfhandle(strm->fd), - NULL, PAGE_READONLY, 0, 0, NULL); - if (strm->mmap_token == NULL) { - DWORD err = GetLastError(); - if (err == ERROR_BAD_EXE_FORMAT) /* mmap unsupported */ - return read_full_contents(strm); - msg("Unable create file mapping for %"TS": Windows error %u", - strm->name, (unsigned int)err); - return -1; - } - - strm->mmap_mem = MapViewOfFile((HANDLE)strm->mmap_token, - FILE_MAP_READ, 0, 0, size); - if (strm->mmap_mem == NULL) { - msg("Unable to map %"TS" into memory: Windows error %u", - strm->name, (unsigned int)GetLastError()); - CloseHandle((HANDLE)strm->mmap_token); - return -1; - } -#else /* _WIN32 */ - strm->mmap_mem = mmap(NULL, size, PROT_READ, MAP_SHARED, strm->fd, 0); - if (strm->mmap_mem == MAP_FAILED) { - strm->mmap_mem = NULL; - if (errno == ENODEV) /* mmap isn't supported on this file */ - return read_full_contents(strm); - if (errno == ENOMEM) { - msg("%"TS" is too large to be processed by this " - "program", strm->name); - } else { - msg_errno("Unable to map %"TS" into memory", - strm->name); - } - return -1; - } - -#ifdef HAVE_POSIX_MADVISE - (void)posix_madvise(strm->mmap_mem, size, POSIX_MADV_SEQUENTIAL); -#endif - strm->mmap_token = strm; /* anything that's not NULL */ - -#endif /* !_WIN32 */ - strm->mmap_size = size; - return 0; -} - -/* - * Read from a file, returning the full count to indicate all bytes were read, a - * short count (possibly 0) to indicate EOF, or -1 to indicate error. - */ -ssize_t -xread(struct file_stream *strm, void *buf, size_t count) -{ - char *p = buf; - size_t orig_count = count; - - while (count != 0) { - ssize_t res = read(strm->fd, p, MIN(count, INT_MAX)); - if (res == 0) - break; - if (res < 0) { - if (errno == EAGAIN || errno == EINTR) - continue; - msg_errno("Error reading from %"TS, strm->name); - return -1; - } - p += res; - count -= res; - } - return orig_count - count; -} - -/* Write to a file, returning 0 if all bytes were written or -1 on error */ -int -full_write(struct file_stream *strm, const void *buf, size_t count) -{ - const char *p = buf; - - while (count != 0) { - ssize_t res = write(strm->fd, p, MIN(count, INT_MAX)); - if (res <= 0) { - msg_errno("Error writing to %"TS, strm->name); - return -1; - } - p += res; - count -= res; - } - return 0; -} - -/* Close a file, returning 0 on success or -1 on error */ -int -xclose(struct file_stream *strm) -{ - int ret = 0; - - if (!strm->is_standard_stream) { - if (close(strm->fd) != 0) { - msg_errno("Error closing %"TS, strm->name); - ret = -1; - } - free(strm->name); - } - - if (strm->mmap_token != NULL) { -#ifdef _WIN32 - UnmapViewOfFile(strm->mmap_mem); - CloseHandle((HANDLE)strm->mmap_token); -#else - munmap(strm->mmap_mem, strm->mmap_size); -#endif - strm->mmap_token = NULL; - } else { - free(strm->mmap_mem); - } - strm->mmap_mem = NULL; - strm->fd = -1; - strm->name = NULL; - return ret; -} - -/* - * Parse the compression level given on the command line, returning the - * compression level on success or -1 on error - */ -int -parse_compression_level(tchar opt_char, const tchar *arg) -{ - int level; - - if (arg == NULL) - arg = T(""); - - if (opt_char < '0' || opt_char > '9') - goto invalid; - level = opt_char - '0'; - - if (arg[0] != '\0') { - if (arg[0] < '0' || arg[0] > '9') - goto invalid; - if (arg[1] != '\0') /* Levels are at most 2 digits */ - goto invalid; - if (level == 0) /* Don't allow arguments like "-01" */ - goto invalid; - level = (level * 10) + (arg[0] - '0'); - } - - if (level < 0 || level > 12) - goto invalid; - - return level; - -invalid: - msg("Invalid compression level: \"%"TC"%"TS"\". " - "Must be an integer in the range [0, 12].", opt_char, arg); - return -1; -} - -/* Allocate a new DEFLATE compressor */ -struct libdeflate_compressor * -alloc_compressor(int level) -{ - struct libdeflate_compressor *c; - - c = libdeflate_alloc_compressor(level); - if (c == NULL) { - msg_errno("Unable to allocate compressor with " - "compression level %d", level); - } - return c; -} - -/* Allocate a new DEFLATE decompressor */ -struct libdeflate_decompressor * -alloc_decompressor(void) -{ - struct libdeflate_decompressor *d; - - d = libdeflate_alloc_decompressor(); - if (d == NULL) - msg_errno("Unable to allocate decompressor"); - - return d; -} |