Mercurial > molko
comparison src/libmlk-core/core/zfile.c @ 320:8f9937403749
misc: improve loading of data
author | David Demelier <markand@malikania.fr> |
---|---|
date | Fri, 01 Oct 2021 20:30:00 +0200 |
parents | libmlk-core/core/zfile.c@1a6125ffebff |
children | 7d7991f97acf |
comparison
equal
deleted
inserted
replaced
319:b843eef4cc35 | 320:8f9937403749 |
---|---|
1 /* | |
2 * zfile.c -- load potentially ZSTD compressed file | |
3 * | |
4 * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr> | |
5 * | |
6 * Permission to use, copy, modify, and/or distribute this software for any | |
7 * purpose with or without fee is hereby granted, provided that the above | |
8 * copyright notice and this permission notice appear in all copies. | |
9 * | |
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
17 */ | |
18 | |
19 #include "config.h" | |
20 | |
21 #include <sys/stat.h> | |
22 #include <assert.h> | |
23 #include <errno.h> | |
24 #include <fcntl.h> | |
25 #include <stdint.h> | |
26 #include <stdlib.h> | |
27 #include <string.h> | |
28 #include <unistd.h> | |
29 | |
30 /* | |
31 * If not enabled, we still need to check if a file is in zstandard so we use | |
32 * the magic number defined in the zstd.h file or copy it if zstd is disabled. | |
33 */ | |
34 #if defined(MLK_WITH_ZSTD) | |
35 # include <zstd.h> | |
36 #else | |
37 # define ZSTD_MAGICNUMBER 0xFD2FB528 | |
38 #endif | |
39 | |
40 /* Windows thing. */ | |
41 #if !defined(O_BINARY) | |
42 # define O_BINARY 0 | |
43 #endif | |
44 | |
45 #include <port/port.h> | |
46 | |
47 #include "zfile.h" | |
48 | |
49 static int | |
50 is_zstd(int fd) | |
51 { | |
52 uint32_t magic = 0; | |
53 | |
54 read(fd, &magic, sizeof (magic)); | |
55 lseek(fd, 0, SEEK_SET); | |
56 | |
57 #if SDL_BYTEORDER != SDL_LIL_ENDIAN | |
58 magic = SDL_Swap32(magic); | |
59 #endif | |
60 | |
61 return magic == ZSTD_MAGICNUMBER; | |
62 } | |
63 | |
64 static int | |
65 decompress(int fd, struct zfile *zf) | |
66 { | |
67 #if defined(MLK_WITH_ZSTD) | |
68 char *in = NULL; | |
69 unsigned long long datasz; | |
70 struct stat st; | |
71 ssize_t nr; | |
72 | |
73 /* Load uncompressed data. */ | |
74 if (fstat(fd, &st) < 0) | |
75 goto fail; | |
76 if (!(in = calloc(1, st.st_size)) || (nr = read(fd, in, st.st_size)) != st.st_size) | |
77 goto fail; | |
78 | |
79 switch ((datasz = ZSTD_getFrameContentSize(in, st.st_size))) { | |
80 case ZSTD_CONTENTSIZE_ERROR: | |
81 errno = EINVAL; | |
82 goto fail; | |
83 case ZSTD_CONTENTSIZE_UNKNOWN: | |
84 errno = ENOTSUP; | |
85 goto fail; | |
86 default: | |
87 break; | |
88 } | |
89 | |
90 /* Finally decompress. */ | |
91 if (!(zf->data = calloc(1, datasz + 1))) | |
92 goto fail; | |
93 if (ZSTD_isError(ZSTD_decompress(zf->data, datasz, in, st.st_size))) { | |
94 errno = EINVAL; | |
95 goto fail; | |
96 } | |
97 if (!(zf->fp = fmemopen(zf->data, datasz, "r"))) | |
98 goto fail; | |
99 | |
100 close(fd); | |
101 free(in); | |
102 | |
103 return 0; | |
104 | |
105 fail: | |
106 close(fd); | |
107 free(zf->data); | |
108 free(in); | |
109 | |
110 return -1; | |
111 #else | |
112 (void)fd; | |
113 (void)zf; | |
114 | |
115 errno = ENOTSUP; | |
116 | |
117 return -1; | |
118 #endif | |
119 } | |
120 | |
121 static int | |
122 reopen(int fd, struct zfile *zf) | |
123 { | |
124 if (!(zf->fp = fdopen(fd, "r"))) | |
125 return close(fd), -1; | |
126 | |
127 return 0; | |
128 } | |
129 | |
130 int | |
131 zfile_open(struct zfile *zf, const char *path) | |
132 { | |
133 assert(zf); | |
134 assert(path); | |
135 | |
136 int fd; | |
137 | |
138 memset(zf, 0, sizeof (*zf)); | |
139 | |
140 if ((fd = open(path, O_RDONLY | O_BINARY)) < 0) | |
141 return -1; | |
142 | |
143 return is_zstd(fd) ? decompress(fd, zf) : reopen(fd, zf); | |
144 } | |
145 | |
146 void | |
147 zfile_close(struct zfile *zf) | |
148 { | |
149 assert(zf); | |
150 | |
151 free(zf->data); | |
152 | |
153 if (zf->fp) | |
154 fclose(zf->fp); | |
155 | |
156 memset(zf, 0, sizeof (*zf)); | |
157 } |