xref: /aosp_15_r20/external/sandboxed-api/oss-internship-2020/guetzli/guetzli_transaction.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
1*ec63e07aSXin Li // Copyright 2020 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 "guetzli_transaction.h"  // NOLINT(build/include)
16*ec63e07aSXin Li 
17*ec63e07aSXin Li #include <fcntl.h>
18*ec63e07aSXin Li #include <sys/stat.h>
19*ec63e07aSXin Li #include <sys/types.h>
20*ec63e07aSXin Li #include <unistd.h>
21*ec63e07aSXin Li 
22*ec63e07aSXin Li #include <iostream>
23*ec63e07aSXin Li #include <memory>
24*ec63e07aSXin Li 
25*ec63e07aSXin Li #include "absl/status/statusor.h"
26*ec63e07aSXin Li 
27*ec63e07aSXin Li namespace guetzli::sandbox {
28*ec63e07aSXin Li 
Main()29*ec63e07aSXin Li absl::Status GuetzliTransaction::Main() {
30*ec63e07aSXin Li   sapi::v::Fd in_fd(open(params_.in_file, O_RDONLY));
31*ec63e07aSXin Li 
32*ec63e07aSXin Li   if (in_fd.GetValue() < 0) {
33*ec63e07aSXin Li     return absl::FailedPreconditionError("Error opening input file");
34*ec63e07aSXin Li   }
35*ec63e07aSXin Li 
36*ec63e07aSXin Li   SAPI_ASSIGN_OR_RETURN(image_type_, GetImageTypeFromFd(in_fd.GetValue()));
37*ec63e07aSXin Li   SAPI_RETURN_IF_ERROR(sandbox()->TransferToSandboxee(&in_fd));
38*ec63e07aSXin Li 
39*ec63e07aSXin Li   if (in_fd.GetRemoteFd() < 0) {
40*ec63e07aSXin Li     return absl::FailedPreconditionError(
41*ec63e07aSXin Li         "Error receiving remote FD: remote input fd is set to -1");
42*ec63e07aSXin Li   }
43*ec63e07aSXin Li 
44*ec63e07aSXin Li   GuetzliApi api(sandbox());
45*ec63e07aSXin Li   sapi::v::LenVal output(0);
46*ec63e07aSXin Li 
47*ec63e07aSXin Li   sapi::v::Struct<ProcessingParams> processing_params;
48*ec63e07aSXin Li   *processing_params.mutable_data() = {in_fd.GetRemoteFd(), params_.verbose,
49*ec63e07aSXin Li                                        params_.quality, params_.memlimit_mb};
50*ec63e07aSXin Li 
51*ec63e07aSXin Li   auto result =
52*ec63e07aSXin Li       image_type_ == ImageType::kJpeg
53*ec63e07aSXin Li           ? api.ProcessJpeg(processing_params.PtrBefore(), output.PtrBefore())
54*ec63e07aSXin Li           : api.ProcessRgb(processing_params.PtrBefore(), output.PtrBefore());
55*ec63e07aSXin Li 
56*ec63e07aSXin Li   if (!result.value_or(false)) {
57*ec63e07aSXin Li     return absl::FailedPreconditionError(absl::StrCat(
58*ec63e07aSXin Li         "Error processing ", (image_type_ == ImageType::kJpeg ? "jpeg" : "rgb"),
59*ec63e07aSXin Li         " data"));
60*ec63e07aSXin Li   }
61*ec63e07aSXin Li 
62*ec63e07aSXin Li   sapi::v::Fd out_fd(open(".", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR));
63*ec63e07aSXin Li   if (out_fd.GetValue() < 0) {
64*ec63e07aSXin Li     return absl::FailedPreconditionError("Error creating temp output file");
65*ec63e07aSXin Li   }
66*ec63e07aSXin Li 
67*ec63e07aSXin Li   SAPI_RETURN_IF_ERROR(sandbox()->TransferToSandboxee(&out_fd));
68*ec63e07aSXin Li 
69*ec63e07aSXin Li   if (out_fd.GetRemoteFd() < 0) {
70*ec63e07aSXin Li     return absl::FailedPreconditionError(
71*ec63e07aSXin Li         "Error receiving remote FD: remote output fd is set to -1");
72*ec63e07aSXin Li   }
73*ec63e07aSXin Li 
74*ec63e07aSXin Li   auto write_result = api.WriteDataToFd(out_fd.GetRemoteFd(), output.PtrNone());
75*ec63e07aSXin Li 
76*ec63e07aSXin Li   if (!write_result.value_or(false)) {
77*ec63e07aSXin Li     return absl::FailedPreconditionError("Error writing file inside sandbox");
78*ec63e07aSXin Li   }
79*ec63e07aSXin Li 
80*ec63e07aSXin Li   SAPI_RETURN_IF_ERROR(LinkOutFile(out_fd.GetValue()));
81*ec63e07aSXin Li 
82*ec63e07aSXin Li   return absl::OkStatus();
83*ec63e07aSXin Li }
84*ec63e07aSXin Li 
LinkOutFile(int out_fd) const85*ec63e07aSXin Li absl::Status GuetzliTransaction::LinkOutFile(int out_fd) const {
86*ec63e07aSXin Li   if (access(params_.out_file, F_OK) != -1) {
87*ec63e07aSXin Li     if (remove(params_.out_file) < 0) {
88*ec63e07aSXin Li       return absl::FailedPreconditionError(absl::StrCat(
89*ec63e07aSXin Li           "Error deleting existing output file: ", params_.out_file));
90*ec63e07aSXin Li     }
91*ec63e07aSXin Li   }
92*ec63e07aSXin Li 
93*ec63e07aSXin Li   std::string path = absl::StrCat("/proc/self/fd/", out_fd);
94*ec63e07aSXin Li 
95*ec63e07aSXin Li   if (linkat(AT_FDCWD, path.c_str(), AT_FDCWD, params_.out_file,
96*ec63e07aSXin Li              AT_SYMLINK_FOLLOW) < 0) {
97*ec63e07aSXin Li     return absl::FailedPreconditionError(
98*ec63e07aSXin Li         absl::StrCat("Error linking: ", params_.out_file));
99*ec63e07aSXin Li   }
100*ec63e07aSXin Li 
101*ec63e07aSXin Li   return absl::OkStatus();
102*ec63e07aSXin Li }
103*ec63e07aSXin Li 
GetImageTypeFromFd(int fd) const104*ec63e07aSXin Li absl::StatusOr<ImageType> GuetzliTransaction::GetImageTypeFromFd(int fd) const {
105*ec63e07aSXin Li   static const unsigned char kPNGMagicBytes[] = {
106*ec63e07aSXin Li       0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n',
107*ec63e07aSXin Li   };
108*ec63e07aSXin Li   char read_buf[sizeof(kPNGMagicBytes)];
109*ec63e07aSXin Li 
110*ec63e07aSXin Li   if (read(fd, read_buf, sizeof(kPNGMagicBytes)) != sizeof(kPNGMagicBytes)) {
111*ec63e07aSXin Li     return absl::FailedPreconditionError(
112*ec63e07aSXin Li         "Error determining type of the input file");
113*ec63e07aSXin Li   }
114*ec63e07aSXin Li 
115*ec63e07aSXin Li   if (lseek(fd, 0, SEEK_SET) != 0) {
116*ec63e07aSXin Li     return absl::FailedPreconditionError(
117*ec63e07aSXin Li         "Error returnig cursor to the beginning");
118*ec63e07aSXin Li   }
119*ec63e07aSXin Li 
120*ec63e07aSXin Li   return memcmp(read_buf, kPNGMagicBytes, sizeof(kPNGMagicBytes)) == 0
121*ec63e07aSXin Li              ? ImageType::kPng
122*ec63e07aSXin Li              : ImageType::kJpeg;
123*ec63e07aSXin Li }
124*ec63e07aSXin Li 
125*ec63e07aSXin Li }  // namespace guetzli::sandbox
126