File indexing completed on 2023-03-17 11:26:55
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 #if __APPLE__
0013 #include <crt_externs.h>
0014 #define environ (*_NSGetEnviron())
0015 #endif
0016
0017 using namespace edm::storage;
0018
0019 static std::string join(char **cmd) {
0020 size_t size = 0;
0021 for (char **p = cmd; p && p[0]; ++p)
0022 size += 1 + strlen(*p);
0023
0024 std::string result;
0025 result.reserve(size);
0026
0027 for (char **p = cmd; p && p[0]; ++p) {
0028 if (p != cmd)
0029 result += ' ';
0030 result += *p;
0031 }
0032
0033 return result;
0034 }
0035
0036 RemoteFile::RemoteFile(IOFD fd, const std::string &name) : File(fd), name_(name) {}
0037
0038 void RemoteFile::remove(void) { unlink(name_.c_str()); }
0039
0040 void RemoteFile::close(void) {
0041 remove();
0042 File::close();
0043 }
0044
0045 void RemoteFile::abort(void) {
0046 remove();
0047 File::abort();
0048 }
0049
0050 int RemoteFile::local(const std::string &tmpdir, std::string &temp) {
0051
0052
0053
0054
0055 if (tmpdir.empty() || tmpdir == ".") {
0056 size_t len = pathconf(".", _PC_PATH_MAX);
0057 char *buf = (char *)malloc(len);
0058 getcwd(buf, len);
0059
0060 temp.reserve(len + 32);
0061 temp = buf;
0062 free(buf);
0063 } else {
0064 temp.reserve(tmpdir.size() + 32);
0065 temp = tmpdir;
0066 }
0067 if (temp[temp.size() - 1] != '/')
0068 temp += '/';
0069
0070 temp += "storage-factory-local-XXXXXX";
0071 temp.c_str();
0072
0073 int fd = mkstemp(&temp[0]);
0074 if (fd == -1)
0075 throwStorageError("RemoteFile", "Calling RemoteFile::local()", "mkstemp()", errno);
0076
0077 return fd;
0078 }
0079
0080 std::unique_ptr<Storage> RemoteFile::get(int localfd, const std::string &name, char **cmd, int mode) {
0081
0082
0083
0084 assert(!(mode & (IOFlags::OpenWrite | IOFlags::OpenCreate)));
0085
0086 pid_t pid = -1;
0087 int rc = posix_spawnp(&pid, cmd[0], nullptr, nullptr, cmd, environ);
0088
0089 if (rc == -1) {
0090 int errsave = errno;
0091 ::close(localfd);
0092 unlink(name.c_str());
0093 throwStorageError("RemoteFile", "Calling RemoteFile::get()", "posix_spawnp()", errsave);
0094 }
0095
0096 pid_t rcpid;
0097 do
0098 rcpid = waitpid(pid, &rc, 0);
0099 while (rcpid == (pid_t)-1 && errno == EINTR);
0100
0101 if (rcpid == (pid_t)-1) {
0102 int errsave = errno;
0103 ::close(localfd);
0104 unlink(name.c_str());
0105 throwStorageError("RemoteFile", "Calling RemoteFile::get()", "waitpid()", errsave);
0106 }
0107
0108 if (WIFEXITED(rc) && WEXITSTATUS(rc) == 0)
0109 return std::unique_ptr<Storage>(static_cast<Storage *>(new RemoteFile(localfd, name)));
0110 else {
0111 ::close(localfd);
0112 unlink(name.c_str());
0113 cms::Exception ex("RemoteFile");
0114 ex << "'" << join(cmd) << "'"
0115 << (WIFEXITED(rc) ? " exited with exit code "
0116 : WIFSIGNALED(rc) ? " died from signal "
0117 : " died for an obscure unknown reason with exit status ")
0118 << (WIFEXITED(rc) ? WEXITSTATUS(rc)
0119 : WIFSIGNALED(rc) ? WTERMSIG(rc)
0120 : rc);
0121 ex.addContext("Calling RemoteFile::get()");
0122 throw ex;
0123 }
0124 }