MCPcopy Create free account
hub / github.com/Snapchat/Valdi / decompressToMmap

Method decompressToMmap

valdi/src/valdi/runtime/Resources/ZStdUtils.cpp:94–173  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

92 return output;
93}
94Result<Ref<MmapBuffer>> ZStdUtils::decompressToMmap(const Byte* input,
95 size_t len,
96 const Path& filePath,
97 bool* outPublishFailed) {
98 auto firstFrameSize = ZSTD_findFrameCompressedSize(input, len);
99 bool isSingleFrame = !ZSTD_isError(firstFrameSize) && firstFrameSize == len;
100
101 if (!isSingleFrame) {
102 return Error("decompressToMmap requires a single ZStd frame");
103 }
104
105 auto contentSize = ZSTD_getFrameContentSize(input, len);
106 if (contentSize == ZSTD_CONTENTSIZE_UNKNOWN || contentSize == ZSTD_CONTENTSIZE_ERROR) {
107 return Error("ZStd frame does not encode the decompressed content size");
108 }
109
110 if (contentSize > kMaxSinglePassDecompressSize) {
111 return Error(
112 STRING_FORMAT("Decompressed size {} exceeds maximum {}", contentSize, kMaxSinglePassDecompressSize));
113 }
114
115 // mkstemp atomically creates a uniquely-named file and returns an open fd.
116 // We deliberately place the tmp file in the SAME directory as the final
117 // target rather than under std::filesystem::temp_directory_path():
118 // 1. On Android, temp_directory_path() throws filesystem_error when
119 // TMPDIR is unset and /tmp doesn't exist.
120 // 2. Even when it returns a valid path, it's typically on a different
121 // mount point than the app's cache dir, which makes std::rename
122 // fail with EXDEV and silently drop the file.
123 // Placing the tmp next to the target guarantees same-filesystem atomic
124 // rename. The parent directory is already ensured to exist by
125 // ValdiModuleArchive::decompress before we get here.
126 std::string tmpPathStr = filePath.toString() + ".XXXXXX";
127 int tmpFd = mkstemp(tmpPathStr.data());
128 if (tmpFd < 0) {
129 return Error(STRING_FORMAT("mkstemp failed for template '{}': {}", tmpPathStr, strerror(errno)));
130 }
131
132 struct TmpFileGuard {
133 std::string path;
134 bool dismissed = false;
135 ~TmpFileGuard() {
136 if (!dismissed) {
137 unlink(path.c_str());
138 }
139 }
140 } tmpGuard{tmpPathStr};
141
142 // createWritable(fd, ...) takes ownership of tmpFd and closes it on every path.
143 auto bufferResult = MmapBuffer::createWritable(tmpFd, static_cast<size_t>(contentSize), tmpPathStr);
144 if (!bufferResult) {
145 return bufferResult.error().rethrow("Failed to create mmap buffer");
146 }
147
148 auto buffer = bufferResult.moveValue();
149
150 auto result = ZSTD_decompress(const_cast<Byte*>(buffer->data()), buffer->size(), input, len);
151 if (ZSTD_isError(result) != 0) {

Callers

nothing calls this directly

Calls 12

ZSTD_isErrorFunction · 0.85
ZSTD_getFrameContentSizeFunction · 0.85
ZSTD_decompressFunction · 0.85
ZSTD_getErrorNameFunction · 0.85
rethrowMethod · 0.80
makeReadOnlyMethod · 0.80
toStringMethod · 0.65
errorMethod · 0.65
ErrorInterface · 0.50
dataMethod · 0.45
sizeMethod · 0.45

Tested by

no test coverage detected