Convert all filesystem error types into the same Error struct

This commit is contained in:
Dane Everitt 2020-12-15 20:51:13 -08:00
parent 9ae75a399b
commit 3a26a5d39d
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53
11 changed files with 104 additions and 75 deletions

View File

@ -99,8 +99,8 @@ func (e *RequestError) Abort(c *gin.Context) {
// Handle specific filesystem errors for a server. // Handle specific filesystem errors for a server.
func (e *RequestError) AbortFilesystemError(c *gin.Context) { func (e *RequestError) AbortFilesystemError(c *gin.Context) {
if errors.Is(e.Err, os.ErrNotExist) || filesystem.IsBadPathResolutionError(e.Err) { if errors.Is(e.Err, os.ErrNotExist) || filesystem.IsErrorCode(e.Err, filesystem.ErrCodePathResolution) {
if filesystem.IsBadPathResolutionError(e.Err) { if filesystem.IsErrorCode(e.Err, filesystem.ErrCodePathResolution) {
e.logger().Warn(e.Err.Error()) e.logger().Warn(e.Err.Error())
} }
@ -108,7 +108,7 @@ func (e *RequestError) AbortFilesystemError(c *gin.Context) {
return return
} }
if errors.Is(e.Err, filesystem.ErrNotEnoughDiskSpace) { if filesystem.IsErrorCode(e.Err, filesystem.ErrCodeDiskSpace) {
c.AbortWithStatusJSON(http.StatusConflict, gin.H{"error": "There is not enough disk space available to perform that action."}) c.AbortWithStatusJSON(http.StatusConflict, gin.H{"error": "There is not enough disk space available to perform that action."})
return return
} }

View File

@ -56,7 +56,7 @@ func getServerFileContents(c *gin.Context) {
// Returns the contents of a directory for a server. // Returns the contents of a directory for a server.
func getServerListDirectory(c *gin.Context) { func getServerListDirectory(c *gin.Context) {
s := GetServer(c.Param("server")) s := ExtractServer(c)
stats, err := s.Filesystem().ListDirectory(c.Query("directory")) stats, err := s.Filesystem().ListDirectory(c.Query("directory"))
if err != nil { if err != nil {
@ -211,7 +211,7 @@ func postServerWriteFile(c *gin.Context) {
f = "/" + strings.TrimLeft(f, "/") f = "/" + strings.TrimLeft(f, "/")
if err := s.Filesystem().Writefile(f, c.Request.Body); err != nil { if err := s.Filesystem().Writefile(f, c.Request.Body); err != nil {
if errors.Is(err, filesystem.ErrIsDirectory) { if filesystem.IsErrorCode(err, filesystem.ErrCodeIsDirectory) {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"error": "Cannot write file, name conflicts with an existing directory by the same name.", "error": "Cannot write file, name conflicts with an existing directory by the same name.",
}) })
@ -257,7 +257,7 @@ func postServerDownloadRemoteFile(c *gin.Context) {
filename := strings.Split(u.Path, "/") filename := strings.Split(u.Path, "/")
if err := s.Filesystem().Writefile(filepath.Join(data.BasePath, filename[len(filename)-1]), resp.Body); err != nil { if err := s.Filesystem().Writefile(filepath.Join(data.BasePath, filename[len(filename)-1]), resp.Body); err != nil {
if errors.Is(err, filesystem.ErrIsDirectory) { if filesystem.IsErrorCode(err, filesystem.ErrCodeIsDirectory) {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"error": "Cannot write file, name conflicts with an existing directory by the same name.", "error": "Cannot write file, name conflicts with an existing directory by the same name.",
}) })
@ -351,9 +351,8 @@ func postServerDecompressFiles(c *gin.Context) {
hasSpace, err := s.Filesystem().SpaceAvailableForDecompression(data.RootPath, data.File) hasSpace, err := s.Filesystem().SpaceAvailableForDecompression(data.RootPath, data.File)
if err != nil { if err != nil {
// Handle an unknown format error. // Handle an unknown format error.
if errors.Is(err, filesystem.ErrUnknownArchiveFormat) { if filesystem.IsErrorCode(err, filesystem.ErrCodeUnknownArchive) {
s.Log().WithField("error", err).Warn("failed to decompress file due to unknown format") s.Log().WithField("error", err).Warn("failed to decompress file due to unknown format")
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
"error": "unknown archive format", "error": "unknown archive format",
}) })

View File

@ -40,7 +40,7 @@ func (fs *Filesystem) GetIncludedFiles(dir string, ignored []string) (*backup.In
if e.IsSymlink() { if e.IsSymlink() {
sp, err = fs.SafePath(p) sp, err = fs.SafePath(p)
if err != nil { if err != nil {
if IsBadPathResolutionError(err) { if IsErrorCode(err, ErrCodePathResolution) {
return godirwalk.SkipThis return godirwalk.SkipThis
} }
@ -114,7 +114,7 @@ func (fs *Filesystem) CompressFiles(dir string, paths []string) (os.FileInfo, er
// use the resolved location for the rest of this function. // use the resolved location for the rest of this function.
sp, err = fs.SafePath(p) sp, err = fs.SafePath(p)
if err != nil { if err != nil {
if IsBadPathResolutionError(err) { if IsErrorCode(err, ErrCodePathResolution) {
return godirwalk.SkipThis return godirwalk.SkipThis
} }

View File

@ -36,7 +36,7 @@ func (fs *Filesystem) SpaceAvailableForDecompression(dir string, file string) (b
// Walk over the archive and figure out just how large the final output would be from unarchiving it. // Walk over the archive and figure out just how large the final output would be from unarchiving it.
err = archiver.Walk(source, func(f archiver.File) error { err = archiver.Walk(source, func(f archiver.File) error {
if atomic.AddInt64(&size, f.Size())+dirSize > fs.MaxDisk() { if atomic.AddInt64(&size, f.Size())+dirSize > fs.MaxDisk() {
return ErrNotEnoughDiskSpace return &Error{code: ErrCodeDiskSpace}
} }
return nil return nil
@ -44,7 +44,7 @@ func (fs *Filesystem) SpaceAvailableForDecompression(dir string, file string) (b
if err != nil { if err != nil {
if strings.HasPrefix(err.Error(), "format ") { if strings.HasPrefix(err.Error(), "format ") {
return false, ErrUnknownArchiveFormat return false, &Error{code: ErrCodeUnknownArchive}
} }
return false, err return false, err
@ -100,7 +100,7 @@ func (fs *Filesystem) DecompressFile(dir string, file string) error {
}) })
if err != nil { if err != nil {
if strings.HasPrefix(err.Error(), "format ") { if strings.HasPrefix(err.Error(), "format ") {
return ErrUnknownArchiveFormat return &Error{code: ErrCodeUnknownArchive}
} }
return err return err

View File

@ -171,7 +171,7 @@ func (fs *Filesystem) DirectorySize(dir string) (int64, error) {
// it. Otherwise, allow it to continue. // it. Otherwise, allow it to continue.
if e.IsSymlink() { if e.IsSymlink() {
if _, err := fs.SafePath(p); err != nil { if _, err := fs.SafePath(p); err != nil {
if IsBadPathResolutionError(err) { if IsErrorCode(err, ErrCodePathResolution) {
return godirwalk.SkipThis return godirwalk.SkipThis
} }
@ -205,7 +205,7 @@ func (fs *Filesystem) hasSpaceFor(size int64) error {
} }
if (s + size) > fs.MaxDisk() { if (s + size) > fs.MaxDisk() {
return ErrNotEnoughDiskSpace return &Error{code: ErrCodeDiskSpace}
} }
return nil return nil

View File

@ -8,42 +8,72 @@ import (
"path/filepath" "path/filepath"
) )
var ErrIsDirectory = errors.New("filesystem: is a directory") type ErrorCode string
var ErrNotEnoughDiskSpace = errors.New("filesystem: not enough disk space")
var ErrUnknownArchiveFormat = errors.New("filesystem: unknown archive format")
type BadPathResolutionError struct { const (
ErrCodeIsDirectory ErrorCode = "E_ISDIR"
ErrCodeDiskSpace ErrorCode = "E_NODISK"
ErrCodeUnknownArchive ErrorCode = "E_UNKNFMT"
ErrCodePathResolution ErrorCode = "E_BADPATH"
)
type Error struct {
code ErrorCode
path string path string
resolved string resolved string
} }
// Returns the specific error for a bad path resolution. // Returns a human-readable error string to identify the Error by.
func (b *BadPathResolutionError) Error() string { func (e *Error) Error() string {
r := b.resolved switch e.code {
if r == "" { case ErrCodeIsDirectory:
r = "<empty>" return "filesystem: is a directory"
case ErrCodeDiskSpace:
return "filesystem: not enough disk space"
case ErrCodeUnknownArchive:
return "filesystem: unknown archive format"
case ErrCodePathResolution:
r := e.resolved
if r == "" {
r = "<empty>"
}
return fmt.Sprintf("filesystem: server path [%s] resolves to a location outside the server root: %s", e.path, r)
} }
return "filesystem: unhandled error type"
}
return fmt.Sprintf("filesystem: server path [%s] resolves to a location outside the server root: %s", b.path, r) // Returns the ErrorCode for this specific error instance.
func (e *Error) Code() ErrorCode {
return e.code
}
// Checks if the given error is one of the Filesystem errors.
func IsFilesystemError(err error) (*Error, bool) {
if e := errors.Unwrap(err); e != nil {
err = e
}
if fserr, ok := err.(*Error); ok {
return fserr, true
}
return nil, false
}
// Checks if "err" is a filesystem Error type. If so, it will then drop in and check
// that the error code is the same as the provided ErrorCode passed in "code".
func IsErrorCode(err error, code ErrorCode) bool {
if e, ok := IsFilesystemError(err); ok {
return e.code == code
}
return false
}
func NewDiskSpaceError() *Error {
return &Error{code: ErrCodeDiskSpace}
} }
// Returns a new BadPathResolution error. // Returns a new BadPathResolution error.
func NewBadPathResolution(path string, resolved string) *BadPathResolutionError { func NewBadPathResolution(path string, resolved string) *Error {
return &BadPathResolutionError{path, resolved} return &Error{code: ErrCodePathResolution, path: path, resolved: resolved}
}
// Determines if the given error is a bad path resolution error.
func IsBadPathResolutionError(err error) bool {
e := errors.Unwrap(err)
if e == nil {
e = err
}
if _, ok := e.(*BadPathResolutionError); ok {
return true
}
return false
} }
// Generates an error logger instance with some basic information. // Generates an error logger instance with some basic information.
@ -57,7 +87,7 @@ func (fs *Filesystem) error(err error) *log.Entry {
// directory, otherwise return nil. Returning this error for a file will stop the walking // directory, otherwise return nil. Returning this error for a file will stop the walking
// for the remainder of the directory. This is assuming an os.FileInfo struct was even returned. // for the remainder of the directory. This is assuming an os.FileInfo struct was even returned.
func (fs *Filesystem) handleWalkerError(err error, f os.FileInfo) error { func (fs *Filesystem) handleWalkerError(err error, f os.FileInfo) error {
if !IsBadPathResolutionError(err) { if !IsErrorCode(err, ErrCodePathResolution) {
return err return err
} }

View File

@ -11,9 +11,9 @@ func TestFilesystem_PathResolutionError(t *testing.T) {
g.Describe("NewBadPathResolutionError", func() { g.Describe("NewBadPathResolutionError", func() {
g.It("is can detect itself as an error correctly", func() { g.It("is can detect itself as an error correctly", func() {
err := NewBadPathResolution("foo", "bar") err := NewBadPathResolution("foo", "bar")
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
g.Assert(err.Error()).Equal("filesystem: server path [foo] resolves to a location outside the server root: bar") g.Assert(err.Error()).Equal("filesystem: server path [foo] resolves to a location outside the server root: bar")
g.Assert(IsBadPathResolutionError(ErrIsDirectory)).IsFalse() g.Assert(IsErrorCode(&Error{code: ErrCodeIsDirectory}, ErrCodePathResolution)).IsFalse()
}) })
g.It("returns <empty> if no destination path is provided", func() { g.It("returns <empty> if no destination path is provided", func() {

View File

@ -62,7 +62,7 @@ func (fs *Filesystem) Readfile(p string, w io.Writer) error {
if st, err := os.Stat(cleaned); err != nil { if st, err := os.Stat(cleaned); err != nil {
return err return err
} else if st.IsDir() { } else if st.IsDir() {
return ErrIsDirectory return &Error{code: ErrCodeIsDirectory}
} }
f, err := os.Open(cleaned) f, err := os.Open(cleaned)
@ -100,7 +100,7 @@ func (fs *Filesystem) Writefile(p string, r io.Reader) error {
} }
} else { } else {
if stat.IsDir() { if stat.IsDir() {
return ErrIsDirectory return &Error{code: ErrCodeIsDirectory}
} }
currentSize = stat.Size() currentSize = stat.Size()

View File

@ -98,7 +98,7 @@ func TestFilesystem_Readfile(t *testing.T) {
err = fs.Readfile("test.txt", buf) err = fs.Readfile("test.txt", buf)
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(errors.Is(err, ErrIsDirectory)).IsTrue() g.Assert(IsErrorCode(err, ErrCodeIsDirectory)).IsTrue()
}) })
g.It("cannot open a file outside the root directory", func() { g.It("cannot open a file outside the root directory", func() {
@ -107,7 +107,7 @@ func TestFilesystem_Readfile(t *testing.T) {
err = fs.Readfile("/../test.txt", buf) err = fs.Readfile("/../test.txt", buf)
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
g.AfterEach(func() { g.AfterEach(func() {
@ -168,7 +168,7 @@ func TestFilesystem_Writefile(t *testing.T) {
err := fs.Writefile("/some/../foo/../../test.txt", r) err := fs.Writefile("/some/../foo/../../test.txt", r)
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
g.It("cannot write a file that exceeds the disk limits", func() { g.It("cannot write a file that exceeds the disk limits", func() {
@ -182,7 +182,7 @@ func TestFilesystem_Writefile(t *testing.T) {
r := bytes.NewReader(b) r := bytes.NewReader(b)
err = fs.Writefile("test.txt", r) err = fs.Writefile("test.txt", r)
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(errors.Is(err, ErrNotEnoughDiskSpace)).IsTrue() g.Assert(IsErrorCode(err, ErrCodeDiskSpace)).IsTrue()
}) })
/*g.It("updates the total space used when a file is appended to", func() { /*g.It("updates the total space used when a file is appended to", func() {
@ -259,7 +259,7 @@ func TestFilesystem_CreateDirectory(t *testing.T) {
g.It("should not allow the creation of directories outside the root", func() { g.It("should not allow the creation of directories outside the root", func() {
err := fs.CreateDirectory("test", "e/../../something") err := fs.CreateDirectory("test", "e/../../something")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
g.It("should not increment the disk usage", func() { g.It("should not increment the disk usage", func() {
@ -309,7 +309,7 @@ func TestFilesystem_Rename(t *testing.T) {
g.It("does not allow renaming to a location outside the root", func() { g.It("does not allow renaming to a location outside the root", func() {
err := fs.Rename("source.txt", "../target.txt") err := fs.Rename("source.txt", "../target.txt")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
g.It("does not allow renaming from a location outside the root", func() { g.It("does not allow renaming from a location outside the root", func() {
@ -317,7 +317,7 @@ func TestFilesystem_Rename(t *testing.T) {
err = fs.Rename("/../ext-source.txt", "target.txt") err = fs.Rename("/../ext-source.txt", "target.txt")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
g.It("allows a file to be renamed", func() { g.It("allows a file to be renamed", func() {
@ -395,7 +395,7 @@ func TestFilesystem_Copy(t *testing.T) {
err = fs.Copy("../ext-source.txt") err = fs.Copy("../ext-source.txt")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
g.It("should return an error if the source directory is outside the root", func() { g.It("should return an error if the source directory is outside the root", func() {
@ -407,11 +407,11 @@ func TestFilesystem_Copy(t *testing.T) {
err = fs.Copy("../nested/in/dir/ext-source.txt") err = fs.Copy("../nested/in/dir/ext-source.txt")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
err = fs.Copy("nested/in/../../../nested/in/dir/ext-source.txt") err = fs.Copy("nested/in/../../../nested/in/dir/ext-source.txt")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
g.It("should return an error if the source is a directory", func() { g.It("should return an error if the source is a directory", func() {
@ -428,7 +428,7 @@ func TestFilesystem_Copy(t *testing.T) {
err := fs.Copy("source.txt") err := fs.Copy("source.txt")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(errors.Is(err, ErrNotEnoughDiskSpace)).IsTrue() g.Assert(IsErrorCode(err, ErrCodeDiskSpace)).IsTrue()
}) })
g.It("should create a copy of the file and increment the disk used", func() { g.It("should create a copy of the file and increment the disk used", func() {
@ -503,7 +503,7 @@ func TestFilesystem_Delete(t *testing.T) {
err = fs.Delete("../ext-source.txt") err = fs.Delete("../ext-source.txt")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
g.It("does not allow the deletion of the root directory", func() { g.It("does not allow the deletion of the root directory", func() {

View File

@ -73,22 +73,22 @@ func TestFilesystem_SafePath(t *testing.T) {
g.It("blocks access to files outside the root directory", func() { g.It("blocks access to files outside the root directory", func() {
p, err := fs.SafePath("../test.txt") p, err := fs.SafePath("../test.txt")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
g.Assert(p).Equal("") g.Assert(p).Equal("")
p, err = fs.SafePath("/../test.txt") p, err = fs.SafePath("/../test.txt")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
g.Assert(p).Equal("") g.Assert(p).Equal("")
p, err = fs.SafePath("./foo/../../test.txt") p, err = fs.SafePath("./foo/../../test.txt")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
g.Assert(p).Equal("") g.Assert(p).Equal("")
p, err = fs.SafePath("..") p, err = fs.SafePath("..")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
g.Assert(p).Equal("") g.Assert(p).Equal("")
}) })
}) })
@ -124,7 +124,7 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
err := fs.Readfile("symlinked.txt", &b) err := fs.Readfile("symlinked.txt", &b)
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
}) })
@ -134,7 +134,7 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
err := fs.Writefile("symlinked.txt", r) err := fs.Writefile("symlinked.txt", r)
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
g.It("cannot write a file to a directory symlinked outside the root", func() { g.It("cannot write a file to a directory symlinked outside the root", func() {
@ -142,7 +142,7 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
err := fs.Writefile("external_dir/foo.txt", r) err := fs.Writefile("external_dir/foo.txt", r)
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
}) })
@ -150,19 +150,19 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
g.It("cannot create a directory outside the root", func() { g.It("cannot create a directory outside the root", func() {
err := fs.CreateDirectory("my_dir", "external_dir") err := fs.CreateDirectory("my_dir", "external_dir")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
g.It("cannot create a nested directory outside the root", func() { g.It("cannot create a nested directory outside the root", func() {
err := fs.CreateDirectory("my/nested/dir", "external_dir/foo/bar") err := fs.CreateDirectory("my/nested/dir", "external_dir/foo/bar")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
g.It("cannot create a nested directory outside the root", func() { g.It("cannot create a nested directory outside the root", func() {
err := fs.CreateDirectory("my/nested/dir", "external_dir/server") err := fs.CreateDirectory("my/nested/dir", "external_dir/server")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
}) })
@ -170,13 +170,13 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
g.It("cannot rename a file symlinked outside the directory root", func() { g.It("cannot rename a file symlinked outside the directory root", func() {
err := fs.Rename("symlinked.txt", "foo.txt") err := fs.Rename("symlinked.txt", "foo.txt")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
g.It("cannot rename a symlinked directory outside the root", func() { g.It("cannot rename a symlinked directory outside the root", func() {
err := fs.Rename("external_dir", "foo") err := fs.Rename("external_dir", "foo")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
g.It("cannot rename a file to a location outside the directory root", func() { g.It("cannot rename a file to a location outside the directory root", func() {
@ -184,7 +184,7 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
err := fs.Rename("my_file.txt", "external_dir/my_file.txt") err := fs.Rename("my_file.txt", "external_dir/my_file.txt")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
}) })
@ -192,13 +192,13 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
g.It("cannot chown a file symlinked outside the directory root", func() { g.It("cannot chown a file symlinked outside the directory root", func() {
err := fs.Chown("symlinked.txt") err := fs.Chown("symlinked.txt")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
g.It("cannot chown a directory symlinked outside the directory root", func() { g.It("cannot chown a directory symlinked outside the directory root", func() {
err := fs.Chown("external_dir") err := fs.Chown("external_dir")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
}) })
@ -206,7 +206,7 @@ func TestFilesystem_Blocks_Symlinks(t *testing.T) {
g.It("cannot copy a file symlinked outside the directory root", func() { g.It("cannot copy a file symlinked outside the directory root", func() {
err := fs.Copy("symlinked.txt") err := fs.Copy("symlinked.txt")
g.Assert(err).IsNotNil() g.Assert(err).IsNotNil()
g.Assert(IsBadPathResolutionError(err)).IsTrue() g.Assert(IsErrorCode(err, ErrCodePathResolution)).IsTrue()
}) })
}) })

View File

@ -169,7 +169,7 @@ func (s *Server) onBeforeStart() error {
} else { } else {
s.PublishConsoleOutputFromDaemon("Checking server disk space usage, this could take a few seconds...") s.PublishConsoleOutputFromDaemon("Checking server disk space usage, this could take a few seconds...")
if !s.Filesystem().HasSpaceAvailable(false) { if !s.Filesystem().HasSpaceAvailable(false) {
return filesystem.ErrNotEnoughDiskSpace return filesystem.NewDiskSpaceError()
} }
} }