Flamenco/pkg/shaman/filestore/substore.go
Sybren A. Stüvel fe9849b134 Shaman: fix bunch of path issues on Windows
Shaman was made on Linux, using the `path` module, which only supports
forward slashes. This mostly replaces `path` with `path/filepath` to use
native paths and increase Windows compatibility.

The work isn't done yet, though.
2022-03-28 11:02:18 +02:00

107 lines
3.4 KiB
Go

/* (c) 2019, Blender Foundation - Sybren A. Stüvel
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package filestore
import (
"errors"
"os"
"path/filepath"
)
type storageBin struct {
basePath string
dirName string
hasTempSuffix bool
fileSuffix string
}
var (
errNoWriteAllowed = errors.New("writing is only allowed in storage bins with a temp suffix")
)
func (s *storageBin) storagePrefix(partialPath string) string {
return filepath.Join(s.basePath, s.dirName, partialPath)
}
// Returns whether 'someFullPath' is pointing to a path inside our storage for the given partial path.
// Only looks at the paths, does not perform any filesystem checks to see the file is actually there.
func (s *storageBin) contains(partialPath, someFullPath string) bool {
expectedPrefix := s.storagePrefix(partialPath)
return len(expectedPrefix) < len(someFullPath) && expectedPrefix == someFullPath[:len(expectedPrefix)]
}
// pathOrGlob returns either a path, or a glob when hasTempSuffix=true.
func (s *storageBin) pathOrGlob(partialPath string) string {
pathOrGlob := s.storagePrefix(partialPath)
if s.hasTempSuffix {
pathOrGlob += "-*"
}
pathOrGlob += s.fileSuffix
return pathOrGlob
}
// resolve finds a file '{basePath}/{dirName}/partialPath*{fileSuffix}'
// and returns its path. The * glob pattern is only used when
// hasTempSuffix is true.
func (s *storageBin) resolve(partialPath string) string {
pathOrGlob := s.pathOrGlob(partialPath)
if !s.hasTempSuffix {
_, err := os.Stat(pathOrGlob)
if err != nil {
return ""
}
return pathOrGlob
}
matches, _ := filepath.Glob(pathOrGlob)
if len(matches) == 0 {
return ""
}
return matches[0]
}
// pathFor(somePath) returns that path inside the storage bin, including proper suffix.
// Note that this is only valid for bins without temp suffixes.
func (s *storageBin) pathFor(partialPath string) string {
return s.storagePrefix(partialPath) + s.fileSuffix
}
// openForWriting makes sure there is a place to write to.
func (s *storageBin) openForWriting(partialPath string) (*os.File, error) {
if !s.hasTempSuffix {
return nil, errNoWriteAllowed
}
pathOrGlob := s.pathOrGlob(partialPath)
dirname, filename := filepath.Split(pathOrGlob)
if err := os.MkdirAll(dirname, 0777); err != nil {
return nil, err
}
// This creates the file with 0666 permissions (before umask).
// Note that this is our own TempFile() and not ioutils.TempFile().
return TempFile(dirname, filename)
}