1*ec63e07aSXin Li // Copyright 2022 Google LLC
2*ec63e07aSXin Li //
3*ec63e07aSXin Li // Licensed under the Apache License, Version 2.0 (the "License");
4*ec63e07aSXin Li // you may not use this file except in compliance with the License.
5*ec63e07aSXin Li // You may obtain a copy of the License at
6*ec63e07aSXin Li //
7*ec63e07aSXin Li // https://www.apache.org/licenses/LICENSE-2.0
8*ec63e07aSXin Li //
9*ec63e07aSXin Li // Unless required by applicable law or agreed to in writing, software
10*ec63e07aSXin Li // distributed under the License is distributed on an "AS IS" BASIS,
11*ec63e07aSXin Li // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*ec63e07aSXin Li // See the License for the specific language governing permissions and
13*ec63e07aSXin Li // limitations under the License.
14*ec63e07aSXin Li
15*ec63e07aSXin Li #include "contrib/zstd/wrapper/wrapper_zstd.h"
16*ec63e07aSXin Li
17*ec63e07aSXin Li #include <errno.h>
18*ec63e07aSXin Li #include <fcntl.h>
19*ec63e07aSXin Li #include <unistd.h>
20*ec63e07aSXin Li
21*ec63e07aSXin Li #include <cstdio>
22*ec63e07aSXin Li #include <cstdlib>
23*ec63e07aSXin Li #include <iostream>
24*ec63e07aSXin Li #include <memory>
25*ec63e07aSXin Li
26*ec63e07aSXin Li constexpr size_t kFileMaxSize = 1024 * 1024 * 1024; // 1GB
27*ec63e07aSXin Li
FDGetSize(int fd)28*ec63e07aSXin Li off_t FDGetSize(int fd) {
29*ec63e07aSXin Li off_t size = lseek(fd, 0, SEEK_END);
30*ec63e07aSXin Li if (size < 0) {
31*ec63e07aSXin Li return -1;
32*ec63e07aSXin Li }
33*ec63e07aSXin Li if (lseek(fd, 0, SEEK_SET) < 0) {
34*ec63e07aSXin Li return -1;
35*ec63e07aSXin Li }
36*ec63e07aSXin Li
37*ec63e07aSXin Li return size;
38*ec63e07aSXin Li }
39*ec63e07aSXin Li
ZSTD_compress_fd(int fdin,int fdout,int level)40*ec63e07aSXin Li int ZSTD_compress_fd(int fdin, int fdout, int level) {
41*ec63e07aSXin Li off_t sizein = FDGetSize(fdin);
42*ec63e07aSXin Li if (sizein <= 0) {
43*ec63e07aSXin Li return -1;
44*ec63e07aSXin Li }
45*ec63e07aSXin Li
46*ec63e07aSXin Li size_t sizeout = ZSTD_compressBound(sizein);
47*ec63e07aSXin Li
48*ec63e07aSXin Li auto bufin = std::make_unique<int8_t[]>(sizein);
49*ec63e07aSXin Li auto bufout = std::make_unique<int8_t[]>(sizeout);
50*ec63e07aSXin Li
51*ec63e07aSXin Li if (read(fdin, bufin.get(), sizein) != sizein) {
52*ec63e07aSXin Li return -1;
53*ec63e07aSXin Li }
54*ec63e07aSXin Li
55*ec63e07aSXin Li int retsize =
56*ec63e07aSXin Li ZSTD_compress(bufout.get(), sizeout, bufin.get(), sizein, level);
57*ec63e07aSXin Li if (ZSTD_isError(retsize)) {
58*ec63e07aSXin Li return -1;
59*ec63e07aSXin Li }
60*ec63e07aSXin Li
61*ec63e07aSXin Li if (write(fdout, bufout.get(), retsize) != retsize) {
62*ec63e07aSXin Li return -1;
63*ec63e07aSXin Li }
64*ec63e07aSXin Li
65*ec63e07aSXin Li return 0;
66*ec63e07aSXin Li }
67*ec63e07aSXin Li
ZSTD_compressStream_fd(ZSTD_CCtx * cctx,int fdin,int fdout)68*ec63e07aSXin Li int ZSTD_compressStream_fd(ZSTD_CCtx* cctx, int fdin, int fdout) {
69*ec63e07aSXin Li size_t sizein = ZSTD_CStreamInSize();
70*ec63e07aSXin Li size_t sizeout = ZSTD_CStreamOutSize();
71*ec63e07aSXin Li
72*ec63e07aSXin Li auto bufin = std::make_unique<int8_t[]>(sizein);
73*ec63e07aSXin Li auto bufout = std::make_unique<int8_t[]>(sizeout);
74*ec63e07aSXin Li
75*ec63e07aSXin Li ssize_t size;
76*ec63e07aSXin Li while ((size = read(fdin, bufin.get(), sizein)) > 0) {
77*ec63e07aSXin Li ZSTD_inBuffer_s struct_in;
78*ec63e07aSXin Li struct_in.src = bufin.get();
79*ec63e07aSXin Li struct_in.pos = 0;
80*ec63e07aSXin Li struct_in.size = size;
81*ec63e07aSXin Li
82*ec63e07aSXin Li ZSTD_EndDirective mode = ZSTD_e_continue;
83*ec63e07aSXin Li if (size < sizein) {
84*ec63e07aSXin Li mode = ZSTD_e_end;
85*ec63e07aSXin Li }
86*ec63e07aSXin Li
87*ec63e07aSXin Li bool isdone = false;
88*ec63e07aSXin Li while (!isdone) {
89*ec63e07aSXin Li ZSTD_outBuffer_s struct_out;
90*ec63e07aSXin Li struct_out.dst = bufout.get();
91*ec63e07aSXin Li struct_out.pos = 0;
92*ec63e07aSXin Li struct_out.size = sizeout;
93*ec63e07aSXin Li
94*ec63e07aSXin Li size_t remaining =
95*ec63e07aSXin Li ZSTD_compressStream2(cctx, &struct_out, &struct_in, mode);
96*ec63e07aSXin Li if (ZSTD_isError(remaining)) {
97*ec63e07aSXin Li return -1;
98*ec63e07aSXin Li }
99*ec63e07aSXin Li if (write(fdout, bufout.get(), struct_out.pos) != struct_out.pos) {
100*ec63e07aSXin Li return -1;
101*ec63e07aSXin Li }
102*ec63e07aSXin Li
103*ec63e07aSXin Li if (mode == ZSTD_e_continue) {
104*ec63e07aSXin Li isdone = (struct_in.pos == size);
105*ec63e07aSXin Li } else {
106*ec63e07aSXin Li isdone = (remaining == 0);
107*ec63e07aSXin Li }
108*ec63e07aSXin Li }
109*ec63e07aSXin Li }
110*ec63e07aSXin Li
111*ec63e07aSXin Li if (size != 0) {
112*ec63e07aSXin Li return -1;
113*ec63e07aSXin Li }
114*ec63e07aSXin Li
115*ec63e07aSXin Li return 0;
116*ec63e07aSXin Li }
117*ec63e07aSXin Li
ZSTD_decompress_fd(int fdin,int fdout)118*ec63e07aSXin Li int ZSTD_decompress_fd(int fdin, int fdout) {
119*ec63e07aSXin Li off_t sizein = FDGetSize(fdin);
120*ec63e07aSXin Li if (sizein <= 0) {
121*ec63e07aSXin Li return -1;
122*ec63e07aSXin Li }
123*ec63e07aSXin Li auto bufin = std::make_unique<int8_t[]>(sizein);
124*ec63e07aSXin Li if (read(fdin, bufin.get(), sizein) != sizein) {
125*ec63e07aSXin Li return -1;
126*ec63e07aSXin Li }
127*ec63e07aSXin Li
128*ec63e07aSXin Li size_t sizeout = ZSTD_getFrameContentSize(bufin.get(), sizein);
129*ec63e07aSXin Li if (ZSTD_isError(sizeout) || sizeout > kFileMaxSize) {
130*ec63e07aSXin Li return -1;
131*ec63e07aSXin Li }
132*ec63e07aSXin Li
133*ec63e07aSXin Li auto bufout = std::make_unique<int8_t[]>(sizeout);
134*ec63e07aSXin Li
135*ec63e07aSXin Li size_t desize = ZSTD_decompress(bufout.get(), sizeout, bufin.get(), sizein);
136*ec63e07aSXin Li if (ZSTD_isError(desize) || desize != sizeout) {
137*ec63e07aSXin Li return -1;
138*ec63e07aSXin Li }
139*ec63e07aSXin Li
140*ec63e07aSXin Li if (write(fdout, bufout.get(), sizeout) != sizeout) {
141*ec63e07aSXin Li return -1;
142*ec63e07aSXin Li }
143*ec63e07aSXin Li
144*ec63e07aSXin Li return 0;
145*ec63e07aSXin Li }
146*ec63e07aSXin Li
ZSTD_decompressStream_fd(ZSTD_DCtx * dctx,int fdin,int fdout)147*ec63e07aSXin Li int ZSTD_decompressStream_fd(ZSTD_DCtx* dctx, int fdin, int fdout) {
148*ec63e07aSXin Li size_t sizein = ZSTD_CStreamInSize();
149*ec63e07aSXin Li size_t sizeout = ZSTD_CStreamOutSize();
150*ec63e07aSXin Li
151*ec63e07aSXin Li auto bufin = std::make_unique<int8_t[]>(sizein);
152*ec63e07aSXin Li auto bufout = std::make_unique<int8_t[]>(sizeout);
153*ec63e07aSXin Li
154*ec63e07aSXin Li ssize_t size;
155*ec63e07aSXin Li while ((size = read(fdin, bufin.get(), sizein)) > 0) {
156*ec63e07aSXin Li ZSTD_inBuffer_s struct_in;
157*ec63e07aSXin Li struct_in.src = bufin.get();
158*ec63e07aSXin Li struct_in.pos = 0;
159*ec63e07aSXin Li struct_in.size = size;
160*ec63e07aSXin Li
161*ec63e07aSXin Li while (struct_in.pos < size) {
162*ec63e07aSXin Li ZSTD_outBuffer_s struct_out;
163*ec63e07aSXin Li struct_out.dst = bufout.get();
164*ec63e07aSXin Li struct_out.pos = 0;
165*ec63e07aSXin Li struct_out.size = sizeout;
166*ec63e07aSXin Li
167*ec63e07aSXin Li size_t ret = ZSTD_decompressStream(dctx, &struct_out, &struct_in);
168*ec63e07aSXin Li if (ZSTD_isError(ret)) {
169*ec63e07aSXin Li return -1;
170*ec63e07aSXin Li }
171*ec63e07aSXin Li if (write(fdout, bufout.get(), struct_out.pos) != struct_out.pos) {
172*ec63e07aSXin Li return -1;
173*ec63e07aSXin Li }
174*ec63e07aSXin Li }
175*ec63e07aSXin Li }
176*ec63e07aSXin Li
177*ec63e07aSXin Li if (size != 0) {
178*ec63e07aSXin Li return -1;
179*ec63e07aSXin Li }
180*ec63e07aSXin Li
181*ec63e07aSXin Li return 0;
182*ec63e07aSXin Li }
183