| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- /*
- This file is part of Telegram Desktop,
- the official desktop application for the Telegram messaging service.
- For license and copyright information please follow this link:
- https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
- */
- #include "export/output/export_output_file.h"
- #include "export/output/export_output_result.h"
- #include "export/output/export_output_stats.h"
- #include "base/qt/qt_string_view.h"
- #include <QtCore/QFileInfo>
- #include <QtCore/QDir>
- #include <gsl/util>
- namespace Export {
- namespace Output {
- File::File(const QString &path, Stats *stats) : _path(path), _stats(stats) {
- }
- int64 File::size() const {
- return _offset;
- }
- bool File::empty() const {
- return !_offset;
- }
- Result File::writeBlock(const QByteArray &block) {
- const auto result = writeBlockAttempt(block);
- if (!result) {
- _file.reset();
- }
- return result;
- }
- Result File::writeBlockAttempt(const QByteArray &block) {
- if (_stats && !_inStats) {
- _inStats = true;
- _stats->incrementFiles();
- }
- if (const auto result = reopen(); !result) {
- return result;
- }
- const auto size = block.size();
- if (!size) {
- return Result::Success();
- }
- if (_file->write(block) == size && _file->flush()) {
- _offset += size;
- if (_stats) {
- _stats->incrementBytes(size);
- }
- return Result::Success();
- }
- return error();
- }
- Result File::reopen() {
- if (_file && _file->isOpen()) {
- return Result::Success();
- }
- _file.emplace(_path);
- if (_file->exists()) {
- if (_file->size() < _offset) {
- return fatalError();
- } else if (!_file->resize(_offset)) {
- return error();
- }
- } else if (_offset > 0) {
- return fatalError();
- }
- if (_file->open(QIODevice::Append)) {
- return Result::Success();
- }
- const auto info = QFileInfo(_path);
- const auto dir = info.absoluteDir();
- return (!dir.exists()
- && dir.mkpath(dir.absolutePath())
- && _file->open(QIODevice::Append))
- ? Result::Success()
- : error();
- }
- Result File::error() const {
- return Result(Result::Type::Error, _path);
- }
- Result File::fatalError() const {
- return Result(Result::Type::FatalError, _path);
- }
- QString File::PrepareRelativePath(
- const QString &folder,
- const QString &suggested) {
- if (!QFile::exists(folder + suggested)) {
- return suggested;
- }
- // Not lastIndexOf('.') so that "file.tar.xz" won't be messed up.
- const auto position = suggested.indexOf('.');
- const auto base = suggested.mid(0, position);
- const auto extension = (position >= 0)
- ? base::StringViewMid(suggested, position)
- : QStringView();
- const auto relativePart = [&](int attempt) {
- auto result = base + QString(" (%1)").arg(attempt);
- result.append(extension);
- return result;
- };
- auto attempt = 0;
- while (true) {
- const auto relativePath = relativePart(++attempt);
- if (!QFile::exists(folder + relativePath)) {
- return relativePath;
- }
- }
- }
- Result File::Copy(
- const QString &source,
- const QString &path,
- Stats *stats) {
- QFile f(source);
- if (!f.exists() || !f.open(QIODevice::ReadOnly)) {
- return Result(Result::Type::FatalError, source);
- }
- const auto bytes = f.readAll();
- if (bytes.size() != f.size()) {
- return Result(Result::Type::FatalError, source);
- }
- return File(path, stats).writeBlock(bytes);
- }
- } // namespace Output
- } // namespace File
|