void PcapFile::writePackets(const std::vector<PcapPkt>& pkts) { folly::fbvector<PktHeader> hdrs; hdrs.reserve(pkts.size()); folly::fbvector<struct iovec> iov; // Reserve enough space, assuming each packet is in a single IOBuf. // If some packets are split across IOBuf chains then we will end up // allocating more space as needed in the loop below. iov.reserve(pkts.size() * 2); // Build iovecs for all of the packet headers and data for (const auto& pkt : pkts) { hdrs.emplace_back(pkt); PktHeader* curHdr = &hdrs.back(); iov.push_back({(void*)curHdr, sizeof(PktHeader)}); pkt.buf()->appendToIov(&iov); } int ret = writevFull(file_.fd(), iov.data(), iov.size()); folly::checkUnixError(ret, "error writing pcap data"); }
int writeFileAtomicNoThrow( StringPiece filename, iovec* iov, int count, mode_t permissions) { // We write the data to a temporary file name first, then atomically rename // it into place. This ensures that the file contents will always be valid, // even if we crash or are killed partway through writing out data. // // Create a buffer that will contain two things: // - A nul-terminated version of the filename // - The temporary file name std::vector<char> pathBuffer; // Note that we have to explicitly pass in the size here to make // sure the nul byte gets included in the data. constexpr folly::StringPiece suffix(".XXXXXX\0", 8); pathBuffer.resize((2 * filename.size()) + 1 + suffix.size()); // Copy in the filename and then a nul terminator memcpy(pathBuffer.data(), filename.data(), filename.size()); pathBuffer[filename.size()] = '\0'; const char* const filenameCStr = pathBuffer.data(); // Now prepare the temporary path template char* const tempPath = pathBuffer.data() + filename.size() + 1; memcpy(tempPath, filename.data(), filename.size()); memcpy(tempPath + filename.size(), suffix.data(), suffix.size()); auto tmpFD = mkstemp(tempPath); if (tmpFD == -1) { return errno; } bool success = false; SCOPE_EXIT { if (tmpFD != -1) { close(tmpFD); } if (!success) { unlink(tempPath); } }; auto rc = writevFull(tmpFD, iov, count); if (rc == -1) { return errno; } rc = fchmod(tmpFD, permissions); if (rc == -1) { return errno; } // Close the file before renaming to make sure all data has // been successfully written. rc = close(tmpFD); tmpFD = -1; if (rc == -1) { return errno; } rc = rename(tempPath, filenameCStr); if (rc == -1) { return errno; } success = true; return 0; }