13 # include <crt_externs.h> 14 # define environ (*_NSGetEnviron()) 21 for (
char **
p = cmd;
p &&
p[0]; ++
p)
22 size += 1 + strlen(*p);
25 result.reserve (size);
27 for (
char **p = cmd; p && p[0]; ++
p)
44 { unlink (
name_.c_str()); }
61 if (tmpdir.empty () || tmpdir ==
".")
63 size_t len = pathconf (
".", _PC_PATH_MAX);
64 char *buf = (
char *) malloc (len);
67 temp.reserve (len + 32);
73 temp.reserve (tmpdir.size() + 32);
76 if (temp[temp.size()-1] !=
'/')
79 temp +=
"storage-factory-local-XXXXXX";
82 int fd = mkstemp (&temp[0]);
84 throwStorageError(
"RemoteFile",
"Calling RemoteFile::local()",
"mkstemp()", errno);
89 std::unique_ptr<Storage>
98 int rc = posix_spawnp (&pid, cmd[0],
nullptr,
nullptr, cmd, environ);
104 unlink (name.c_str());
105 throwStorageError (
"RemoteFile",
"Calling RemoteFile::get()",
"posix_spawnp()", errsave);
110 rcpid = waitpid(pid, &rc, 0);
111 while (rcpid == (pid_t) -1 && errno == EINTR);
113 if (rcpid == (pid_t) -1)
117 unlink (name.c_str());
118 throwStorageError (
"RemoteFile",
"Calling RemoteFile::get()",
"waitpid()", errsave);
121 if (WIFEXITED(rc) && WEXITSTATUS(rc) == 0)
122 return std::unique_ptr<Storage> (
static_cast<Storage*
>(
new RemoteFile(localfd, name) ) );
126 unlink (name.c_str());
128 ex <<
"'" <<
join(cmd) <<
"'" 129 << (WIFEXITED(rc) ?
" exited with exit code " 130 : WIFSIGNALED(rc) ?
" died from signal " 131 :
" died for an obscure unknown reason with exit status ")
132 << (WIFEXITED(rc) ? WEXITSTATUS(rc)
133 : WIFSIGNALED(rc) ? WTERMSIG(rc)
135 ex.addContext(
"Calling RemoteFile::get()");
void throwStorageError(const char *category, const char *context, const char *call, int error)
void abort(void) override
RemoteFile(IOFD fd, const std::string &name)
static std::unique_ptr< Storage > get(int localfd, const std::string &name, char **cmd, int mode)
void close(void) override
static int local(const std::string &tmpdir, std::string &temp)
static std::string join(char **cmd)
virtual IOFD fd(void) const