1 // Copyright (c) the JPEG XL Project Authors. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file.
5 
6 #define _DEFAULT_SOURCE  // for mkstemps().
7 
8 #include "tools/benchmark/benchmark_utils.h"
9 
10 // Not supported on Windows due to Linux-specific functions.
11 // Not supported in Android NDK before API 28.
12 #if !defined(_WIN32) && !defined(__EMSCRIPTEN__) && \
13     (!defined(__ANDROID_API__) || __ANDROID_API__ >= 28)
14 
15 #include <libgen.h>
16 #include <spawn.h>
17 #include <stdio.h>
18 #include <sys/types.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 
22 #include <fstream>
23 
24 #include "lib/extras/codec_png.h"
25 #include "lib/jxl/base/file_io.h"
26 #include "lib/jxl/codec_in_out.h"
27 #include "lib/jxl/image_bundle.h"
28 
29 extern char** environ;
30 
31 namespace jxl {
TemporaryFile(std::string basename,std::string extension)32 TemporaryFile::TemporaryFile(std::string basename, std::string extension) {
33   const auto extension_size = 1 + extension.size();
34   temp_filename_ = std::move(basename) + "_XXXXXX." + std::move(extension);
35   const int fd = mkstemps(&temp_filename_[0], extension_size);
36   if (fd == -1) {
37     ok_ = false;
38     return;
39   }
40   close(fd);
41 }
~TemporaryFile()42 TemporaryFile::~TemporaryFile() {
43   if (ok_) {
44     unlink(temp_filename_.c_str());
45   }
46 }
47 
GetFileName(std::string * const output) const48 Status TemporaryFile::GetFileName(std::string* const output) const {
49   JXL_RETURN_IF_ERROR(ok_);
50   *output = temp_filename_;
51   return true;
52 }
53 
RunCommand(const std::string & command,const std::vector<std::string> & arguments)54 Status RunCommand(const std::string& command,
55                   const std::vector<std::string>& arguments) {
56   std::vector<char*> args;
57   args.reserve(arguments.size() + 2);
58   args.push_back(const_cast<char*>(command.c_str()));
59   for (const std::string& argument : arguments) {
60     args.push_back(const_cast<char*>(argument.c_str()));
61   }
62   args.push_back(nullptr);
63   pid_t pid;
64   JXL_RETURN_IF_ERROR(posix_spawnp(&pid, command.c_str(), nullptr, nullptr,
65                                    args.data(), environ) == 0);
66   int wstatus;
67   waitpid(pid, &wstatus, 0);
68   return WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == EXIT_SUCCESS;
69 }
70 
71 }  // namespace jxl
72 
73 #else
74 
75 namespace jxl {
76 
TemporaryFile(std::string basename,std::string extension)77 TemporaryFile::TemporaryFile(std::string basename, std::string extension) {}
~TemporaryFile()78 TemporaryFile::~TemporaryFile() {}
GetFileName(std::string * const output) const79 Status TemporaryFile::GetFileName(std::string* const output) const {
80   (void)ok_;
81   return JXL_FAILURE("Not supported on this build");
82 }
83 
RunCommand(const std::string & command,const std::vector<std::string> & arguments)84 Status RunCommand(const std::string& command,
85                   const std::vector<std::string>& arguments) {
86   return JXL_FAILURE("Not supported on this build");
87 }
88 
89 }  // namespace jxl
90 
91 #endif  // _MSC_VER
92