Skip to content

Commit 0445071

Browse files
committed
Add workaround for OneDrive cloud-only files on Windows
1 parent 2def016 commit 0445071

File tree

2 files changed

+24
-13
lines changed

2 files changed

+24
-13
lines changed

src/duplicacy_backupmanager.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ func (manager *BackupManager) Backup(top string, quickMode bool, threads int, ta
396396
var numberOfNewFileChunks int64 // number of new file chunks
397397
var totalUploadedFileChunkLength int64 // total length of uploaded file chunks
398398
var totalUploadedFileChunkBytes int64 // how many actual bytes have been uploaded
399+
var addDataErr string // error string from fileChunkMaker.AddData()
399400

400401
// This function is called when a chunk has been uploaded
401402
uploadChunkCompletionFunc := func(chunk *Chunk, chunkIndex int, inCache bool, chunkSize int, uploadSize int) {
@@ -479,8 +480,11 @@ func (manager *BackupManager) Backup(top string, quickMode bool, threads int, ta
479480
skippedFiles = append(skippedFiles, entry.Path)
480481
continue
481482
}
482-
entry.Size, entry.Hash = fileChunkMaker.AddData(file, uploadChunkFunc)
483-
if !showStatistics || IsTracing() || RunInBackground {
483+
484+
entry.Size, entry.Hash, addDataErr = fileChunkMaker.AddData(file, uploadChunkFunc)
485+
if entry.Size <= 0 && addDataErr == "CLOUD_FILE_FAILURE" {
486+
skippedFiles = append(skippedFiles, entry.Path)
487+
} else if !showStatistics || IsTracing() || RunInBackground {
484488
LOG_INFO("PACK_END", "Packed %s (%d)", entry.Path, entry.Size)
485489
}
486490
file.Close()

src/duplicacy_chunkmaker.go

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"encoding/binary"
1010
"encoding/hex"
1111
"io"
12+
"runtime"
13+
"strings"
1214
)
1315

1416
// ChunkMaker breaks data into chunks using buzhash. To save memory, the chunk maker only use a circular buffer
@@ -135,7 +137,7 @@ func (maker *ChunkMaker) startNewChunk() (chunk *Chunk) {
135137
return
136138
}
137139

138-
func (maker *ChunkMaker) AddData(reader io.Reader, sendChunk func(*Chunk)) (int64, string) {
140+
func (maker *ChunkMaker) AddData(reader io.Reader, sendChunk func(*Chunk)) (int64, string, string) {
139141

140142
isEOF := false
141143
fileSize := int64(0)
@@ -161,7 +163,7 @@ func (maker *ChunkMaker) AddData(reader io.Reader, sendChunk func(*Chunk)) (int6
161163
if maker.minimumChunkSize == maker.maximumChunkSize {
162164

163165
if reader == nil {
164-
return 0, ""
166+
return 0, "", ""
165167
}
166168

167169
for {
@@ -172,8 +174,11 @@ func (maker *ChunkMaker) AddData(reader io.Reader, sendChunk func(*Chunk)) (int6
172174

173175
if err != nil {
174176
if err != io.EOF {
175-
LOG_ERROR("CHUNK_MAKER", "Failed to read %d bytes: %s", count, err.Error())
176-
return 0, ""
177+
// handle OneDrive 'cloud files' errors (sometimes these are caught by os.OpenFile, sometimes
178+
// not)
179+
isWarning := runtime.GOOS == "windows" && strings.HasSuffix(err.Error(), " Access to the cloud file is denied.")
180+
LOG_WERROR(isWarning, "CHUNK_MAKER", "Failed to read %d bytes: %s", count, err.Error())
181+
return -1, "", "CLOUD_FILE_FAILURE" // we'd only hit this if it was a cloud file warning, LOG_ERROR panic exits
177182
} else {
178183
isEOF = true
179184
}
@@ -189,7 +194,7 @@ func (maker *ChunkMaker) AddData(reader io.Reader, sendChunk func(*Chunk)) (int6
189194
}
190195

191196
if isEOF {
192-
return fileSize, hex.EncodeToString(fileHasher.Sum(nil))
197+
return fileSize, hex.EncodeToString(fileHasher.Sum(nil)), ""
193198
}
194199
}
195200

@@ -209,8 +214,10 @@ func (maker *ChunkMaker) AddData(reader io.Reader, sendChunk func(*Chunk)) (int6
209214
count, err = reader.Read(maker.buffer[start : start+count])
210215

211216
if err != nil && err != io.EOF {
212-
LOG_ERROR("CHUNK_MAKER", "Failed to read %d bytes: %s", count, err.Error())
213-
return 0, ""
217+
// handle OneDrive 'cloud files' errors (sometimes these are caught by os.OpenFile, sometimes not)
218+
isWarning := runtime.GOOS == "windows" && strings.HasSuffix(err.Error(), " Access to the cloud file is denied.")
219+
LOG_WERROR(isWarning, "CHUNK_MAKER", "Failed to read %d bytes: %s", count, err.Error())
220+
return -1, "", "CLOUD_FILE_FAILURE" // we'd only hit this if it was a cloud file warning, LOG_ERROR panic exits
214221
}
215222

216223
maker.bufferSize += count
@@ -231,9 +238,9 @@ func (maker *ChunkMaker) AddData(reader io.Reader, sendChunk func(*Chunk)) (int6
231238
if maker.chunk.GetLength() > 0 {
232239
sendChunk(maker.chunk)
233240
}
234-
return 0, ""
241+
return 0, "", ""
235242
} else if isEOF {
236-
return fileSize, hex.EncodeToString(fileHasher.Sum(nil))
243+
return fileSize, hex.EncodeToString(fileHasher.Sum(nil)), ""
237244
} else {
238245
continue
239246
}
@@ -295,12 +302,12 @@ func (maker *ChunkMaker) AddData(reader io.Reader, sendChunk func(*Chunk)) (int6
295302
fill(maker.minimumChunkSize)
296303
sendChunk(maker.chunk)
297304
maker.startNewChunk()
298-
return 0, ""
305+
return 0, "", ""
299306
}
300307
}
301308

302309
if isEOF {
303-
return fileSize, hex.EncodeToString(fileHasher.Sum(nil))
310+
return fileSize, hex.EncodeToString(fileHasher.Sum(nil)), ""
304311
}
305312
}
306313
}

0 commit comments

Comments
 (0)