sandboxed-api/oss-internship-2020/guetzli/guetzli_transaction.cc

135 lines
3.9 KiB
C++
Raw Normal View History

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-08-12 06:44:13 +08:00
#include "guetzli_transaction.h"
#include <iostream>
2020-08-12 06:48:48 +08:00
#include <memory>
2020-08-12 06:44:13 +08:00
namespace guetzli {
namespace sandbox {
absl::Status GuetzliTransaction::Init() {
2020-08-12 06:48:48 +08:00
// Close remote fd if transaction is repeated
if (in_fd_.GetRemoteFd() != -1) {
SAPI_RETURN_IF_ERROR(in_fd_.CloseRemoteFd(sandbox()->GetRpcChannel()));
2020-08-12 06:44:13 +08:00
}
2020-08-12 06:48:48 +08:00
if (out_fd_.GetRemoteFd() != -1) {
SAPI_RETURN_IF_ERROR(out_fd_.CloseRemoteFd(sandbox()->GetRpcChannel()));
2020-08-12 06:44:13 +08:00
}
2020-08-12 06:48:48 +08:00
// Reposition back to the beginning of file
if (lseek(in_fd_.GetValue(), 0, SEEK_CUR) != 0) {
if (lseek(in_fd_.GetValue(), 0, SEEK_SET) != 0) {
2020-08-12 06:44:13 +08:00
return absl::FailedPreconditionError(
2020-08-12 06:48:48 +08:00
"Error returnig cursor to the beginning"
2020-08-12 06:44:13 +08:00
);
}
2020-08-12 06:48:48 +08:00
}
2020-08-12 06:44:13 +08:00
2020-08-12 06:48:48 +08:00
// Choosing between jpg and png modes
sapi::StatusOr<ImageType> image_type = GetImageTypeFromFd(in_fd_.GetValue());
2020-08-12 06:44:13 +08:00
2020-08-12 06:48:48 +08:00
if (!image_type.ok()) {
return image_type.status();
2020-08-12 06:44:13 +08:00
}
2020-08-12 06:48:48 +08:00
image_type_ = image_type.value();
2020-08-12 06:44:13 +08:00
2020-08-12 06:48:48 +08:00
SAPI_RETURN_IF_ERROR(sandbox()->TransferToSandboxee(&in_fd_));
SAPI_RETURN_IF_ERROR(sandbox()->TransferToSandboxee(&out_fd_));
2020-08-12 06:44:13 +08:00
2020-08-12 06:48:48 +08:00
if (in_fd_.GetRemoteFd() < 0) {
return absl::FailedPreconditionError(
"Error receiving remote FD: remote input fd is set to -1");
}
if (out_fd_.GetRemoteFd() < 0) {
return absl::FailedPreconditionError(
"Error receiving remote FD: remote output fd is set to -1");
}
2020-08-12 06:44:13 +08:00
2020-08-13 05:09:40 +08:00
in_fd_.OwnLocalFd(false); // FDCloser will close local fd
out_fd_.OwnLocalFd(false); // FDCloser will close local fd
2020-08-12 06:44:13 +08:00
2020-08-12 06:48:48 +08:00
return absl::OkStatus();
}
2020-08-12 06:44:13 +08:00
absl::Status GuetzliTransaction::Main() {
GuetzliApi api(sandbox());
sapi::v::LenVal output(0);
2020-08-12 06:48:48 +08:00
sapi::v::Struct<ProcessingParams> processing_params;
*processing_params.mutable_data() = {in_fd_.GetRemoteFd(),
params_.verbose,
params_.quality,
params_.memlimit_mb
};
2020-08-12 06:44:13 +08:00
2020-08-13 05:09:40 +08:00
auto result_status = image_type_ == ImageType::kJpeg ?
2020-08-12 06:48:48 +08:00
api.ProcessJpeg(processing_params.PtrBefore(), output.PtrBoth()) :
api.ProcessRgb(processing_params.PtrBefore(), output.PtrBoth());
if (!result_status.value_or(false)) {
std::stringstream error_stream;
error_stream << "Error processing "
2020-08-13 05:09:40 +08:00
<< (image_type_ == ImageType::kJpeg ? "jpeg" : "rgb") << " data"
2020-08-12 06:48:48 +08:00
<< std::endl;
2020-08-12 06:44:13 +08:00
return absl::FailedPreconditionError(
2020-08-12 06:48:48 +08:00
error_stream.str()
2020-08-12 06:44:13 +08:00
);
}
auto write_result = api.WriteDataToFd(out_fd_.GetRemoteFd(),
output.PtrBefore());
if (!write_result.value_or(false)) {
return absl::FailedPreconditionError(
"Error writing file inside sandbox"
);
}
return absl::OkStatus();
}
time_t GuetzliTransaction::CalculateTimeLimitFromImageSize(
uint64_t pixels) const {
return (pixels / kMpixPixels + 5) * 60;
}
2020-08-12 06:48:48 +08:00
sapi::StatusOr<ImageType> GuetzliTransaction::GetImageTypeFromFd(int fd) const {
static const unsigned char kPNGMagicBytes[] = {
0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n',
};
char read_buf[8];
if (read(fd, read_buf, 8) != 8) {
return absl::FailedPreconditionError(
"Error determining type of the input file"
);
}
if (lseek(fd, 0, SEEK_SET) != 0) {
return absl::FailedPreconditionError(
"Error returnig cursor to the beginning"
);
}
return memcmp(read_buf, kPNGMagicBytes, sizeof(kPNGMagicBytes)) == 0 ?
2020-08-13 05:09:40 +08:00
ImageType::kPng : ImageType::kJpeg;
2020-08-12 06:48:48 +08:00
}
2020-08-13 05:09:40 +08:00
} // namespace sandbox
} // namespace guetzli