xref: /aosp_15_r20/external/sandboxed-api/contrib/zstd/utils/utils_zstd.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
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 <fstream>
16*ec63e07aSXin Li #include <iostream>
17*ec63e07aSXin Li #include <string>
18*ec63e07aSXin Li 
19*ec63e07aSXin Li #include "contrib/zstd/sandboxed.h"
20*ec63e07aSXin Li 
21*ec63e07aSXin Li constexpr size_t kFileMaxSize = 1024 * 1024 * 1024;  // 1GB
22*ec63e07aSXin Li 
GetStreamSize(std::ifstream & stream)23*ec63e07aSXin Li std::streamsize GetStreamSize(std::ifstream& stream) {
24*ec63e07aSXin Li   stream.seekg(0, std::ios_base::end);
25*ec63e07aSXin Li   std::streamsize ssize = stream.tellg();
26*ec63e07aSXin Li   stream.seekg(0, std::ios_base::beg);
27*ec63e07aSXin Li 
28*ec63e07aSXin Li   return ssize;
29*ec63e07aSXin Li }
30*ec63e07aSXin Li 
CompressInMemory(ZstdApi & api,std::ifstream & in_stream,std::ofstream & out_stream,int level)31*ec63e07aSXin Li absl::Status CompressInMemory(ZstdApi& api, std::ifstream& in_stream,
32*ec63e07aSXin Li                               std::ofstream& out_stream, int level) {
33*ec63e07aSXin Li   std::streamsize ssize = GetStreamSize(in_stream);
34*ec63e07aSXin Li   sapi::v::Array<uint8_t> inbuf(ssize);
35*ec63e07aSXin Li   in_stream.read(reinterpret_cast<char*>(inbuf.GetData()), ssize);
36*ec63e07aSXin Li   if (in_stream.gcount() != ssize) {
37*ec63e07aSXin Li     return absl::UnavailableError("Unable to read file");
38*ec63e07aSXin Li   }
39*ec63e07aSXin Li 
40*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(size_t size, api.ZSTD_compressBound(inbuf.GetSize()));
41*ec63e07aSXin Li   sapi::v::Array<uint8_t> outbuf(size);
42*ec63e07aSXin Li 
43*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(
44*ec63e07aSXin Li       size_t outsize,
45*ec63e07aSXin Li       api.ZSTD_compress(outbuf.PtrAfter(), size, inbuf.PtrBefore(),
46*ec63e07aSXin Li                         inbuf.GetSize(), level));
47*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(int iserr, api.ZSTD_isError(outsize));
48*ec63e07aSXin Li   if (iserr) {
49*ec63e07aSXin Li     return absl::UnavailableError("Unable to compress file");
50*ec63e07aSXin Li   }
51*ec63e07aSXin Li 
52*ec63e07aSXin Li   out_stream.write(reinterpret_cast<char*>(outbuf.GetData()), outsize);
53*ec63e07aSXin Li   if (!out_stream.good()) {
54*ec63e07aSXin Li     return absl::UnavailableError("Unable to write file");
55*ec63e07aSXin Li   }
56*ec63e07aSXin Li 
57*ec63e07aSXin Li   return absl::OkStatus();
58*ec63e07aSXin Li }
59*ec63e07aSXin Li 
DecompressInMemory(ZstdApi & api,std::ifstream & in_stream,std::ofstream & out_stream)60*ec63e07aSXin Li absl::Status DecompressInMemory(ZstdApi& api, std::ifstream& in_stream,
61*ec63e07aSXin Li                                 std::ofstream& out_stream) {
62*ec63e07aSXin Li   int iserr;
63*ec63e07aSXin Li   std::streamsize ssize = GetStreamSize(in_stream);
64*ec63e07aSXin Li   sapi::v::Array<uint8_t> inbuf(ssize);
65*ec63e07aSXin Li   in_stream.read(reinterpret_cast<char*>(inbuf.GetData()), ssize);
66*ec63e07aSXin Li   if (in_stream.gcount() != ssize) {
67*ec63e07aSXin Li     return absl::UnavailableError("Unable to read file");
68*ec63e07aSXin Li   }
69*ec63e07aSXin Li 
70*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(size_t size, api.ZSTD_getFrameContentSize(
71*ec63e07aSXin Li                                          inbuf.PtrBefore(), inbuf.GetSize()));
72*ec63e07aSXin Li   if (size > kFileMaxSize) {
73*ec63e07aSXin Li     return absl::UnavailableError("File to large");
74*ec63e07aSXin Li   }
75*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(iserr, api.ZSTD_isError(size));
76*ec63e07aSXin Li   if (iserr) {
77*ec63e07aSXin Li     return absl::UnavailableError("Unable to decompress file");
78*ec63e07aSXin Li   }
79*ec63e07aSXin Li   sapi::v::Array<uint8_t> outbuf(size);
80*ec63e07aSXin Li 
81*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(size_t desize,
82*ec63e07aSXin Li                         api.ZSTD_decompress(outbuf.PtrAfter(), size,
83*ec63e07aSXin Li                                             inbuf.PtrNone(), inbuf.GetSize()));
84*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(iserr, api.ZSTD_isError(desize));
85*ec63e07aSXin Li   if (iserr) {
86*ec63e07aSXin Li     return absl::UnavailableError("Unable to decompress file");
87*ec63e07aSXin Li   }
88*ec63e07aSXin Li 
89*ec63e07aSXin Li   out_stream.write(reinterpret_cast<char*>(outbuf.GetData()), desize);
90*ec63e07aSXin Li   if (!out_stream.good()) {
91*ec63e07aSXin Li     return absl::UnavailableError("Unable to write file");
92*ec63e07aSXin Li   }
93*ec63e07aSXin Li 
94*ec63e07aSXin Li   return absl::OkStatus();
95*ec63e07aSXin Li }
96*ec63e07aSXin Li 
CompressStream(ZstdApi & api,std::ifstream & in_stream,std::ofstream & out_stream,int level)97*ec63e07aSXin Li absl::Status CompressStream(ZstdApi& api, std::ifstream& in_stream,
98*ec63e07aSXin Li                             std::ofstream& out_stream, int level) {
99*ec63e07aSXin Li   int iserr;
100*ec63e07aSXin Li 
101*ec63e07aSXin Li   // Create necessary buffers.
102*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(size_t inbuf_size, api.ZSTD_CStreamInSize());
103*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(size_t outbuf_size, api.ZSTD_CStreamOutSize());
104*ec63e07aSXin Li   sapi::v::Array<uint8_t> inbuf(inbuf_size);
105*ec63e07aSXin Li   sapi::v::Array<uint8_t> outbuf(outbuf_size);
106*ec63e07aSXin Li 
107*ec63e07aSXin Li   if (!api.GetSandbox()->Allocate(&inbuf).ok() ||
108*ec63e07aSXin Li       !api.GetSandbox()->Allocate(&outbuf).ok()) {
109*ec63e07aSXin Li     return absl::UnavailableError("Unable to allocate buffors");
110*ec63e07aSXin Li   }
111*ec63e07aSXin Li 
112*ec63e07aSXin Li   // Create Zstd context.
113*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(ZSTD_CCtx * cctx, api.ZSTD_createCCtx());
114*ec63e07aSXin Li   sapi::v::RemotePtr rcctx(cctx);
115*ec63e07aSXin Li 
116*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(iserr, api.ZSTD_CCtx_setParameter(
117*ec63e07aSXin Li                                    &rcctx, ZSTD_c_compressionLevel, level));
118*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(iserr, api.ZSTD_isError(iserr));
119*ec63e07aSXin Li   if (iserr) {
120*ec63e07aSXin Li     return absl::UnavailableError("Unable to set parameter");
121*ec63e07aSXin Li   }
122*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(
123*ec63e07aSXin Li       iserr, api.ZSTD_CCtx_setParameter(&rcctx, ZSTD_c_checksumFlag, 1));
124*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(iserr, api.ZSTD_isError(iserr));
125*ec63e07aSXin Li   if (iserr) {
126*ec63e07aSXin Li     return absl::UnavailableError("Unable to set parameter");
127*ec63e07aSXin Li   }
128*ec63e07aSXin Li 
129*ec63e07aSXin Li   // Compress.
130*ec63e07aSXin Li   while (in_stream) {
131*ec63e07aSXin Li     in_stream.read(reinterpret_cast<char*>(inbuf.GetData()), inbuf_size);
132*ec63e07aSXin Li 
133*ec63e07aSXin Li     if (!api.GetSandbox()->TransferToSandboxee(&inbuf).ok()) {
134*ec63e07aSXin Li       return absl::UnavailableError("Unable to transfer data");
135*ec63e07aSXin Li     }
136*ec63e07aSXin Li 
137*ec63e07aSXin Li     sapi::v::Struct<ZSTD_inBuffer_s> struct_in;
138*ec63e07aSXin Li     struct_in.mutable_data()->src = static_cast<uint8_t*>(inbuf.GetRemote());
139*ec63e07aSXin Li     struct_in.mutable_data()->pos = 0;
140*ec63e07aSXin Li     struct_in.mutable_data()->size = in_stream.gcount();
141*ec63e07aSXin Li 
142*ec63e07aSXin Li     ZSTD_EndDirective mode = ZSTD_e_continue;
143*ec63e07aSXin Li     if (in_stream.gcount() < inbuf_size) {
144*ec63e07aSXin Li       mode = ZSTD_e_end;
145*ec63e07aSXin Li     }
146*ec63e07aSXin Li 
147*ec63e07aSXin Li     bool isdone = false;
148*ec63e07aSXin Li     while (!isdone) {
149*ec63e07aSXin Li       sapi::v::Struct<ZSTD_outBuffer_s> struct_out;
150*ec63e07aSXin Li       struct_out.mutable_data()->dst =
151*ec63e07aSXin Li           static_cast<uint8_t*>(outbuf.GetRemote());
152*ec63e07aSXin Li       struct_out.mutable_data()->pos = 0;
153*ec63e07aSXin Li       struct_out.mutable_data()->size = outbuf.GetSize();
154*ec63e07aSXin Li 
155*ec63e07aSXin Li       SAPI_ASSIGN_OR_RETURN(size_t remaining, api.ZSTD_compressStream2(
156*ec63e07aSXin Li                                                   &rcctx, struct_out.PtrBoth(),
157*ec63e07aSXin Li                                                   struct_in.PtrBoth(), mode));
158*ec63e07aSXin Li       SAPI_ASSIGN_OR_RETURN(int iserr, api.ZSTD_isError(remaining));
159*ec63e07aSXin Li       if (iserr) {
160*ec63e07aSXin Li         return absl::UnavailableError("Unable to decompress file");
161*ec63e07aSXin Li       }
162*ec63e07aSXin Li 
163*ec63e07aSXin Li       if (!api.GetSandbox()->TransferFromSandboxee(&outbuf).ok()) {
164*ec63e07aSXin Li         return absl::UnavailableError("Unable to transfer data from");
165*ec63e07aSXin Li       }
166*ec63e07aSXin Li       out_stream.write(reinterpret_cast<char*>(outbuf.GetData()),
167*ec63e07aSXin Li                        struct_out.mutable_data()->pos);
168*ec63e07aSXin Li       if (!out_stream.good()) {
169*ec63e07aSXin Li         return absl::UnavailableError("Unable to write file");
170*ec63e07aSXin Li       }
171*ec63e07aSXin Li 
172*ec63e07aSXin Li       if (mode == ZSTD_e_continue) {
173*ec63e07aSXin Li         isdone = (struct_in.mutable_data()->pos == in_stream.gcount());
174*ec63e07aSXin Li       } else {
175*ec63e07aSXin Li         isdone = (remaining == 0);
176*ec63e07aSXin Li       }
177*ec63e07aSXin Li     }
178*ec63e07aSXin Li   }
179*ec63e07aSXin Li 
180*ec63e07aSXin Li   api.ZSTD_freeDCtx(&rcctx).IgnoreError();
181*ec63e07aSXin Li 
182*ec63e07aSXin Li   return absl::OkStatus();
183*ec63e07aSXin Li }
184*ec63e07aSXin Li 
DecompressStream(ZstdApi & api,std::ifstream & in_stream,std::ofstream & out_stream)185*ec63e07aSXin Li absl::Status DecompressStream(ZstdApi& api, std::ifstream& in_stream,
186*ec63e07aSXin Li                               std::ofstream& out_stream) {
187*ec63e07aSXin Li   // Create necessary buffers.
188*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(size_t inbuf_size, api.ZSTD_CStreamInSize());
189*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(size_t outbuf_size, api.ZSTD_CStreamOutSize());
190*ec63e07aSXin Li   sapi::v::Array<uint8_t> inbuf(inbuf_size);
191*ec63e07aSXin Li   sapi::v::Array<uint8_t> outbuf(outbuf_size);
192*ec63e07aSXin Li 
193*ec63e07aSXin Li   if (!api.GetSandbox()->Allocate(&inbuf).ok() ||
194*ec63e07aSXin Li       !api.GetSandbox()->Allocate(&outbuf).ok()) {
195*ec63e07aSXin Li     return absl::UnavailableError("Unable to allocate buffors");
196*ec63e07aSXin Li   }
197*ec63e07aSXin Li 
198*ec63e07aSXin Li   // Create Zstd context.
199*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(ZSTD_DCtx * dctx, api.ZSTD_createDCtx());
200*ec63e07aSXin Li   sapi::v::RemotePtr rdctx(dctx);
201*ec63e07aSXin Li 
202*ec63e07aSXin Li   // Decompress.
203*ec63e07aSXin Li   while (in_stream) {
204*ec63e07aSXin Li     in_stream.read(reinterpret_cast<char*>(inbuf.GetData()), inbuf_size);
205*ec63e07aSXin Li 
206*ec63e07aSXin Li     if (!api.GetSandbox()->TransferToSandboxee(&inbuf).ok()) {
207*ec63e07aSXin Li       return absl::UnavailableError("Unable to transfer data");
208*ec63e07aSXin Li     }
209*ec63e07aSXin Li 
210*ec63e07aSXin Li     sapi::v::Struct<ZSTD_inBuffer_s> struct_in;
211*ec63e07aSXin Li     *struct_in.mutable_data() = {static_cast<uint8_t*>(inbuf.GetRemote()),
212*ec63e07aSXin Li                                  (size_t)in_stream.gcount(), 0};
213*ec63e07aSXin Li 
214*ec63e07aSXin Li     bool isdone = false;
215*ec63e07aSXin Li     while (struct_in.mutable_data()->pos < in_stream.gcount()) {
216*ec63e07aSXin Li       sapi::v::Struct<ZSTD_outBuffer_s> struct_out;
217*ec63e07aSXin Li       *struct_out.mutable_data() = {static_cast<uint8_t*>(outbuf.GetRemote()),
218*ec63e07aSXin Li                                     (size_t)outbuf.GetSize(), 0};
219*ec63e07aSXin Li 
220*ec63e07aSXin Li       SAPI_ASSIGN_OR_RETURN(
221*ec63e07aSXin Li           size_t ret, api.ZSTD_decompressStream(&rdctx, struct_out.PtrBoth(),
222*ec63e07aSXin Li                                                 struct_in.PtrBoth()));
223*ec63e07aSXin Li       SAPI_ASSIGN_OR_RETURN(int iserr, api.ZSTD_isError(ret));
224*ec63e07aSXin Li       if (iserr) {
225*ec63e07aSXin Li         return absl::UnavailableError("Unable to decompress file");
226*ec63e07aSXin Li       }
227*ec63e07aSXin Li 
228*ec63e07aSXin Li       if (!api.GetSandbox()->TransferFromSandboxee(&outbuf).ok()) {
229*ec63e07aSXin Li         return absl::UnavailableError("Unable to transfer data from");
230*ec63e07aSXin Li       }
231*ec63e07aSXin Li 
232*ec63e07aSXin Li       out_stream.write(reinterpret_cast<char*>(outbuf.GetData()),
233*ec63e07aSXin Li                        struct_out.mutable_data()->pos);
234*ec63e07aSXin Li       if (!out_stream.good()) {
235*ec63e07aSXin Li         return absl::UnavailableError("Unable to write file");
236*ec63e07aSXin Li       }
237*ec63e07aSXin Li     }
238*ec63e07aSXin Li   }
239*ec63e07aSXin Li 
240*ec63e07aSXin Li   api.ZSTD_freeDCtx(&rdctx).IgnoreError();
241*ec63e07aSXin Li 
242*ec63e07aSXin Li   return absl::OkStatus();
243*ec63e07aSXin Li }
244*ec63e07aSXin Li 
CompressInMemoryFD(ZstdApi & api,sapi::v::Fd & infd,sapi::v::Fd & outfd,int level)245*ec63e07aSXin Li absl::Status CompressInMemoryFD(ZstdApi& api, sapi::v::Fd& infd,
246*ec63e07aSXin Li                                 sapi::v::Fd& outfd, int level) {
247*ec63e07aSXin Li   SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&infd));
248*ec63e07aSXin Li   SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&outfd));
249*ec63e07aSXin Li 
250*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(
251*ec63e07aSXin Li       int iserr,
252*ec63e07aSXin Li       api.ZSTD_compress_fd(infd.GetRemoteFd(), outfd.GetRemoteFd(), 0));
253*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(iserr, api.ZSTD_isError(iserr));
254*ec63e07aSXin Li   if (iserr) {
255*ec63e07aSXin Li     return absl::UnavailableError("Unable to compress file");
256*ec63e07aSXin Li   }
257*ec63e07aSXin Li 
258*ec63e07aSXin Li   infd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
259*ec63e07aSXin Li   outfd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
260*ec63e07aSXin Li 
261*ec63e07aSXin Li   return absl::OkStatus();
262*ec63e07aSXin Li }
263*ec63e07aSXin Li 
DecompressInMemoryFD(ZstdApi & api,sapi::v::Fd & infd,sapi::v::Fd & outfd)264*ec63e07aSXin Li absl::Status DecompressInMemoryFD(ZstdApi& api, sapi::v::Fd& infd,
265*ec63e07aSXin Li                                   sapi::v::Fd& outfd) {
266*ec63e07aSXin Li   SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&infd));
267*ec63e07aSXin Li   SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&outfd));
268*ec63e07aSXin Li 
269*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(int iserr, api.ZSTD_decompress_fd(infd.GetRemoteFd(),
270*ec63e07aSXin Li                                                           outfd.GetRemoteFd()));
271*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(iserr, api.ZSTD_isError(iserr));
272*ec63e07aSXin Li   if (iserr) {
273*ec63e07aSXin Li     return absl::UnavailableError("Unable to compress file");
274*ec63e07aSXin Li   }
275*ec63e07aSXin Li 
276*ec63e07aSXin Li   infd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
277*ec63e07aSXin Li   outfd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
278*ec63e07aSXin Li 
279*ec63e07aSXin Li   return absl::OkStatus();
280*ec63e07aSXin Li }
281*ec63e07aSXin Li 
CompressStreamFD(ZstdApi & api,sapi::v::Fd & infd,sapi::v::Fd & outfd,int level)282*ec63e07aSXin Li absl::Status CompressStreamFD(ZstdApi& api, sapi::v::Fd& infd,
283*ec63e07aSXin Li                               sapi::v::Fd& outfd, int level) {
284*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(ZSTD_CCtx * cctx, api.ZSTD_createCCtx());
285*ec63e07aSXin Li   sapi::v::RemotePtr rcctx(cctx);
286*ec63e07aSXin Li 
287*ec63e07aSXin Li   int iserr;
288*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(iserr, api.ZSTD_CCtx_setParameter(
289*ec63e07aSXin Li                                    &rcctx, ZSTD_c_compressionLevel, level));
290*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(iserr, api.ZSTD_isError(iserr));
291*ec63e07aSXin Li   if (iserr) {
292*ec63e07aSXin Li     return absl::UnavailableError("Unable to set parameter l");
293*ec63e07aSXin Li   }
294*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(
295*ec63e07aSXin Li       iserr, api.ZSTD_CCtx_setParameter(&rcctx, ZSTD_c_checksumFlag, 1));
296*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(iserr, api.ZSTD_isError(iserr));
297*ec63e07aSXin Li   if (iserr) {
298*ec63e07aSXin Li     return absl::UnavailableError("Unable to set parameter c");
299*ec63e07aSXin Li   }
300*ec63e07aSXin Li 
301*ec63e07aSXin Li   SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&infd));
302*ec63e07aSXin Li   SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&outfd));
303*ec63e07aSXin Li 
304*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(iserr,
305*ec63e07aSXin Li                         api.ZSTD_compressStream_fd(&rcctx, infd.GetRemoteFd(),
306*ec63e07aSXin Li                                                    outfd.GetRemoteFd()));
307*ec63e07aSXin Li   if (iserr) {
308*ec63e07aSXin Li     return absl::UnavailableError("Unable to compress");
309*ec63e07aSXin Li   }
310*ec63e07aSXin Li 
311*ec63e07aSXin Li   infd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
312*ec63e07aSXin Li   outfd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
313*ec63e07aSXin Li 
314*ec63e07aSXin Li   return absl::OkStatus();
315*ec63e07aSXin Li }
316*ec63e07aSXin Li 
DecompressStreamFD(ZstdApi & api,sapi::v::Fd & infd,sapi::v::Fd & outfd)317*ec63e07aSXin Li absl::Status DecompressStreamFD(ZstdApi& api, sapi::v::Fd& infd,
318*ec63e07aSXin Li                                 sapi::v::Fd& outfd) {
319*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(ZSTD_DCtx * dctx, api.ZSTD_createDCtx());
320*ec63e07aSXin Li   sapi::v::RemotePtr rdctx(dctx);
321*ec63e07aSXin Li 
322*ec63e07aSXin Li   SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&infd));
323*ec63e07aSXin Li   SAPI_RETURN_IF_ERROR(api.GetSandbox()->TransferToSandboxee(&outfd));
324*ec63e07aSXin Li 
325*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(int iserr,
326*ec63e07aSXin Li                         api.ZSTD_decompressStream_fd(&rdctx, infd.GetRemoteFd(),
327*ec63e07aSXin Li                                                      outfd.GetRemoteFd()));
328*ec63e07aSXin Li   if (iserr) {
329*ec63e07aSXin Li     return absl::UnavailableError("Unable to decompress");
330*ec63e07aSXin Li   }
331*ec63e07aSXin Li   infd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
332*ec63e07aSXin Li   outfd.CloseRemoteFd(api.GetSandbox()->rpc_channel()).IgnoreError();
333*ec63e07aSXin Li 
334*ec63e07aSXin Li   return absl::OkStatus();
335*ec63e07aSXin Li }
336