Fix "invalid cross-device link" error when running on a different filesystem (#1769)
* fix cross-device rename errors * fallback to copy instead of always using it * use tmp dir in data folder * recreate tmp dir at startup
This commit is contained in:
parent
88ed026eae
commit
a7687c861e
@ -13,6 +13,8 @@ var DatabaseFilePath = "data/owncast.db"
|
|||||||
// LogDirectory is the path to various log files.
|
// LogDirectory is the path to various log files.
|
||||||
var LogDirectory = "./data/logs"
|
var LogDirectory = "./data/logs"
|
||||||
|
|
||||||
|
var TempDir = "./data/tmp"
|
||||||
|
|
||||||
// EnableDebugFeatures will print additional data to help in debugging.
|
// EnableDebugFeatures will print additional data to help in debugging.
|
||||||
var EnableDebugFeatures = false
|
var EnableDebugFeatures = false
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ func appendOfflineToVariantPlaylist(index int, playlistFilePath string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tmpFileName := fmt.Sprintf("tmp-stream-%d.m3u8", index)
|
tmpFileName := fmt.Sprintf("tmp-stream-%d.m3u8", index)
|
||||||
atomicWriteTmpPlaylistFile, err := os.CreateTemp(os.TempDir(), tmpFileName)
|
atomicWriteTmpPlaylistFile, err := os.CreateTemp(config.TempDir, tmpFileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln("error creating tmp playlist file to write to", playlistFilePath, err)
|
log.Errorln("error creating tmp playlist file to write to", playlistFilePath, err)
|
||||||
return
|
return
|
||||||
@ -94,7 +94,7 @@ func createEmptyOfflinePlaylist(playlistFilePath string, offlineFilename string)
|
|||||||
|
|
||||||
func saveOfflineClipToDisk(offlineFilename string) (string, error) {
|
func saveOfflineClipToDisk(offlineFilename string) (string, error) {
|
||||||
offlineFileData := static.GetOfflineSegment()
|
offlineFileData := static.GetOfflineSegment()
|
||||||
offlineTmpFile, err := os.CreateTemp(os.TempDir(), offlineFilename)
|
offlineTmpFile, err := os.CreateTemp(config.TempDir, offlineFilename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln("unable to create temp file for offline video segment", err)
|
log.Errorln("unable to create temp file for offline video segment", err)
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ func fireThumbnailGenerator(segmentPath string, variantIndex int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rename temp file
|
// rename temp file
|
||||||
if err := os.Rename(outputFileTemp, outputFile); err != nil {
|
if err := utils.Move(outputFileTemp, outputFile); err != nil {
|
||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ func makeAnimatedGifPreview(sourceFile string, outputFile string) {
|
|||||||
if _, err := exec.Command("sh", "-c", ffmpegCmd).Output(); err != nil {
|
if _, err := exec.Command("sh", "-c", ffmpegCmd).Output(); err != nil {
|
||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
// rename temp file
|
// rename temp file
|
||||||
} else if err := os.Rename(outputFileTemp, outputFile); err != nil {
|
} else if err := utils.Move(outputFileTemp, outputFile); err != nil {
|
||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
main.go
11
main.go
@ -47,6 +47,17 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recreate the temp dir
|
||||||
|
if utils.DoesFileExists(config.TempDir) {
|
||||||
|
err := os.RemoveAll(config.TempDir)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Unable to remove temp dir!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := os.Mkdir(config.TempDir, 0700); err != nil {
|
||||||
|
log.Fatalln("Unable to create temp dir!", err)
|
||||||
|
}
|
||||||
|
|
||||||
configureLogging(*enableDebugOptions, *enableVerboseLogging)
|
configureLogging(*enableDebugOptions, *enableVerboseLogging)
|
||||||
log.Infoln(config.GetReleaseString())
|
log.Infoln(config.GetReleaseString())
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
@ -60,9 +61,40 @@ func Copy(source, destination string) error {
|
|||||||
return os.WriteFile(destination, input, 0600)
|
return os.WriteFile(destination, input, 0600)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move moves the file to destination.
|
// Move moves the file at source to destination.
|
||||||
func Move(source, destination string) error {
|
func Move(source, destination string) error {
|
||||||
return os.Rename(source, destination)
|
err := os.Rename(source, destination)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln("Moving with os.Rename failed, falling back to copy and delete!", err)
|
||||||
|
return moveFallback(source, destination)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// moveFallback moves a file using a copy followed by a delete, which works across file systems.
|
||||||
|
// source: https://gist.github.com/var23rav/23ae5d0d4d830aff886c3c970b8f6c6b
|
||||||
|
func moveFallback(source, destination string) error {
|
||||||
|
inputFile, err := os.Open(source)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Couldn't open source file: %s", err)
|
||||||
|
}
|
||||||
|
outputFile, err := os.Create(destination)
|
||||||
|
if err != nil {
|
||||||
|
inputFile.Close()
|
||||||
|
return fmt.Errorf("Couldn't open dest file: %s", err)
|
||||||
|
}
|
||||||
|
defer outputFile.Close()
|
||||||
|
_, err = io.Copy(outputFile, inputFile)
|
||||||
|
inputFile.Close()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Writing to output file failed: %s", err)
|
||||||
|
}
|
||||||
|
// The copy was successful, so now delete the original file
|
||||||
|
err = os.Remove(source)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Failed removing original file: %s", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsUserAgentABot returns if a web client user-agent is seen as a bot.
|
// IsUserAgentABot returns if a web client user-agent is seen as a bot.
|
||||||
|
Loading…
Reference in New Issue
Block a user