diff --git a/router/downloader/downloader.go b/router/downloader/downloader.go index 447463f..57aceca 100644 --- a/router/downloader/downloader.go +++ b/router/downloader/downloader.go @@ -66,10 +66,19 @@ func (dl *Download) Execute() error { return errors.New("downloader: failed opening request to download file") } defer res.Body.Close() - if res.StatusCode >= 300 || res.StatusCode < 200 { + if res.StatusCode != http.StatusOK { return errors.New("downloader: got bad response status from endpoint: " + res.Status) } + // If there is a Content-Length header on this request go ahead and check that we can + // even write the whole file before beginning this process. If there is no header present + // we'll just have to give it a spin and see how it goes. + if res.ContentLength > 0 { + if err := dl.server.Filesystem().HasSpaceFor(res.ContentLength); err != nil { + return errors.WrapIf(err, "downloader: failed to write file: not enough space") + } + } + fnameparts := strings.Split(dl.req.URL.Path, "/") p := filepath.Join(dl.req.Directory, fnameparts[len(fnameparts)-1]) dl.server.Log().WithField("path", p).Debug("writing remote file to disk") diff --git a/server/filesystem/compress.go b/server/filesystem/compress.go index 07c7e19..d5f301c 100644 --- a/server/filesystem/compress.go +++ b/server/filesystem/compress.go @@ -150,7 +150,7 @@ func (fs *Filesystem) CompressFiles(dir string, paths []string) (os.FileInfo, er return nil, err } - if err := fs.hasSpaceFor(f.Size()); err != nil { + if err := fs.HasSpaceFor(f.Size()); err != nil { _ = os.Remove(d) return nil, err diff --git a/server/filesystem/disk_space.go b/server/filesystem/disk_space.go index cab4482..ff09c3a 100644 --- a/server/filesystem/disk_space.go +++ b/server/filesystem/disk_space.go @@ -203,7 +203,7 @@ func (fs *Filesystem) DirectorySize(dir string) (int64, error) { // Helper function to determine if a server has space available for a file of a given size. // If space is available, no error will be returned, otherwise an ErrNotEnoughSpace error // will be raised. -func (fs *Filesystem) hasSpaceFor(size int64) error { +func (fs *Filesystem) HasSpaceFor(size int64) error { if fs.MaxDisk() == 0 { return nil } diff --git a/server/filesystem/filesystem.go b/server/filesystem/filesystem.go index 646db9f..a135dbd 100644 --- a/server/filesystem/filesystem.go +++ b/server/filesystem/filesystem.go @@ -86,34 +86,36 @@ func (fs *Filesystem) Writefile(p string, r io.Reader) error { var currentSize int64 // If the file does not exist on the system already go ahead and create the pathway // to it and an empty file. We'll then write to it later on after this completes. - if stat, err := os.Stat(cleaned); err != nil { - if !os.IsNotExist(err) { - return err - } - - if err := os.MkdirAll(filepath.Dir(cleaned), 0755); err != nil { - return err - } - - if err := fs.Chown(filepath.Dir(cleaned)); err != nil { - return err - } - } else { + stat, err := os.Stat(cleaned) + if err != nil && !os.IsNotExist(err) { + return err + } else if err == nil { if stat.IsDir() { return &Error{code: ErrCodeIsDirectory} } - currentSize = stat.Size() } br := bufio.NewReader(r) - // Check that the new size we're writing to the disk can fit. If there is currently a file - // we'll subtract that current file size from the size of the buffer to determine the amount - // of new data we're writing (or amount we're removing if smaller). - if err := fs.hasSpaceFor(int64(br.Size()) - currentSize); err != nil { + // Check that the new size we're writing to the disk can fit. If there is currently + // a file we'll subtract that current file size from the size of the buffer to determine + // the amount of new data we're writing (or amount we're removing if smaller). + if err := fs.HasSpaceFor(int64(br.Size()) - currentSize); err != nil { return err } + // If we were unable to stat the location because it did not exist, go ahead and create + // it now. We do this after checking the disk space so that we do not just create empty + // directories at random. + if err != nil { + if err := os.MkdirAll(filepath.Dir(cleaned), 0755); err != nil { + return err + } + if err := fs.Chown(filepath.Dir(cleaned)); err != nil { + return err + } + } + o := &fileOpener{} // This will either create the file if it does not already exist, or open and // truncate the existing file. @@ -298,7 +300,7 @@ func (fs *Filesystem) Copy(p string) error { } // Check that copying this file wouldn't put the server over its limit. - if err := fs.hasSpaceFor(s.Size()); err != nil { + if err := fs.HasSpaceFor(s.Size()); err != nil { return err }