in watchman/ContentHash.cpp [57:140]
HashValue ContentHashCache::computeHashImmediate(const char* fullPath) {
HashValue result;
uint8_t buf[8192];
auto stm = w_stm_open(fullPath, O_RDONLY);
if (!stm) {
throw std::system_error(
errno,
std::generic_category(),
to<std::string>("w_stm_open ", fullPath));
}
#ifndef _WIN32
SHA_CTX ctx;
SHA1_Init(&ctx);
while (true) {
auto n = stm->read(buf, sizeof(buf));
if (n == 0) {
break;
}
if (n < 0) {
throw std::system_error(
errno,
std::generic_category(),
to<std::string>("while reading from ", fullPath));
}
SHA1_Update(&ctx, buf, n);
}
SHA1_Final(result.data(), &ctx);
#else
// Use the built-in crypt provider API on windows to avoid introducing a
// dependency on openssl in the windows build.
HCRYPTPROV provider{0};
HCRYPTHASH ctx{0};
if (!CryptAcquireContext(
&provider,
nullptr,
nullptr,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
throw std::system_error(
GetLastError(), std::system_category(), "CryptAcquireContext");
}
SCOPE_EXIT {
CryptReleaseContext(provider, 0);
};
if (!CryptCreateHash(provider, CALG_SHA1, 0, 0, &ctx)) {
throw std::system_error(
GetLastError(), std::system_category(), "CryptCreateHash");
}
SCOPE_EXIT {
CryptDestroyHash(ctx);
};
while (true) {
auto n = stm->read(buf, sizeof(buf));
if (n == 0) {
break;
}
if (n < 0) {
throw std::system_error(
errno,
std::generic_category(),
to<std::string>("while reading from ", fullPath));
}
if (!CryptHashData(ctx, buf, n, 0)) {
throw std::system_error(
GetLastError(), std::system_category(), "CryptHashData");
}
}
DWORD size = result.size();
if (!CryptGetHashParam(ctx, HP_HASHVAL, result.data(), &size, 0)) {
throw std::system_error(
GetLastError(), std::system_category(), "CryptGetHashParam HP_HASHVAL");
}
#endif
return result;
}