mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-19 05:02:34 +00:00
ipn/ipnlocal: always write files to partial files, even in buffered mode
The intention was always that files only get written to *.partial files and renamed at the end once fully received, but somewhere in the process that got lost in buffered mode and *.partial files were only being used in direct receive mode. This fix prevents WaitingFiles from returning files that are still being transferred. Updates tailscale/corp#1626 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
5e268e6153
commit
138921ae40
@ -50,10 +50,14 @@ type peerAPIServer struct {
|
|||||||
// download directory (as *.partial files), rather than making
|
// download directory (as *.partial files), rather than making
|
||||||
// the frontend retrieve it over localapi HTTP and write it
|
// the frontend retrieve it over localapi HTTP and write it
|
||||||
// somewhere itself. This is used on GUI macOS version.
|
// somewhere itself. This is used on GUI macOS version.
|
||||||
|
// In directFileMode, the peerapi doesn't do the final rename
|
||||||
|
// from "foo.jpg.partial" to "foo.jpg".
|
||||||
directFileMode bool
|
directFileMode bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// partialSuffix is the suffix appened to files while they're
|
||||||
|
// still in the process of being transferred.
|
||||||
partialSuffix = ".partial"
|
partialSuffix = ".partial"
|
||||||
|
|
||||||
// deletedSuffix is the suffix for a deleted marker file
|
// deletedSuffix is the suffix for a deleted marker file
|
||||||
@ -608,19 +612,18 @@ func (h *peerAPIHandler) handlePeerPut(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Error(w, "bad filename", 400)
|
http.Error(w, "bad filename", 400)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if h.ps.directFileMode {
|
// TODO(bradfitz): prevent same filename being sent by two peers at once
|
||||||
dstFile += partialSuffix
|
partialFile := dstFile + partialSuffix
|
||||||
}
|
f, err := os.Create(partialFile)
|
||||||
f, err := os.Create(dstFile)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logf("put Create error: %v", err)
|
h.logf("put Create error: %v", redactErr(err))
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var success bool
|
var success bool
|
||||||
defer func() {
|
defer func() {
|
||||||
if !success {
|
if !success {
|
||||||
os.Remove(dstFile)
|
os.Remove(partialFile)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
var finalSize int64
|
var finalSize int64
|
||||||
@ -634,7 +637,7 @@ func (h *peerAPIHandler) handlePeerPut(w http.ResponseWriter, r *http.Request) {
|
|||||||
ph: h,
|
ph: h,
|
||||||
}
|
}
|
||||||
if h.ps.directFileMode {
|
if h.ps.directFileMode {
|
||||||
inFile.partialPath = dstFile
|
inFile.partialPath = partialFile
|
||||||
}
|
}
|
||||||
h.ps.b.registerIncomingFile(inFile, true)
|
h.ps.b.registerIncomingFile(inFile, true)
|
||||||
defer h.ps.b.registerIncomingFile(inFile, false)
|
defer h.ps.b.registerIncomingFile(inFile, false)
|
||||||
@ -656,6 +659,13 @@ func (h *peerAPIHandler) handlePeerPut(w http.ResponseWriter, r *http.Request) {
|
|||||||
if inFile != nil { // non-zero length; TODO: notify even for zero length
|
if inFile != nil { // non-zero length; TODO: notify even for zero length
|
||||||
inFile.markAndNotifyDone()
|
inFile.markAndNotifyDone()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if err := os.Rename(partialFile, dstFile); err != nil {
|
||||||
|
err = redactErr(err)
|
||||||
|
h.logf("put final rename: %v", err)
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h.logf("put of %s from %v/%v", approxSize(finalSize), h.remoteAddr.IP, h.peerNode.ComputedName)
|
h.logf("put of %s from %v/%v", approxSize(finalSize), h.remoteAddr.IP, h.peerNode.ComputedName)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user