added cleanup.go
This commit is contained in:
+2
-1
@@ -31,7 +31,8 @@ func run() int {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: cleanup leftover .uploading files on restart
|
conf.Share.RemoveUploadingFiles()
|
||||||
|
|
||||||
srv := server.NewServer(conf)
|
srv := server.NewServer(conf)
|
||||||
if err := srv.StartGoroutine(); err != nil {
|
if err := srv.StartGoroutine(); err != nil {
|
||||||
logger.Error(err)
|
logger.Error(err)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ var ErrIsUploadingAlready = http.NewHttpError(http.StatusConflict,
|
|||||||
var ErrFileIsDir = http.NewHttpError(http.StatusConflict,
|
var ErrFileIsDir = http.NewHttpError(http.StatusConflict,
|
||||||
"there is a directory with such name already")
|
"there is a directory with such name already")
|
||||||
|
|
||||||
// PUT: accept request body and write it to filePath+".uploading"
|
// PUT: accept request body and write it to filePath+UploadingSuffix
|
||||||
// OPTIONS: check if file can be uploaded and return without reading body
|
// OPTIONS: check if file can be uploaded and return without reading body
|
||||||
// returns StatusCreated if upload is a new file, and StatusOK if it is replacing existing file
|
// returns StatusCreated if upload is a new file, and StatusOK if it is replacing existing file
|
||||||
func (conn *TcpConnection) PUT_OPTIONS(req *http.Request) *http.Response {
|
func (conn *TcpConnection) PUT_OPTIONS(req *http.Request) *http.Response {
|
||||||
@@ -87,7 +87,7 @@ func (conn *TcpConnection) handleUpload(req *http.Request, filePath string, file
|
|||||||
WithBodyStr(msg, http.TextPlain)
|
WithBodyStr(msg, http.TextPlain)
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpPath := filePath + ".uploading"
|
tmpPath := filePath + UploadingSuffix
|
||||||
tmpFileExists, fi, err := DirOrFileExists(tmpPath)
|
tmpFileExists, fi, err := DirOrFileExists(tmpPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errToResponse(err)
|
return errToResponse(err)
|
||||||
@@ -161,6 +161,5 @@ func (conn *TcpConnection) handleUpload(req *http.Request, filePath string, file
|
|||||||
}
|
}
|
||||||
renamed = true
|
renamed = true
|
||||||
|
|
||||||
// TODO: is it right status?
|
|
||||||
return conn.http.CreateResponse(resultStatus, req, false)
|
return conn.http.CreateResponse(resultStatus, req, false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PUT writes into filePath+UploadingSuffix and renames it when the body is received
|
||||||
|
const UploadingSuffix = ".uploading"
|
||||||
|
|
||||||
|
// RemoveUploadingFiles deletes UploadingSuffix files left by interrupted uploads
|
||||||
|
// (server crash, kill -9). Call it before the server starts, while nothing is uploading.
|
||||||
|
// Errors are logged, not returned: a share that can't be cleaned is still usable.
|
||||||
|
func (shares Shares) RemoveUploadingFiles() {
|
||||||
|
for _, sh := range shares {
|
||||||
|
// WalkDir doesn't follow symlinks, so it doesn't leave the share
|
||||||
|
_ = filepath.WalkDir(sh.Path, func(path string, d fs.DirEntry, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
confLogger.Warn("cleanup: ", err)
|
||||||
|
return nil // skip unreadable entry, continue walking
|
||||||
|
}
|
||||||
|
if !d.Type().IsRegular() || !strings.HasSuffix(d.Name(), UploadingSuffix) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
err = os.Remove(path)
|
||||||
|
switch {
|
||||||
|
case err == nil:
|
||||||
|
confLogger.Info("cleanup: removed ", path)
|
||||||
|
// nested shares (shared/ and shared/private) walk the same files twice
|
||||||
|
case errors.Is(err, fs.ErrNotExist):
|
||||||
|
default:
|
||||||
|
confLogger.Warn("cleanup: ", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user