2020-08-13 05:09:40 +08:00
|
|
|
// Copyright 2020 Google LLC
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2020-09-17 23:36:07 +08:00
|
|
|
#include "guetzli_transaction.h" // NOLINT(build/include)
|
2020-08-12 06:44:13 +08:00
|
|
|
|
2020-08-18 04:29:07 +08:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2020-08-12 06:44:13 +08:00
|
|
|
#include <iostream>
|
2020-08-12 06:48:48 +08:00
|
|
|
#include <memory>
|
2020-08-12 06:44:13 +08:00
|
|
|
|
2020-10-27 00:08:06 +08:00
|
|
|
#include "absl/status/statusor.h"
|
|
|
|
|
2020-08-31 17:19:00 +08:00
|
|
|
namespace guetzli::sandbox {
|
2020-08-12 06:44:13 +08:00
|
|
|
|
2020-08-18 04:29:07 +08:00
|
|
|
absl::Status GuetzliTransaction::Main() {
|
|
|
|
sapi::v::Fd in_fd(open(params_.in_file, O_RDONLY));
|
2020-08-12 06:44:13 +08:00
|
|
|
|
2020-08-18 04:29:07 +08:00
|
|
|
if (in_fd.GetValue() < 0) {
|
2020-09-17 23:36:07 +08:00
|
|
|
return absl::FailedPreconditionError("Error opening input file");
|
2020-08-12 06:44:13 +08:00
|
|
|
}
|
|
|
|
|
2020-08-18 04:29:07 +08:00
|
|
|
SAPI_ASSIGN_OR_RETURN(image_type_, GetImageTypeFromFd(in_fd.GetValue()));
|
|
|
|
SAPI_RETURN_IF_ERROR(sandbox()->TransferToSandboxee(&in_fd));
|
2020-08-12 06:44:13 +08:00
|
|
|
|
2020-08-18 04:29:07 +08:00
|
|
|
if (in_fd.GetRemoteFd() < 0) {
|
2020-08-12 06:48:48 +08:00
|
|
|
return absl::FailedPreconditionError(
|
|
|
|
"Error receiving remote FD: remote input fd is set to -1");
|
|
|
|
}
|
2020-08-12 06:44:13 +08:00
|
|
|
|
|
|
|
GuetzliApi api(sandbox());
|
|
|
|
sapi::v::LenVal output(0);
|
|
|
|
|
2020-08-12 06:48:48 +08:00
|
|
|
sapi::v::Struct<ProcessingParams> processing_params;
|
2020-09-17 23:36:07 +08:00
|
|
|
*processing_params.mutable_data() = {in_fd.GetRemoteFd(), params_.verbose,
|
|
|
|
params_.quality, params_.memlimit_mb};
|
|
|
|
|
|
|
|
auto result =
|
|
|
|
image_type_ == ImageType::kJpeg
|
|
|
|
? api.ProcessJpeg(processing_params.PtrBefore(), output.PtrBefore())
|
|
|
|
: api.ProcessRgb(processing_params.PtrBefore(), output.PtrBefore());
|
2020-08-12 06:44:13 +08:00
|
|
|
|
2020-08-18 04:29:07 +08:00
|
|
|
if (!result.value_or(false)) {
|
2020-09-17 23:36:07 +08:00
|
|
|
return absl::FailedPreconditionError(absl::StrCat(
|
|
|
|
"Error processing ", (image_type_ == ImageType::kJpeg ? "jpeg" : "rgb"),
|
|
|
|
" data"));
|
2020-08-12 06:44:13 +08:00
|
|
|
}
|
|
|
|
|
2020-08-18 04:29:07 +08:00
|
|
|
sapi::v::Fd out_fd(open(".", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR));
|
|
|
|
if (out_fd.GetValue() < 0) {
|
2020-09-17 23:36:07 +08:00
|
|
|
return absl::FailedPreconditionError("Error creating temp output file");
|
2020-08-18 04:29:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SAPI_RETURN_IF_ERROR(sandbox()->TransferToSandboxee(&out_fd));
|
|
|
|
|
|
|
|
if (out_fd.GetRemoteFd() < 0) {
|
|
|
|
return absl::FailedPreconditionError(
|
|
|
|
"Error receiving remote FD: remote output fd is set to -1");
|
|
|
|
}
|
|
|
|
|
2020-09-17 23:36:07 +08:00
|
|
|
auto write_result = api.WriteDataToFd(out_fd.GetRemoteFd(), output.PtrNone());
|
2020-08-12 06:44:13 +08:00
|
|
|
|
|
|
|
if (!write_result.value_or(false)) {
|
2020-09-17 23:36:07 +08:00
|
|
|
return absl::FailedPreconditionError("Error writing file inside sandbox");
|
2020-08-12 06:44:13 +08:00
|
|
|
}
|
|
|
|
|
2020-08-18 04:29:07 +08:00
|
|
|
SAPI_RETURN_IF_ERROR(LinkOutFile(out_fd.GetValue()));
|
|
|
|
|
2020-08-12 06:44:13 +08:00
|
|
|
return absl::OkStatus();
|
|
|
|
}
|
|
|
|
|
2020-08-18 04:29:07 +08:00
|
|
|
absl::Status GuetzliTransaction::LinkOutFile(int out_fd) const {
|
|
|
|
if (access(params_.out_file, F_OK) != -1) {
|
|
|
|
if (remove(params_.out_file) < 0) {
|
2020-09-17 23:36:07 +08:00
|
|
|
return absl::FailedPreconditionError(absl::StrCat(
|
|
|
|
"Error deleting existing output file: ", params_.out_file));
|
2020-08-18 04:29:07 +08:00
|
|
|
}
|
2020-08-31 17:19:00 +08:00
|
|
|
}
|
2020-08-18 04:29:07 +08:00
|
|
|
|
2020-08-31 17:19:00 +08:00
|
|
|
std::string path = absl::StrCat("/proc/self/fd/", out_fd);
|
2020-09-17 23:36:07 +08:00
|
|
|
|
2020-08-31 17:19:00 +08:00
|
|
|
if (linkat(AT_FDCWD, path.c_str(), AT_FDCWD, params_.out_file,
|
2020-09-17 23:36:07 +08:00
|
|
|
AT_SYMLINK_FOLLOW) < 0) {
|
2020-08-31 17:19:00 +08:00
|
|
|
return absl::FailedPreconditionError(
|
2020-09-17 23:36:07 +08:00
|
|
|
absl::StrCat("Error linking: ", params_.out_file));
|
2020-08-18 04:29:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return absl::OkStatus();
|
2020-08-12 06:44:13 +08:00
|
|
|
}
|
|
|
|
|
2020-09-25 22:43:06 +08:00
|
|
|
absl::StatusOr<ImageType> GuetzliTransaction::GetImageTypeFromFd(int fd) const {
|
2020-08-12 06:48:48 +08:00
|
|
|
static const unsigned char kPNGMagicBytes[] = {
|
2020-09-17 23:36:07 +08:00
|
|
|
0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n',
|
2020-08-12 06:48:48 +08:00
|
|
|
};
|
2020-08-18 04:29:07 +08:00
|
|
|
char read_buf[sizeof(kPNGMagicBytes)];
|
2020-08-12 06:48:48 +08:00
|
|
|
|
2020-08-18 04:29:07 +08:00
|
|
|
if (read(fd, read_buf, sizeof(kPNGMagicBytes)) != sizeof(kPNGMagicBytes)) {
|
2020-08-12 06:48:48 +08:00
|
|
|
return absl::FailedPreconditionError(
|
2020-09-17 23:36:07 +08:00
|
|
|
"Error determining type of the input file");
|
2020-08-12 06:48:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (lseek(fd, 0, SEEK_SET) != 0) {
|
|
|
|
return absl::FailedPreconditionError(
|
2020-09-17 23:36:07 +08:00
|
|
|
"Error returnig cursor to the beginning");
|
2020-08-12 06:48:48 +08:00
|
|
|
}
|
|
|
|
|
2020-09-17 23:36:07 +08:00
|
|
|
return memcmp(read_buf, kPNGMagicBytes, sizeof(kPNGMagicBytes)) == 0
|
|
|
|
? ImageType::kPng
|
|
|
|
: ImageType::kJpeg;
|
2020-08-12 06:48:48 +08:00
|
|
|
}
|
|
|
|
|
2020-08-31 17:19:00 +08:00
|
|
|
} // namespace guetzli::sandbox
|