mirror of
https://github.com/cuberite/libdeflate.git
synced 2025-09-10 04:41:45 -04:00
gzip, gunzip: add dumb support for reading from stdin
No streaming yet, but as a temporary solution just read the full file contents.
This commit is contained in:
parent
3a7658d144
commit
5cc0fc2bbd
@ -18,7 +18,7 @@ libdeflate itself is a library, but the following command-line programs which
|
|||||||
use this library are also provided:
|
use this library are also provided:
|
||||||
|
|
||||||
* gzip (or gunzip), a program which mostly behaves like the standard equivalent,
|
* gzip (or gunzip), a program which mostly behaves like the standard equivalent,
|
||||||
except that it does not yet support reading from standard input and does not
|
except that it does not yet have good streaming support and therefore does not
|
||||||
yet support very large files
|
yet support very large files
|
||||||
* benchmark, a program for benchmarking in-memory compression and decompression
|
* benchmark, a program for benchmarking in-memory compression and decompression
|
||||||
|
|
||||||
|
@ -382,6 +382,7 @@ decompress_file(struct libdeflate_decompressor *decompressor, const tchar *path,
|
|||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto out_close_in;
|
goto out_close_in;
|
||||||
|
|
||||||
|
/* TODO: need a streaming-friendly solution */
|
||||||
ret = map_file_contents(&in, stbuf.st_size);
|
ret = map_file_contents(&in, stbuf.st_size);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto out_close_out;
|
goto out_close_out;
|
||||||
@ -453,8 +454,9 @@ compress_file(struct libdeflate_compressor *compressor, const tchar *path,
|
|||||||
goto out_close_out;
|
goto out_close_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: need a streaming-friendly solution */
|
||||||
ret = map_file_contents(&in, stbuf.st_size);
|
ret = map_file_contents(&in, stbuf.st_size);
|
||||||
if (ret)
|
if (ret != 0)
|
||||||
goto out_close_out;
|
goto out_close_out;
|
||||||
|
|
||||||
ret = do_compress(compressor, &in, &out);
|
ret = do_compress(compressor, &in, &out);
|
||||||
@ -482,6 +484,7 @@ out_free_newpath:
|
|||||||
int
|
int
|
||||||
tmain(int argc, tchar *argv[])
|
tmain(int argc, tchar *argv[])
|
||||||
{
|
{
|
||||||
|
tchar *default_file_list[] = { NULL };
|
||||||
struct options options;
|
struct options options;
|
||||||
int opt_char;
|
int opt_char;
|
||||||
int i;
|
int i;
|
||||||
@ -547,15 +550,12 @@ tmain(int argc, tchar *argv[])
|
|||||||
argc -= toptind;
|
argc -= toptind;
|
||||||
|
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
show_usage(stderr);
|
argv = default_file_list;
|
||||||
return 1;
|
argc = ARRAY_LEN(default_file_list);
|
||||||
}
|
} else {
|
||||||
for (i = 0; i < argc; i++) {
|
for (i = 0; i < argc; i++)
|
||||||
if (argv[i][0] == '-' && argv[i][1] == '\0') {
|
if (argv[i][0] == '-' && argv[i][1] == '\0')
|
||||||
msg("This implementation of gzip does not yet "
|
argv[i] = NULL;
|
||||||
"support reading from standard input.");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
@ -204,6 +204,7 @@ quote_path(const tchar *path)
|
|||||||
int
|
int
|
||||||
xopen_for_read(const tchar *path, bool symlink_ok, struct file_stream *strm)
|
xopen_for_read(const tchar *path, bool symlink_ok, struct file_stream *strm)
|
||||||
{
|
{
|
||||||
|
strm->mmap_token = NULL;
|
||||||
strm->mmap_mem = NULL;
|
strm->mmap_mem = NULL;
|
||||||
|
|
||||||
if (path == NULL) {
|
if (path == NULL) {
|
||||||
@ -243,6 +244,7 @@ xopen_for_write(const tchar *path, bool overwrite, struct file_stream *strm)
|
|||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
|
strm->mmap_token = NULL;
|
||||||
strm->mmap_mem = NULL;
|
strm->mmap_mem = NULL;
|
||||||
|
|
||||||
if (path == NULL) {
|
if (path == NULL) {
|
||||||
@ -297,14 +299,56 @@ err:
|
|||||||
return ret;
|
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 */
|
/* Map the contents of a file into memory */
|
||||||
int
|
int
|
||||||
map_file_contents(struct file_stream *strm, u64 size)
|
map_file_contents(struct file_stream *strm, u64 size)
|
||||||
{
|
{
|
||||||
if (size == 0) {
|
if (size == 0) /* mmap isn't supported on empty files */
|
||||||
strm->mmap_size = 0;
|
return read_full_contents(strm);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size > SIZE_MAX) {
|
if (size > SIZE_MAX) {
|
||||||
msg("%"TS" is too large to be processed by this program",
|
msg("%"TS" is too large to be processed by this program",
|
||||||
@ -316,8 +360,11 @@ map_file_contents(struct file_stream *strm, u64 size)
|
|||||||
(HANDLE)(intptr_t)_get_osfhandle(strm->fd),
|
(HANDLE)(intptr_t)_get_osfhandle(strm->fd),
|
||||||
NULL, PAGE_READONLY, 0, 0, NULL);
|
NULL, PAGE_READONLY, 0, 0, NULL);
|
||||||
if (strm->mmap_token == 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",
|
msg("Unable create file mapping for %"TS": Windows error %u",
|
||||||
strm->name, (unsigned int)GetLastError());
|
strm->name, (unsigned int)err);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,6 +380,8 @@ map_file_contents(struct file_stream *strm, u64 size)
|
|||||||
strm->mmap_mem = mmap(NULL, size, PROT_READ, MAP_SHARED, strm->fd, 0);
|
strm->mmap_mem = mmap(NULL, size, PROT_READ, MAP_SHARED, strm->fd, 0);
|
||||||
if (strm->mmap_mem == MAP_FAILED) {
|
if (strm->mmap_mem == MAP_FAILED) {
|
||||||
strm->mmap_mem = NULL;
|
strm->mmap_mem = NULL;
|
||||||
|
if (errno == ENODEV) /* mmap isn't supported on this file */
|
||||||
|
return read_full_contents(strm);
|
||||||
if (errno == ENOMEM) {
|
if (errno == ENOMEM) {
|
||||||
msg("%"TS" is too large to be processed by this "
|
msg("%"TS" is too large to be processed by this "
|
||||||
"program", strm->name);
|
"program", strm->name);
|
||||||
@ -346,6 +395,7 @@ map_file_contents(struct file_stream *strm, u64 size)
|
|||||||
#ifdef HAVE_POSIX_MADVISE
|
#ifdef HAVE_POSIX_MADVISE
|
||||||
posix_madvise(strm->mmap_mem, size, POSIX_MADV_SEQUENTIAL);
|
posix_madvise(strm->mmap_mem, size, POSIX_MADV_SEQUENTIAL);
|
||||||
#endif
|
#endif
|
||||||
|
strm->mmap_token = strm; /* anything that's not NULL */
|
||||||
|
|
||||||
#endif /* !_WIN32 */
|
#endif /* !_WIN32 */
|
||||||
strm->mmap_size = size;
|
strm->mmap_size = size;
|
||||||
@ -401,23 +451,27 @@ int
|
|||||||
xclose(struct file_stream *strm)
|
xclose(struct file_stream *strm)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if (strm->fd >= 0 && !strm->is_standard_stream) {
|
|
||||||
|
if (!strm->is_standard_stream) {
|
||||||
if (close(strm->fd) != 0) {
|
if (close(strm->fd) != 0) {
|
||||||
msg_errno("Error closing %"TS, strm->name);
|
msg_errno("Error closing %"TS, strm->name);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
free(strm->name);
|
free(strm->name);
|
||||||
|
|
||||||
if (strm->mmap_mem != NULL) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
UnmapViewOfFile(strm->mmap_mem);
|
|
||||||
CloseHandle((HANDLE)strm->mmap_token);
|
|
||||||
#else
|
|
||||||
munmap(strm->mmap_mem, strm->mmap_size);
|
|
||||||
#endif
|
|
||||||
strm->mmap_mem = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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->fd = -1;
|
||||||
strm->name = NULL;
|
strm->name = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user