forked from TrueCloudLab/restic
restore: factor out file creation helper
This commit is contained in:
parent
fc3841e7cc
commit
c166ad7daf
1 changed files with 45 additions and 34 deletions
|
@ -39,6 +39,48 @@ func newFilesWriter(count int) *filesWriter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createFile(path string, createSize int64, sparse bool) (*os.File, error) {
|
||||||
|
var f *os.File
|
||||||
|
var err error
|
||||||
|
if f, err = os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600); err != nil {
|
||||||
|
if !fs.IsAccessDenied(err) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If file is readonly, clear the readonly flag by resetting the
|
||||||
|
// permissions of the file and try again
|
||||||
|
// as the metadata will be set again in the second pass and the
|
||||||
|
// readonly flag will be applied again if needed.
|
||||||
|
if err = fs.ResetPermissions(path); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if f, err = os.OpenFile(path, os.O_TRUNC|os.O_WRONLY, 0600); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if createSize > 0 {
|
||||||
|
if sparse {
|
||||||
|
err = truncateSparse(f, createSize)
|
||||||
|
if err != nil {
|
||||||
|
_ = f.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := fs.PreallocateFile(f, createSize)
|
||||||
|
if err != nil {
|
||||||
|
// Just log the preallocate error but don't let it cause the restore process to fail.
|
||||||
|
// Preallocate might return an error if the filesystem (implementation) does not
|
||||||
|
// support preallocation or our parameters combination to the preallocate call
|
||||||
|
// This should yield a syscall.ENOTSUP error, but some other errors might also
|
||||||
|
// show up.
|
||||||
|
debug.Log("Failed to preallocate %v with size %v: %v", path, createSize, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return f, err
|
||||||
|
}
|
||||||
|
|
||||||
func (w *filesWriter) writeToFile(path string, blob []byte, offset int64, createSize int64, sparse bool) error {
|
func (w *filesWriter) writeToFile(path string, blob []byte, offset int64, createSize int64, sparse bool) error {
|
||||||
bucket := &w.buckets[uint(xxhash.Sum64String(path))%uint(len(w.buckets))]
|
bucket := &w.buckets[uint(xxhash.Sum64String(path))%uint(len(w.buckets))]
|
||||||
|
|
||||||
|
@ -53,22 +95,10 @@ func (w *filesWriter) writeToFile(path string, blob []byte, offset int64, create
|
||||||
var f *os.File
|
var f *os.File
|
||||||
var err error
|
var err error
|
||||||
if createSize >= 0 {
|
if createSize >= 0 {
|
||||||
if f, err = os.OpenFile(path, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600); err != nil {
|
f, err = createFile(path, createSize, sparse)
|
||||||
if fs.IsAccessDenied(err) {
|
if err != nil {
|
||||||
// If file is readonly, clear the readonly flag by resetting the
|
|
||||||
// permissions of the file and try again
|
|
||||||
// as the metadata will be set again in the second pass and the
|
|
||||||
// readonly flag will be applied again if needed.
|
|
||||||
if err = fs.ResetPermissions(path); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if f, err = os.OpenFile(path, os.O_TRUNC|os.O_WRONLY, 0600); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if f, err = os.OpenFile(path, os.O_WRONLY, 0600); err != nil {
|
} else if f, err = os.OpenFile(path, os.O_WRONLY, 0600); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -76,25 +106,6 @@ func (w *filesWriter) writeToFile(path string, blob []byte, offset int64, create
|
||||||
wr := &partialFile{File: f, users: 1, sparse: sparse}
|
wr := &partialFile{File: f, users: 1, sparse: sparse}
|
||||||
bucket.files[path] = wr
|
bucket.files[path] = wr
|
||||||
|
|
||||||
if createSize >= 0 {
|
|
||||||
if sparse {
|
|
||||||
err = truncateSparse(f, createSize)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err := fs.PreallocateFile(wr.File, createSize)
|
|
||||||
if err != nil {
|
|
||||||
// Just log the preallocate error but don't let it cause the restore process to fail.
|
|
||||||
// Preallocate might return an error if the filesystem (implementation) does not
|
|
||||||
// support preallocation or our parameters combination to the preallocate call
|
|
||||||
// This should yield a syscall.ENOTSUP error, but some other errors might also
|
|
||||||
// show up.
|
|
||||||
debug.Log("Failed to preallocate %v with size %v: %v", path, createSize, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return wr, nil
|
return wr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue