/* A simple Backup Client / Server Copyright (C) 2023 Mike Nolan This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ using System; using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Tesses.Backup.Models; using Tesses.VirtualFilesystem; namespace Tesses.Backup { public class BackupContext { IVirtualFilesystem fs; string key; HttpClient clt; long device; internal BackupContext(string key,HttpClient clt,IVirtualFilesystem fs,CreateBackupResponse resp,long device) { this.key=key; this.clt =clt; this.fs = fs; this.BackupResponse = resp; this.device =device; CalculateLength(this.BackupResponse.BackupData,Special.Root); } public CreateBackupResponse BackupResponse {get;set;} public List<(UnixPath Path,string Hash)> FilesToBackup {get;set;}=new List<(UnixPath Path,string Hash)>(); public long TotalBytes {get;set;}=0; private void CalculateLength(List files,UnixPath path) { foreach(var file in files) { if(file.IsFile) { FilesToBackup.Add((path / file.Name,file.Hash)); TotalBytes += file.Length; }else{ CalculateLength(file.SubEntries,path / file.Name); } } } private class CallbackStrm : Stream { Stream strm; Action read; public CallbackStrm(Stream strm,Action read) { this.strm = strm; this.read=read; } public override bool CanRead => strm.CanRead; public override bool CanSeek => strm.CanSeek; public override bool CanWrite => false; public override long Length => strm.Length; public override long Position { get => strm.Position; set => strm.Position=value; } public override void Flush() { strm.Flush(); } public override async Task FlushAsync(CancellationToken cancellationToken) { await strm.FlushAsync(cancellationToken); } public override int Read(byte[] buffer, int offset, int count) { int outCount= strm.Read(buffer,offset,count); this?.read(outCount); return outCount; } public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) { int outCount= await strm.ReadAsync(buffer,offset,count); this?.read(outCount); return outCount; } public override long Seek(long offset, SeekOrigin origin) { return strm.Seek(offset,origin); } public override void SetLength(long value) { throw new NotImplementedException(); } public override void Write(byte[] buffer, int offset, int count) { throw new NotImplementedException(); } } public async Task PerformBackupAsync(IProgress progress=null) { BackupProgress p=new BackupProgress(); var files = FilesToBackup; p.FileCount = files.Count; p.BackupBytesWriten = 0; p.BackupTotalBytes = TotalBytes; for(int i = 0;i{ p.FileBytesWriten += ctx; p.BackupBytesWriten += ctx; progress?.Report(p); })) await clt.PutAsync($"/api/v1/File?key={key}&hash={p.Hash}&device={device}",new StreamContent(strm)); }}catch(Exception ex) { _=ex; } progress?.Report(p); } progress?.Report(p); } } }