Writes extracted entries under `root`, creating parent directories as it goes. mkdir on an existing path fails harmlessly; the fopen is the real success check.
| 92 | // goes. mkdir on an existing path fails harmlessly; the fopen is the real |
| 93 | // success check. |
| 94 | struct DirExtractSink : TransferProto::ExtractSink { |
| 95 | std::string root; // always ends with '/' |
| 96 | FILE* out = nullptr; |
| 97 | explicit DirExtractSink(std::string r) : root(std::move(r)) |
| 98 | { |
| 99 | if (root.empty() || root.back() != '/') { |
| 100 | root += '/'; |
| 101 | } |
| 102 | } |
| 103 | ~DirExtractSink() override |
| 104 | { |
| 105 | if (out != nullptr) { |
| 106 | fclose(out); |
| 107 | } |
| 108 | } |
| 109 | void ensureParents(const std::string& relPath) |
| 110 | { |
| 111 | std::string current = root; |
| 112 | size_t start = 0; |
| 113 | for (size_t pos = relPath.find('/', start); pos != std::string::npos; pos = relPath.find('/', start)) { |
| 114 | current += relPath.substr(start, pos - start); |
| 115 | mkdir(current.c_str(), 0777); |
| 116 | current += '/'; |
| 117 | start = pos + 1; |
| 118 | } |
| 119 | } |
| 120 | bool makeDir(const std::string& relPath) override |
| 121 | { |
| 122 | ensureParents(relPath); |
| 123 | std::string full = root + relPath; |
| 124 | if (!full.empty() && full.back() == '/') { |
| 125 | full.pop_back(); |
| 126 | } |
| 127 | mkdir(full.c_str(), 0777); |
| 128 | return true; |
| 129 | } |
| 130 | bool beginFile(const std::string& relPath, uint32_t) override |
| 131 | { |
| 132 | ensureParents(relPath); |
| 133 | out = fopen((root + relPath).c_str(), "wb"); |
| 134 | return out != nullptr; |
| 135 | } |
| 136 | bool writeFile(const void* data, size_t n) override { return out != nullptr && fwrite(data, 1, n, out) == n; } |
| 137 | void endFile() override |
| 138 | { |
| 139 | if (out != nullptr) { |
| 140 | fclose(out); |
| 141 | out = nullptr; |
| 142 | } |
| 143 | } |
| 144 | }; |
| 145 | |
| 146 | // Recursively gather files (with '/'-separated relative paths) and the dir |
| 147 | // list sendZipStream needs. Returns false if any regular file exceeds the |
nothing calls this directly
no outgoing calls
no test coverage detected