Recursively gather files (with '/'-separated relative paths) and the dir list sendZipStream needs. Returns false if any regular file exceeds the store-only entry limit or carries an unsafe relative path — the whole zip must refuse rather than emit a truncated/traversing entry.
| 148 | // store-only entry limit or carries an unsafe relative path — the whole zip |
| 149 | // must refuse rather than emit a truncated/traversing entry. |
| 150 | bool collect(const std::string& root, const std::string& sub, std::vector<TransferProto::SendFile>& files, std::vector<std::string>& dirs) |
| 151 | { |
| 152 | std::string current = root; |
| 153 | if (!current.empty() && current.back() != '/') { |
| 154 | current += '/'; |
| 155 | } |
| 156 | current += sub; |
| 157 | DIR* d = opendir(current.c_str()); |
| 158 | if (d == nullptr) { |
| 159 | return true; // unreadable/empty dir contributes nothing |
| 160 | } |
| 161 | bool ok = true; |
| 162 | while (struct dirent* ent = readdir(d)) { |
| 163 | const std::string name = ent->d_name; |
| 164 | if (name == "." || name == "..") { |
| 165 | continue; |
| 166 | } |
| 167 | const std::string full = current + name; |
| 168 | struct stat st; |
| 169 | if (stat(full.c_str(), &st) != 0) { |
| 170 | continue; |
| 171 | } |
| 172 | if (S_ISDIR(st.st_mode)) { |
| 173 | const std::string nextSub = sub + name + "/"; |
| 174 | dirs.push_back(nextSub); |
| 175 | if (!collect(root, nextSub, files, dirs)) { |
| 176 | ok = false; |
| 177 | } |
| 178 | } |
| 179 | else { |
| 180 | if ((uint64_t)st.st_size > TransferProto::kZipMaxSize) { |
| 181 | ok = false; |
| 182 | continue; |
| 183 | } |
| 184 | TransferProto::SendFile entry; |
| 185 | entry.absPath = full; |
| 186 | entry.relPath = sub + name; |
| 187 | entry.size = (uint32_t)st.st_size; |
| 188 | if (!TransferProto::isSafeZipRelativePath(entry.relPath)) { |
| 189 | ok = false; |
| 190 | continue; |
| 191 | } |
| 192 | files.push_back(entry); |
| 193 | } |
| 194 | } |
| 195 | closedir(d); |
| 196 | return ok; |
| 197 | } |
| 198 | |
| 199 | int zipDir(const char* srcDir, const char* outZipPath) |
| 200 | { |