Sybren A. Stüvel
fe9849b134
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.
107 lines
3.4 KiB
Go
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)
|
|
}
|