File indexing completed on 2024-07-12 02:42:04
0001 #include "Utilities/StorageFactory/interface/RemoteFile.h"
0002 #include "Utilities/StorageFactory/src/Throw.h"
0003 #include "FWCore/Utilities/interface/Exception.h"
0004 #include <sys/wait.h>
0005 #include <sys/types.h>
0006 #include <cerrno>
0007 #include <cassert>
0008 #include <spawn.h>
0009 #include <unistd.h>
0010 #include <ostream>
0011 #include <cstring>
0012 #include <filesystem>
0013 #include <vector>
0014 #if __APPLE__
0015 #include <crt_externs.h>
0016 #define environ (*_NSGetEnviron())
0017 #endif
0018
0019 using namespace edm::storage;
0020
0021 static std::string join(char **cmd) {
0022 size_t size = 0;
0023 for (char **p = cmd; p && p[0]; ++p)
0024 size += 1 + strlen(*p);
0025
0026 std::string result;
0027 result.reserve(size);
0028
0029 for (char **p = cmd; p && p[0]; ++p) {
0030 if (p != cmd)
0031 result += ' ';
0032 result += *p;
0033 }
0034
0035 return result;
0036 }
0037
0038 RemoteFile::RemoteFile(IOFD fd, const std::string &name) : File(fd), name_(name) {}
0039
0040 void RemoteFile::remove(void) { unlink(name_.c_str()); }
0041
0042 void RemoteFile::close(void) {
0043 remove();
0044 File::close();
0045 }
0046
0047 void RemoteFile::abort(void) {
0048 remove();
0049 File::abort();
0050 }
0051
0052 int RemoteFile::local(const std::string &tmpdir, std::string &temp) {
0053
0054
0055
0056
0057 std::vector<char> temp_chars;
0058
0059 if (tmpdir.empty() || tmpdir == ".") {
0060 std::filesystem::path current_path = std::filesystem::current_path();
0061 auto spath = current_path.string();
0062 temp_chars.reserve(spath.size() + 30);
0063 temp_chars.assign(spath.begin(), spath.end());
0064 } else {
0065 temp_chars.reserve(tmpdir.size() + 30);
0066 temp_chars.assign(tmpdir.begin(), tmpdir.end());
0067 }
0068
0069 if (temp_chars.back() != '/')
0070 temp_chars.push_back('/');
0071
0072 std::string suffix = "storage-factory-local-XXXXXX";
0073 temp_chars.insert(temp_chars.end(), suffix.begin(), suffix.end());
0074
0075
0076 temp_chars.push_back('\0');
0077
0078 int fd = mkstemp(temp_chars.data());
0079 if (fd == -1)
0080 throwStorageError("RemoteFile", "Calling RemoteFile::local()", "mkstemp()", errno);
0081
0082 temp.assign(temp_chars.begin(), temp_chars.end() - 1);
0083
0084 return fd;
0085 }
0086
0087 std::unique_ptr<Storage> RemoteFile::get(int localfd, const std::string &name, char **cmd, int mode) {
0088
0089
0090
0091 assert(!(mode & (IOFlags::OpenWrite | IOFlags::OpenCreate)));
0092
0093 pid_t pid = -1;
0094 int rc = posix_spawnp(&pid, cmd[0], nullptr, nullptr, cmd, environ);
0095
0096 if (rc == -1) {
0097 int errsave = errno;
0098 ::close(localfd);
0099 unlink(name.c_str());
0100 throwStorageError("RemoteFile", "Calling RemoteFile::get()", "posix_spawnp()", errsave);
0101 }
0102
0103 pid_t rcpid;
0104 do
0105 rcpid = waitpid(pid, &rc, 0);
0106 while (rcpid == (pid_t)-1 && errno == EINTR);
0107
0108 if (rcpid == (pid_t)-1) {
0109 int errsave = errno;
0110 ::close(localfd);
0111 unlink(name.c_str());
0112 throwStorageError("RemoteFile", "Calling RemoteFile::get()", "waitpid()", errsave);
0113 }
0114
0115 if (WIFEXITED(rc) && WEXITSTATUS(rc) == 0)
0116 return std::unique_ptr<Storage>(static_cast<Storage *>(new RemoteFile(localfd, name)));
0117 else {
0118 ::close(localfd);
0119 unlink(name.c_str());
0120 cms::Exception ex("RemoteFile");
0121 ex << "'" << join(cmd) << "'"
0122 << (WIFEXITED(rc) ? " exited with exit code "
0123 : WIFSIGNALED(rc) ? " died from signal "
0124 : " died for an obscure unknown reason with exit status ")
0125 << (WIFEXITED(rc) ? WEXITSTATUS(rc)
0126 : WIFSIGNALED(rc) ? WTERMSIG(rc)
0127 : rc);
0128 ex.addContext("Calling RemoteFile::get()");
0129 throw ex;
0130 }
0131 }