BlobStorage::Blob BlobStorage::add(const String& path, const Data& data) { ASSERT(!RunLoop::isMain()); auto hash = computeSHA1(data); if (data.isEmpty()) return { data, hash }; auto blobPath = WebCore::fileSystemRepresentation(blobPathForHash(hash)); auto linkPath = WebCore::fileSystemRepresentation(path); unlink(linkPath.data()); bool blobExists = access(blobPath.data(), F_OK) != -1; if (blobExists) { auto existingData = mapFile(blobPath.data()); if (bytesEqual(existingData, data)) { link(blobPath.data(), linkPath.data()); return { existingData, hash }; } unlink(blobPath.data()); } auto mappedData = data.mapToFile(blobPath.data()); if (mappedData.isNull()) return { }; link(blobPath.data(), linkPath.data()); m_approximateSize += mappedData.size(); return { mappedData, hash }; }
BlobStorage::Blob BlobStorage::get(const String& path) { ASSERT(!RunLoop::isMain()); auto linkPath = WebCore::fileSystemRepresentation(path); auto data = mapFile(linkPath.data()); return { data, computeSHA1(data) }; }
BlobStorage::Blob BlobStorage::add(const String& path, const Data& data) { ASSERT(!RunLoop::isMain()); auto hash = computeSHA1(data); if (data.isEmpty()) return { data, hash }; auto blobPath = WebCore::fileSystemRepresentation(blobPathForHash(hash)); auto linkPath = WebCore::fileSystemRepresentation(path); unlink(linkPath.data()); bool blobExists = access(blobPath.data(), F_OK) != -1; if (blobExists) { auto existingData = mapFile(blobPath.data()); if (bytesEqual(existingData, data)) { link(blobPath.data(), linkPath.data()); return { existingData, hash }; } unlink(blobPath.data()); } int fd = open(blobPath.data(), O_CREAT | O_EXCL | O_RDWR , S_IRUSR | S_IWUSR); if (fd < 0) return { }; size_t size = data.size(); if (ftruncate(fd, size) < 0) { close(fd); return { }; } void* map = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); close(fd); if (map == MAP_FAILED) return { }; uint8_t* mapData = static_cast<uint8_t*>(map); data.apply([&mapData](const uint8_t* bytes, size_t bytesSize) { memcpy(mapData, bytes, bytesSize); mapData += bytesSize; return true; }); // Drop the write permission. mprotect(map, size, PROT_READ); auto mappedData = Data::adoptMap(map, size); link(blobPath.data(), linkPath.data()); m_approximateSize += size; return { mappedData, hash }; }
/** * Entry point. * @param argc Must be equal to 3. * @param argv Must contain : * 1) the executable name. * 2) "all" to compute the sha1 of the whole file or "chunk" for compute sha1 of each chunk. * 3) The filename. * @return 0 if all done fine else > 0 */ int main(int argc, char* argv[]) { QTextStream out(stdout); if (argc != 3) { out << "Usage : " << argv[0] << " (all|chunk) <file>" << endl; return 1; } QString mode = QString(argv[1]); if (mode == "all") { out << computeSHA1(argv[2], BUFFER_SIZE).toHex() << "\n"; } else if (mode == "chunk") { QList<QByteArray> shas = computeMultiSHA1(argv[2], CHUNK_SIZE, BUFFER_SIZE); foreach (QByteArray sha, shas) out << sha.toHex() << "\n"; } return 0; }