| 61 | } |
| 62 | |
| 63 | void temp_fstream::open (std::ios_base::openmode mode) |
| 64 | { |
| 65 | close(); |
| 66 | |
| 67 | const char* tmpdir = getenv("TMPDIR"); |
| 68 | size_t tmpdir_len = tmpdir ? std::strlen(tmpdir) : 0; |
| 69 | if (tmpdir_len == 0 || tmpdir_len > 4096) { |
| 70 | // no $TMPDIR or it's excessively long => fall back to /tmp |
| 71 | tmpdir = "/tmp"; |
| 72 | tmpdir_len = 4; |
| 73 | } |
| 74 | std::vector<char> path_buffer(tmpdir_len + 18); |
| 75 | char* path = &path_buffer[0]; |
| 76 | std::strcpy(path, tmpdir); |
| 77 | std::strcpy(path + tmpdir_len, "/git-crypt.XXXXXX"); |
| 78 | mode_t old_umask = umask(0077); |
| 79 | int fd = mkstemp(path); |
| 80 | if (fd == -1) { |
| 81 | int mkstemp_errno = errno; |
| 82 | umask(old_umask); |
| 83 | throw System_error("mkstemp", "", mkstemp_errno); |
| 84 | } |
| 85 | umask(old_umask); |
| 86 | std::fstream::open(path, mode); |
| 87 | if (!std::fstream::is_open()) { |
| 88 | unlink(path); |
| 89 | ::close(fd); |
| 90 | throw System_error("std::fstream::open", path, 0); |
| 91 | } |
| 92 | unlink(path); |
| 93 | ::close(fd); |
| 94 | } |
| 95 | |
| 96 | void temp_fstream::close () |
| 97 | { |