Replace error handling package with emperror; add better reporting for errors escaping server root

This commit is contained in:
Dane Everitt 2020-11-08 13:52:20 -08:00
parent 0989c78d4b
commit be9d1a3986
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53
55 changed files with 396 additions and 367 deletions

View File

@ -2,10 +2,10 @@ package api
import ( import (
"bytes" "bytes"
"emperror.dev/errors"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/apex/log" "github.com/apex/log"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/system" "github.com/pterodactyl/wings/system"
"io" "io"
@ -69,7 +69,7 @@ func (r *Request) Endpoint(endpoint string) string {
func (r *Request) Make(method, url string, body io.Reader, opts ...func(r *http.Request)) (*Response, error) { func (r *Request) Make(method, url string, body io.Reader, opts ...func(r *http.Request)) (*Response, error) {
req, err := http.NewRequest(method, url, body) req, err := http.NewRequest(method, url, body)
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
req.Header.Set("User-Agent", fmt.Sprintf("Pterodactyl Wings/v%s (id:%s)", system.Version, config.Get().AuthenticationTokenId)) req.Header.Set("User-Agent", fmt.Sprintf("Pterodactyl Wings/v%s (id:%s)", system.Version, config.Get().AuthenticationTokenId))
@ -127,7 +127,7 @@ func (r *Request) Get(url string, data Q) (*Response, error) {
func (r *Request) Post(url string, data interface{}) (*Response, error) { func (r *Request) Post(url string, data interface{}) (*Response, error) {
b, err := json.Marshal(data) b, err := json.Marshal(data)
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
return r.Make(http.MethodPost, r.Endpoint(url), bytes.NewBuffer(b)) return r.Make(http.MethodPost, r.Endpoint(url), bytes.NewBuffer(b))
@ -167,10 +167,10 @@ func (r *Response) Read() ([]byte, error) {
func (r *Response) Bind(v interface{}) error { func (r *Response) Bind(v interface{}) error {
b, err := r.Read() b, err := r.Read()
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return errors.WithStack(json.Unmarshal(b, &v)) return errors.WithStackIf(json.Unmarshal(b, &v))
} }
// Returns the error message from the API call as a string. The error message will be formatted // Returns the error message from the API call as a string. The error message will be formatted

View File

@ -1,8 +1,8 @@
package api package api
import ( import (
"emperror.dev/errors"
"fmt" "fmt"
"github.com/pkg/errors"
"strconv" "strconv"
) )
@ -16,7 +16,7 @@ type BackupRemoteUploadResponse struct {
func (r *Request) GetBackupRemoteUploadURLs(backup string, size int64) (*BackupRemoteUploadResponse, error) { func (r *Request) GetBackupRemoteUploadURLs(backup string, size int64) (*BackupRemoteUploadResponse, error) {
resp, err := r.Get(fmt.Sprintf("/backups/%s", backup), Q{"size": strconv.FormatInt(size, 10)}) resp, err := r.Get(fmt.Sprintf("/backups/%s", backup), Q{"size": strconv.FormatInt(size, 10)})
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
defer resp.Body.Close() defer resp.Body.Close()
@ -26,7 +26,7 @@ func (r *Request) GetBackupRemoteUploadURLs(backup string, size int64) (*BackupR
var res BackupRemoteUploadResponse var res BackupRemoteUploadResponse
if err := resp.Bind(&res); err != nil { if err := resp.Bind(&res); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
return &res, nil return &res, nil
@ -44,7 +44,7 @@ type BackupRequest struct {
func (r *Request) SendBackupStatus(backup string, data BackupRequest) error { func (r *Request) SendBackupStatus(backup string, data BackupRequest) error {
resp, err := r.Post(fmt.Sprintf("/backups/%s", backup), data) resp, err := r.Post(fmt.Sprintf("/backups/%s", backup), data)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
defer resp.Body.Close() defer resp.Body.Close()

View File

@ -2,10 +2,10 @@ package api
import ( import (
"context" "context"
"emperror.dev/errors"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/apex/log" "github.com/apex/log"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"strconv" "strconv"
@ -57,7 +57,7 @@ type RawServerData struct {
func (r *Request) GetServers() ([]RawServerData, error) { func (r *Request) GetServers() ([]RawServerData, error) {
resp, err := r.Get("/servers", Q{"per_page": strconv.Itoa(int(config.Get().RemoteQuery.BootServersPerPage))}) resp, err := r.Get("/servers", Q{"per_page": strconv.Itoa(int(config.Get().RemoteQuery.BootServersPerPage))})
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
defer resp.Body.Close() defer resp.Body.Close()
@ -67,7 +67,7 @@ func (r *Request) GetServers() ([]RawServerData, error) {
var res allServerResponse var res allServerResponse
if err := resp.Bind(&res); err != nil { if err := resp.Bind(&res); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
var mu sync.Mutex var mu sync.Mutex
@ -117,7 +117,7 @@ func (r *Request) GetServers() ([]RawServerData, error) {
} }
if err := g.Wait(); err != nil { if err := g.Wait(); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
} }
@ -130,7 +130,7 @@ func (r *Request) GetServerConfiguration(uuid string) (ServerConfigurationRespon
resp, err := r.Get(fmt.Sprintf("/servers/%s", uuid), nil) resp, err := r.Get(fmt.Sprintf("/servers/%s", uuid), nil)
if err != nil { if err != nil {
return cfg, errors.WithStack(err) return cfg, errors.WithStackIf(err)
} }
defer resp.Body.Close() defer resp.Body.Close()
@ -139,7 +139,7 @@ func (r *Request) GetServerConfiguration(uuid string) (ServerConfigurationRespon
} }
if err := resp.Bind(&cfg); err != nil { if err := resp.Bind(&cfg); err != nil {
return cfg, errors.WithStack(err) return cfg, errors.WithStackIf(err)
} }
return cfg, nil return cfg, nil
@ -150,7 +150,7 @@ func (r *Request) GetInstallationScript(uuid string) (InstallationScript, error)
var is InstallationScript var is InstallationScript
resp, err := r.Get(fmt.Sprintf("/servers/%s/install", uuid), nil) resp, err := r.Get(fmt.Sprintf("/servers/%s/install", uuid), nil)
if err != nil { if err != nil {
return is, errors.WithStack(err) return is, errors.WithStackIf(err)
} }
defer resp.Body.Close() defer resp.Body.Close()
@ -159,7 +159,7 @@ func (r *Request) GetInstallationScript(uuid string) (InstallationScript, error)
} }
if err := resp.Bind(&is); err != nil { if err := resp.Bind(&is); err != nil {
return is, errors.WithStack(err) return is, errors.WithStackIf(err)
} }
return is, nil return is, nil
@ -169,7 +169,7 @@ func (r *Request) GetInstallationScript(uuid string) (InstallationScript, error)
func (r *Request) SendInstallationStatus(uuid string, successful bool) error { func (r *Request) SendInstallationStatus(uuid string, successful bool) error {
resp, err := r.Post(fmt.Sprintf("/servers/%s/install", uuid), D{"successful": successful}) resp, err := r.Post(fmt.Sprintf("/servers/%s/install", uuid), D{"successful": successful})
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
defer resp.Body.Close() defer resp.Body.Close()
@ -183,7 +183,7 @@ func (r *Request) SendInstallationStatus(uuid string, successful bool) error {
func (r *Request) SendArchiveStatus(uuid string, successful bool) error { func (r *Request) SendArchiveStatus(uuid string, successful bool) error {
resp, err := r.Post(fmt.Sprintf("/servers/%s/archive", uuid), D{"successful": successful}) resp, err := r.Post(fmt.Sprintf("/servers/%s/archive", uuid), D{"successful": successful})
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
defer resp.Body.Close() defer resp.Body.Close()
@ -193,7 +193,7 @@ func (r *Request) SendArchiveStatus(uuid string, successful bool) error {
func (r *Request) SendTransferFailure(uuid string) error { func (r *Request) SendTransferFailure(uuid string) error {
resp, err := r.Get(fmt.Sprintf("/servers/%s/transfer/failure", uuid), nil) resp, err := r.Get(fmt.Sprintf("/servers/%s/transfer/failure", uuid), nil)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
defer resp.Body.Close() defer resp.Body.Close()
@ -203,7 +203,7 @@ func (r *Request) SendTransferFailure(uuid string) error {
func (r *Request) SendTransferSuccess(uuid string) error { func (r *Request) SendTransferSuccess(uuid string) error {
resp, err := r.Get(fmt.Sprintf("/servers/%s/transfer/success", uuid), nil) resp, err := r.Get(fmt.Sprintf("/servers/%s/transfer/success", uuid), nil)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
defer resp.Body.Close() defer resp.Body.Close()

View File

@ -1,8 +1,8 @@
package api package api
import ( import (
"emperror.dev/errors"
"github.com/apex/log" "github.com/apex/log"
"github.com/pkg/errors"
"regexp" "regexp"
) )

View File

@ -19,7 +19,7 @@ import (
"github.com/pterodactyl/wings/loggers/cli" "github.com/pterodactyl/wings/loggers/cli"
"golang.org/x/crypto/acme/autocert" "golang.org/x/crypto/acme/autocert"
"github.com/pkg/errors" "emperror.dev/errors"
"github.com/pkg/profile" "github.com/pkg/profile"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
@ -77,7 +77,7 @@ func readConfiguration() (*config.Configuration, error) {
} }
if s, err := os.Stat(p); err != nil { if s, err := os.Stat(p); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} else if s.IsDir() { } else if s.IsDir() {
return nil, errors.New("cannot use directory as configuration file path") return nil, errors.New("cannot use directory as configuration file path")
} }
@ -199,7 +199,7 @@ func rootCmdRun(*cobra.Command, []string) {
states, err := server.CachedServerStates() states, err := server.CachedServerStates()
if err != nil { if err != nil {
log.WithField("error", errors.WithStack(err)).Error("failed to retrieve locally cached server states from disk, assuming all servers in offline state") log.WithField("error", errors.WithStackIf(err)).Error("failed to retrieve locally cached server states from disk, assuming all servers in offline state")
} }
// Create a new workerpool that limits us to 4 servers being bootstrapped at a time // Create a new workerpool that limits us to 4 servers being bootstrapped at a time
@ -235,7 +235,7 @@ func rootCmdRun(*cobra.Command, []string) {
// as a result will result in a slow boot. // as a result will result in a slow boot.
if !r && (st == environment.ProcessRunningState || st == environment.ProcessStartingState) { if !r && (st == environment.ProcessRunningState || st == environment.ProcessStartingState) {
if err := s.HandlePowerAction(server.PowerActionStart); err != nil { if err := s.HandlePowerAction(server.PowerActionStart); err != nil {
s.Log().WithField("error", errors.WithStack(err)).Warn("failed to return server to running state") s.Log().WithField("error", errors.WithStackIf(err)).Warn("failed to return server to running state")
} }
} else if r || (!r && s.IsRunning()) { } else if r || (!r && s.IsRunning()) {
// If the server is currently running on Docker, mark the process as being in that state. // If the server is currently running on Docker, mark the process as being in that state.
@ -248,7 +248,7 @@ func rootCmdRun(*cobra.Command, []string) {
s.Environment.SetState(environment.ProcessRunningState) s.Environment.SetState(environment.ProcessRunningState)
if err := s.Environment.Attach(); err != nil { if err := s.Environment.Attach(); err != nil {
s.Log().WithField("error", errors.WithStack(err)).Warn("failed to attach to running server environment") s.Log().WithField("error", errors.WithStackIf(err)).Warn("failed to attach to running server environment")
} }
return return
@ -369,13 +369,13 @@ func Execute() error {
// in the code without having to pass around a logger instance. // in the code without having to pass around a logger instance.
func configureLogging(logDir string, debug bool) error { func configureLogging(logDir string, debug bool) error {
if err := os.MkdirAll(path.Join(logDir, "/install"), 0700); err != nil { if err := os.MkdirAll(path.Join(logDir, "/install"), 0700); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
p := filepath.Join(logDir, "/wings.log") p := filepath.Join(logDir, "/wings.log")
w, err := logrotate.NewFile(p) w, err := logrotate.NewFile(p)
if err != nil { if err != nil {
panic(errors.Wrap(err, "failed to open process log file")) panic(errors.WrapIf(err, "failed to open process log file"))
} }
if debug { if debug {

View File

@ -1,11 +1,11 @@
package config package config
import ( import (
"emperror.dev/errors"
"fmt" "fmt"
"github.com/cobaugh/osrelease" "github.com/cobaugh/osrelease"
"github.com/creasty/defaults" "github.com/creasty/defaults"
"github.com/gbrlsnchs/jwt/v3" "github.com/gbrlsnchs/jwt/v3"
"github.com/pkg/errors"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
"io/ioutil" "io/ioutil"
"os" "os"
@ -198,7 +198,7 @@ func GetJwtAlgorithm() *jwt.HMACSHA {
func NewFromPath(path string) (*Configuration, error) { func NewFromPath(path string) (*Configuration, error) {
c := new(Configuration) c := new(Configuration)
if err := defaults.Set(c); err != nil { if err := defaults.Set(c); err != nil {
return c, errors.WithStack(err) return c, errors.WithStackIf(err)
} }
c.unsafeSetPath(path) c.unsafeSetPath(path)
@ -236,12 +236,12 @@ func (c *Configuration) EnsurePterodactylUser() (*user.User, error) {
if err == nil { if err == nil {
return u, c.setSystemUser(u) return u, c.setSystemUser(u)
} else if _, ok := err.(user.UnknownUserError); !ok { } else if _, ok := err.(user.UnknownUserError); !ok {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
sysName, err := getSystemName() sysName, err := getSystemName()
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
var command = fmt.Sprintf("useradd --system --no-create-home --shell /bin/false %s", c.System.Username) var command = fmt.Sprintf("useradd --system --no-create-home --shell /bin/false %s", c.System.Username)
@ -254,17 +254,17 @@ func (c *Configuration) EnsurePterodactylUser() (*user.User, error) {
// We have to create the group first on Alpine, so do that here before continuing on // We have to create the group first on Alpine, so do that here before continuing on
// to the user creation process. // to the user creation process.
if _, err := exec.Command("addgroup", "-S", c.System.Username).Output(); err != nil { if _, err := exec.Command("addgroup", "-S", c.System.Username).Output(); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
} }
split := strings.Split(command, " ") split := strings.Split(command, " ")
if _, err := exec.Command(split[0], split[1:]...).Output(); err != nil { if _, err := exec.Command(split[0], split[1:]...).Output(); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
if u, err := user.Lookup(c.System.Username); err != nil { if u, err := user.Lookup(c.System.Username); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} else { } else {
return u, c.setSystemUser(u) return u, c.setSystemUser(u)
} }
@ -306,11 +306,11 @@ func (c *Configuration) WriteToDisk() error {
b, err := yaml.Marshal(&ccopy) b, err := yaml.Marshal(&ccopy)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
if err := ioutil.WriteFile(c.GetPath(), b, 0644); err != nil { if err := ioutil.WriteFile(c.GetPath(), b, 0644); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return nil return nil
@ -320,7 +320,7 @@ func (c *Configuration) WriteToDisk() error {
func getSystemName() (string, error) { func getSystemName() (string, error) {
// use osrelease to get release version and ID // use osrelease to get release version and ID
if release, err := osrelease.Read(); err != nil { if release, err := osrelease.Read(); err != nil {
return "", errors.WithStack(err) return "", errors.WithStackIf(err)
} else { } else {
return release["ID"], nil return release["ID"], nil
} }

View File

@ -1,10 +1,10 @@
package config package config
import ( import (
"emperror.dev/errors"
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/pkg/errors"
) )
type dockerNetworkInterfaces struct { type dockerNetworkInterfaces struct {
@ -73,7 +73,7 @@ func (c RegistryConfiguration) Base64() (string, error) {
b, err := json.Marshal(authConfig) b, err := json.Marshal(authConfig)
if err != nil { if err != nil {
return "", errors.WithStack(err) return "", errors.WithStackIf(err)
} }
return base64.URLEncoding.EncodeToString(b), nil return base64.URLEncoding.EncodeToString(b), nil

View File

@ -2,9 +2,9 @@ package config
import ( import (
"context" "context"
"emperror.dev/errors"
"fmt" "fmt"
"github.com/apex/log" "github.com/apex/log"
"github.com/pkg/errors"
"html/template" "html/template"
"io/ioutil" "io/ioutil"
"os" "os"
@ -94,7 +94,7 @@ func (sc *SystemConfiguration) ConfigureDirectories() error {
// that. // that.
if d, err := filepath.EvalSymlinks(sc.Data); err != nil { if d, err := filepath.EvalSymlinks(sc.Data); err != nil {
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
} else if d != sc.Data { } else if d != sc.Data {
sc.Data = d sc.Data = d
@ -130,13 +130,13 @@ func (sc *SystemConfiguration) EnableLogRotation() error {
} }
if st, err := os.Stat("/etc/logrotate.d"); err != nil && !os.IsNotExist(err) { if st, err := os.Stat("/etc/logrotate.d"); err != nil && !os.IsNotExist(err) {
return errors.WithStack(err) return errors.WithStackIf(err)
} else if (err != nil && os.IsNotExist(err)) || !st.IsDir() { } else if (err != nil && os.IsNotExist(err)) || !st.IsDir() {
return nil return nil
} }
if _, err := os.Stat("/etc/logrotate.d/wings"); err != nil && !os.IsNotExist(err) { if _, err := os.Stat("/etc/logrotate.d/wings"); err != nil && !os.IsNotExist(err) {
return errors.WithStack(err) return errors.WithStackIf(err)
} else if err == nil { } else if err == nil {
return nil return nil
} }
@ -147,7 +147,7 @@ func (sc *SystemConfiguration) EnableLogRotation() error {
// it so files can be rotated easily. // it so files can be rotated easily.
f, err := os.Create("/etc/logrotate.d/wings") f, err := os.Create("/etc/logrotate.d/wings")
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
defer f.Close() defer f.Close()
@ -167,10 +167,10 @@ func (sc *SystemConfiguration) EnableLogRotation() error {
}`) }`)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return errors.Wrap(t.Execute(f, sc), "failed to write logrotate file to disk") return errors.WrapIf(t.Execute(f, sc), "failed to write logrotate file to disk")
} }
// Returns the location of the JSON file that tracks server states. // Returns the location of the JSON file that tracks server states.
@ -190,7 +190,7 @@ func (sc *SystemConfiguration) ConfigureTimezone() error {
if sc.Timezone == "" { if sc.Timezone == "" {
if b, err := ioutil.ReadFile("/etc/timezone"); err != nil { if b, err := ioutil.ReadFile("/etc/timezone"); err != nil {
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
return errors.Wrap(err, "failed to open /etc/timezone for automatic server timezone calibration") return errors.WrapIf(err, "failed to open /etc/timezone for automatic server timezone calibration")
} }
ctx, _ := context.WithTimeout(context.Background(), time.Second*5) ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
@ -224,5 +224,5 @@ func (sc *SystemConfiguration) ConfigureTimezone() error {
_, err := time.LoadLocation(sc.Timezone) _, err := time.LoadLocation(sc.Timezone)
return errors.Wrap(err, fmt.Sprintf("the supplied timezone %s is invalid", sc.Timezone)) return errors.WrapIf(err, fmt.Sprintf("the supplied timezone %s is invalid", sc.Timezone))
} }

View File

@ -4,6 +4,7 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"context" "context"
"emperror.dev/errors"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/apex/log" "github.com/apex/log"
@ -12,7 +13,6 @@ import (
"github.com/docker/docker/api/types/mount" "github.com/docker/docker/api/types/mount"
"github.com/docker/docker/client" "github.com/docker/docker/client"
"github.com/docker/docker/daemon/logger/jsonfilelog" "github.com/docker/docker/daemon/logger/jsonfilelog"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
"io" "io"
@ -36,7 +36,7 @@ func (e *Environment) Attach() error {
} }
if err := e.followOutput(); err != nil { if err := e.followOutput(); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
opts := types.ContainerAttachOptions{ opts := types.ContainerAttachOptions{
@ -48,7 +48,7 @@ func (e *Environment) Attach() error {
// Set the stream again with the container. // Set the stream again with the container.
if st, err := e.client.ContainerAttach(context.Background(), e.Id, opts); err != nil { if st, err := e.client.ContainerAttach(context.Background(), e.Id, opts); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} else { } else {
e.SetStream(&st) e.SetStream(&st)
} }
@ -70,14 +70,14 @@ func (e *Environment) Attach() error {
// indicates that the container is no longer running. // indicates that the container is no longer running.
go func(ctx context.Context) { go func(ctx context.Context) {
if err := e.pollResources(ctx); err != nil { if err := e.pollResources(ctx); err != nil {
log.WithField("environment_id", e.Id).WithField("error", errors.WithStack(err)).Error("error during environment resource polling") log.WithField("environment_id", e.Id).WithField("error", errors.WithStackIf(err)).Error("error during environment resource polling")
} }
}(ctx) }(ctx)
// Stream the reader output to the console which will then fire off events and handle console // Stream the reader output to the console which will then fire off events and handle console
// throttling and sending the output to the user. // throttling and sending the output to the user.
if _, err := io.Copy(console, e.stream.Reader); err != nil { if _, err := io.Copy(console, e.stream.Reader); err != nil {
log.WithField("environment_id", e.Id).WithField("error", errors.WithStack(err)).Error("error while copying environment output to console") log.WithField("environment_id", e.Id).WithField("error", errors.WithStackIf(err)).Error("error while copying environment output to console")
} }
}(c) }(c)
@ -115,7 +115,7 @@ func (e *Environment) InSituUpdate() error {
return nil return nil
} }
return errors.WithStack(err) return errors.WithStackIf(err)
} }
u := container.UpdateConfig{ u := container.UpdateConfig{
@ -125,7 +125,7 @@ func (e *Environment) InSituUpdate() error {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel() defer cancel()
if _, err := e.client.ContainerUpdate(ctx, e.Id, u); err != nil { if _, err := e.client.ContainerUpdate(ctx, e.Id, u); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return nil return nil
@ -140,12 +140,12 @@ func (e *Environment) Create() error {
if _, err := e.client.ContainerInspect(context.Background(), e.Id); err == nil { if _, err := e.client.ContainerInspect(context.Background(), e.Id); err == nil {
return nil return nil
} else if !client.IsErrNotFound(err) { } else if !client.IsErrNotFound(err) {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// Try to pull the requested image before creating the container. // Try to pull the requested image before creating the container.
if err := e.ensureImageExists(e.meta.Image); err != nil { if err := e.ensureImageExists(e.meta.Image); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
a := e.Configuration.Allocations() a := e.Configuration.Allocations()
@ -220,7 +220,7 @@ func (e *Environment) Create() error {
} }
if _, err := e.client.ContainerCreate(context.Background(), conf, hostConf, nil, e.Id); err != nil { if _, err := e.client.ContainerCreate(context.Background(), conf, hostConf, nil, e.Id); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return nil return nil
@ -272,7 +272,7 @@ func (e *Environment) Destroy() error {
func (e *Environment) followOutput() error { func (e *Environment) followOutput() error {
if exists, err := e.Exists(); !exists { if exists, err := e.Exists(); !exists {
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return errors.New(fmt.Sprintf("no such container: %s", e.Id)) return errors.New(fmt.Sprintf("no such container: %s", e.Id))
@ -338,7 +338,7 @@ func (e *Environment) followOutput() error {
} }
}(reader) }(reader)
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// Pulls the image from Docker. If there is an error while pulling the image from the source // Pulls the image from Docker. If there is an error while pulling the image from the source

View File

@ -2,9 +2,9 @@ package docker
import ( import (
"context" "context"
"emperror.dev/errors"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/client" "github.com/docker/docker/client"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api" "github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
"github.com/pterodactyl/wings/events" "github.com/pterodactyl/wings/events"
@ -156,7 +156,7 @@ func (e *Environment) ExitState() (uint32, bool, error) {
return 1, false, nil return 1, false, nil
} }
return 0, false, errors.WithStack(err) return 0, false, errors.WithStackIf(err)
} }
return uint32(c.State.ExitCode), c.State.OOMKilled, nil return uint32(c.State.ExitCode), c.State.OOMKilled, nil

View File

@ -2,11 +2,11 @@ package docker
import ( import (
"context" "context"
"emperror.dev/errors"
"github.com/apex/log" "github.com/apex/log"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/client" "github.com/docker/docker/client"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api" "github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
"os" "os"
@ -26,7 +26,7 @@ func (e *Environment) OnBeforeStart() error {
// the Panel is usee. // the Panel is usee.
if err := e.client.ContainerRemove(context.Background(), e.Id, types.ContainerRemoveOptions{RemoveVolumes: true}); err != nil { if err := e.client.ContainerRemove(context.Background(), e.Id, types.ContainerRemoveOptions{RemoveVolumes: true}); err != nil {
if !client.IsErrNotFound(err) { if !client.IsErrNotFound(err) {
return errors.Wrap(err, "failed to remove server docker container during pre-boot") return errors.WrapIf(err, "failed to remove server docker container during pre-boot")
} }
} }
@ -69,7 +69,7 @@ func (e *Environment) Start() error {
// //
// @see https://github.com/pterodactyl/panel/issues/2000 // @see https://github.com/pterodactyl/panel/issues/2000
if !client.IsErrNotFound(err) { if !client.IsErrNotFound(err) {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
} else { } else {
// If the server is running update our internal state and continue on with the attach. // If the server is running update our internal state and continue on with the attach.
@ -84,7 +84,7 @@ func (e *Environment) Start() error {
// to truncate them. // to truncate them.
if _, err := os.Stat(c.LogPath); err == nil { if _, err := os.Stat(c.LogPath); err == nil {
if err := os.Truncate(c.LogPath, 0); err != nil { if err := os.Truncate(c.LogPath, 0); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
} }
} }
@ -99,14 +99,14 @@ func (e *Environment) Start() error {
// exists on the system, and rebuild the container if that is required for server booting to // exists on the system, and rebuild the container if that is required for server booting to
// occur. // occur.
if err := e.OnBeforeStart(); err != nil { if err := e.OnBeforeStart(); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel() defer cancel()
if err := e.client.ContainerStart(ctx, e.Id, types.ContainerStartOptions{}); err != nil { if err := e.client.ContainerStart(ctx, e.Id, types.ContainerStartOptions{}); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// No errors, good to continue through. // No errors, good to continue through.
@ -169,7 +169,7 @@ func (e *Environment) Stop() error {
// will be terminated forcefully depending on the value of the second argument. // will be terminated forcefully depending on the value of the second argument.
func (e *Environment) WaitForStop(seconds uint, terminate bool) error { func (e *Environment) WaitForStop(seconds uint, terminate bool) error {
if err := e.Stop(); err != nil { if err := e.Stop(); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(seconds)*time.Second) ctx, cancel := context.WithTimeout(context.Background(), time.Duration(seconds)*time.Second)
@ -185,20 +185,20 @@ func (e *Environment) WaitForStop(seconds uint, terminate bool) error {
if terminate { if terminate {
log.WithField("container_id", e.Id).Debug("server did not stop in time, executing process termination") log.WithField("container_id", e.Id).Debug("server did not stop in time, executing process termination")
return errors.WithStack(e.Terminate(os.Kill)) return errors.WithStackIf(e.Terminate(os.Kill))
} }
return errors.WithStack(ctxErr) return errors.WithStackIf(ctxErr)
} }
case err := <-errChan: case err := <-errChan:
if err != nil { if err != nil {
if terminate { if terminate {
log.WithField("container_id", e.Id).WithField("error", errors.WithStack(err)).Warn("error while waiting for container stop, attempting process termination") log.WithField("container_id", e.Id).WithField("error", errors.WithStackIf(err)).Warn("error while waiting for container stop, attempting process termination")
return errors.WithStack(e.Terminate(os.Kill)) return errors.WithStackIf(e.Terminate(os.Kill))
} }
return errors.WithStack(err) return errors.WithStackIf(err)
} }
case <-ok: case <-ok:
} }
@ -210,7 +210,7 @@ func (e *Environment) WaitForStop(seconds uint, terminate bool) error {
func (e *Environment) Terminate(signal os.Signal) error { func (e *Environment) Terminate(signal os.Signal) error {
c, err := e.client.ContainerInspect(context.Background(), e.Id) c, err := e.client.ContainerInspect(context.Background(), e.Id)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
if !c.State.Running { if !c.State.Running {

View File

@ -1,8 +1,8 @@
package docker package docker
import ( import (
"emperror.dev/errors"
"fmt" "fmt"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
) )

View File

@ -2,10 +2,10 @@ package docker
import ( import (
"context" "context"
"emperror.dev/errors"
"encoding/json" "encoding/json"
"github.com/apex/log" "github.com/apex/log"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
"io" "io"
"math" "math"
@ -26,7 +26,7 @@ func (e *Environment) pollResources(ctx context.Context) error {
stats, err := e.client.ContainerStats(context.Background(), e.Id, true) stats, err := e.client.ContainerStats(context.Background(), e.Id, true)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
defer stats.Body.Close() defer stats.Body.Close()
@ -41,7 +41,7 @@ func (e *Environment) pollResources(ctx context.Context) error {
if err := dec.Decode(&v); err != nil { if err := dec.Decode(&v); err != nil {
if err != io.EOF { if err != io.EOF {
l.WithField("error", errors.WithStack(err)).Warn("error while processing Docker stats output for container") l.WithField("error", errors.WithStackIf(err)).Warn("error while processing Docker stats output for container")
} else { } else {
l.Debug("io.EOF encountered during stats decode, stopping polling...") l.Debug("io.EOF encountered during stats decode, stopping polling...")
} }
@ -76,7 +76,7 @@ func (e *Environment) pollResources(ctx context.Context) error {
} }
if b, err := json.Marshal(st); err != nil { if b, err := json.Marshal(st); err != nil {
l.WithField("error", errors.WithStack(err)).Warn("error while marshaling stats object for environment") l.WithField("error", errors.WithStackIf(err)).Warn("error while marshaling stats object for environment")
} else { } else {
e.Events().Publish(environment.ResourceEvent, string(b)) e.Events().Publish(environment.ResourceEvent, string(b))
} }

View File

@ -4,9 +4,9 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"context" "context"
"emperror.dev/errors"
"encoding/json" "encoding/json"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
"strconv" "strconv"
) )
@ -15,7 +15,7 @@ type dockerLogLine struct {
Log string `json:"log"` Log string `json:"log"`
} }
var ErrNotAttached = errors.New("not attached to instance") var ErrNotAttached = errors.Sentinel("not attached to instance")
func (e *Environment) setStream(s *types.HijackedResponse) { func (e *Environment) setStream(s *types.HijackedResponse) {
e.mu.Lock() e.mu.Lock()
@ -42,7 +42,7 @@ func (e *Environment) SendCommand(c string) error {
_, err := e.stream.Conn.Write([]byte(c + "\n")) _, err := e.stream.Conn.Write([]byte(c + "\n"))
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// Reads the log file for the server. This does not care if the server is running or not, it will // Reads the log file for the server. This does not care if the server is running or not, it will
@ -54,7 +54,7 @@ func (e *Environment) Readlog(lines int) ([]string, error) {
Tail: strconv.Itoa(lines), Tail: strconv.Itoa(lines),
}) })
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
defer r.Close() defer r.Close()

View File

@ -1,9 +1,9 @@
package events package events
import ( import (
"emperror.dev/errors"
"encoding/json" "encoding/json"
"github.com/gammazero/workerpool" "github.com/gammazero/workerpool"
"github.com/pkg/errors"
"strings" "strings"
"sync" "sync"
) )
@ -69,7 +69,7 @@ func (e *EventBus) Publish(topic string, data string) {
func (e *EventBus) PublishJson(topic string, data interface{}) error { func (e *EventBus) PublishJson(topic string, data interface{}) error {
b, err := json.Marshal(data) b, err := json.Marshal(data)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
e.Publish(topic, string(b)) e.Publish(topic, string(b))

2
go.mod
View File

@ -3,6 +3,7 @@ module github.com/pterodactyl/wings
go 1.13 go 1.13
require ( require (
emperror.dev/errors v0.8.0
github.com/AlecAivazis/survey/v2 v2.1.0 github.com/AlecAivazis/survey/v2 v2.1.0
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
github.com/Jeffail/gabs/v2 v2.5.1 github.com/Jeffail/gabs/v2 v2.5.1
@ -57,7 +58,6 @@ require (
github.com/opencontainers/image-spec v1.0.1 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pierrec/lz4 v2.5.2+incompatible // indirect github.com/pierrec/lz4 v2.5.2+incompatible // indirect
github.com/pkg/errors v0.9.1
github.com/pkg/profile v1.5.0 github.com/pkg/profile v1.5.0
github.com/pkg/sftp v1.11.0 github.com/pkg/sftp v1.11.0
github.com/prometheus/common v0.11.1 // indirect github.com/prometheus/common v0.11.1 // indirect

6
go.sum
View File

@ -1,5 +1,7 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
emperror.dev/errors v0.8.0 h1:4lycVEx0sdJkwDUfQ9pdu6SR0x7rgympt5f4+ok8jDk=
emperror.dev/errors v0.8.0/go.mod h1:YcRvLPh626Ubn2xqtoprejnA5nFha+TJ+2vew48kWuE=
github.com/AlecAivazis/survey/v2 v2.1.0 h1:AT4+23hOFopXYZaNGugbk7MWItkz0SfTmH/Hk92KeeE= github.com/AlecAivazis/survey/v2 v2.1.0 h1:AT4+23hOFopXYZaNGugbk7MWItkz0SfTmH/Hk92KeeE=
github.com/AlecAivazis/survey/v2 v2.1.0/go.mod h1:9FJRdMdDm8rnT+zHVbvQT2RTSTLq0Ttd6q3Vl2fahjk= github.com/AlecAivazis/survey/v2 v2.1.0/go.mod h1:9FJRdMdDm8rnT+zHVbvQT2RTSTLq0Ttd6q3Vl2fahjk=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
@ -561,9 +563,13 @@ go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=

View File

@ -1,10 +1,10 @@
package installer package installer
import ( import (
"emperror.dev/errors"
"encoding/json" "encoding/json"
"github.com/asaskevich/govalidator" "github.com/asaskevich/govalidator"
"github.com/buger/jsonparser" "github.com/buger/jsonparser"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api" "github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
"github.com/pterodactyl/wings/server" "github.com/pterodactyl/wings/server"
@ -43,21 +43,21 @@ func New(data []byte) (*Installer, error) {
// Unmarshal the environment variables from the request into the server struct. // Unmarshal the environment variables from the request into the server struct.
if b, _, _, err := jsonparser.Get(data, "environment"); err != nil { if b, _, _, err := jsonparser.Get(data, "environment"); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} else { } else {
cfg.EnvVars = make(environment.Variables) cfg.EnvVars = make(environment.Variables)
if err := json.Unmarshal(b, &cfg.EnvVars); err != nil { if err := json.Unmarshal(b, &cfg.EnvVars); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
} }
// Unmarshal the allocation mappings from the request into the server struct. // Unmarshal the allocation mappings from the request into the server struct.
if b, _, _, err := jsonparser.Get(data, "allocations", "mappings"); err != nil { if b, _, _, err := jsonparser.Get(data, "allocations", "mappings"); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} else { } else {
cfg.Allocations.Mappings = make(map[string][]int) cfg.Allocations.Mappings = make(map[string][]int)
if err := json.Unmarshal(b, &cfg.Allocations.Mappings); err != nil { if err := json.Unmarshal(b, &cfg.Allocations.Mappings); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
} }
@ -66,7 +66,7 @@ func New(data []byte) (*Installer, error) {
c, err := api.New().GetServerConfiguration(cfg.Uuid) c, err := api.New().GetServerConfiguration(cfg.Uuid)
if err != nil { if err != nil {
if !api.IsRequestError(err) { if !api.IsRequestError(err) {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
return nil, errors.New(err.Error()) return nil, errors.New(err.Error())

View File

@ -6,7 +6,7 @@ import (
"github.com/apex/log/handlers/cli" "github.com/apex/log/handlers/cli"
color2 "github.com/fatih/color" color2 "github.com/fatih/color"
"github.com/mattn/go-colorable" "github.com/mattn/go-colorable"
"github.com/pkg/errors" "emperror.dev/errors"
"io" "io"
"os" "os"
"sync" "sync"
@ -88,10 +88,10 @@ func getErrorStack(err error, i bool) errors.StackTrace {
if i { if i {
// Just abort out of this and return a stacktrace leading up to this point. It isn't perfect // Just abort out of this and return a stacktrace leading up to this point. It isn't perfect
// but it'll at least include what function lead to this being called which we can then handle. // but it'll at least include what function lead to this being called which we can then handle.
return errors.Wrap(err, "failed to generate stacktrace for caught error").(tracer).StackTrace() return errors.WrapIf(err, "failed to generate stacktrace for caught error").(tracer).StackTrace()
} }
return getErrorStack(errors.Wrap(err, err.Error()), true) return getErrorStack(errors.WrapIf(err, err.Error()), true)
} }
st := e.StackTrace() st := e.StackTrace()
@ -101,7 +101,7 @@ func getErrorStack(err error, i bool) errors.StackTrace {
// trace since they'll point to the error that was generated by this function. // trace since they'll point to the error that was generated by this function.
f := 0 f := 0
if i { if i {
f = 4 f = 5
} }
if i && l > 9 { if i && l > 9 {

View File

@ -2,11 +2,11 @@ package parser
import ( import (
"bytes" "bytes"
"emperror.dev/errors"
"github.com/Jeffail/gabs/v2" "github.com/Jeffail/gabs/v2"
"github.com/apex/log" "github.com/apex/log"
"github.com/buger/jsonparser" "github.com/buger/jsonparser"
"github.com/iancoleman/strcase" "github.com/iancoleman/strcase"
"github.com/pkg/errors"
"io/ioutil" "io/ioutil"
"os" "os"
"regexp" "regexp"
@ -76,13 +76,13 @@ func (cfr *ConfigurationFileReplacement) getKeyValue(value []byte) interface{} {
func (f *ConfigurationFile) IterateOverJson(data []byte) (*gabs.Container, error) { func (f *ConfigurationFile) IterateOverJson(data []byte) (*gabs.Container, error) {
parsed, err := gabs.ParseJSON(data) parsed, err := gabs.ParseJSON(data)
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
for _, v := range f.Replace { for _, v := range f.Replace {
value, err := f.LookupConfigurationValue(v) value, err := f.LookupConfigurationValue(v)
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
// Check for a wildcard character, and if found split the key on that value to // Check for a wildcard character, and if found split the key on that value to
@ -101,7 +101,7 @@ func (f *ConfigurationFile) IterateOverJson(data []byte) (*gabs.Container, error
continue continue
} }
return nil, errors.Wrap(err, "failed to set config value of array child") return nil, errors.WrapIf(err, "failed to set config value of array child")
} }
} }
} else { } else {
@ -110,7 +110,7 @@ func (f *ConfigurationFile) IterateOverJson(data []byte) (*gabs.Container, error
continue continue
} }
return nil, errors.Wrap(err, "unable to set config value at pathway: "+v.Match) return nil, errors.WrapIf(err, "unable to set config value at pathway: "+v.Match)
} }
} }
} }
@ -138,7 +138,7 @@ func setValueAtPath(c *gabs.Container, path string, value interface{}) error {
_, err = c.SetP(value, path) _, err = c.SetP(value, path)
} }
return errors.WithStack(err) return errors.WithStackIf(err)
} }
i, _ := strconv.Atoi(matches[2]) i, _ := strconv.Atoi(matches[2])
@ -147,7 +147,7 @@ func setValueAtPath(c *gabs.Container, path string, value interface{}) error {
ct, err := c.ArrayElementP(i, matches[1]) ct, err := c.ArrayElementP(i, matches[1])
if err != nil { if err != nil {
if i != 0 || (!errors.Is(err, gabs.ErrNotArray) && !errors.Is(err, gabs.ErrNotFound)) { if i != 0 || (!errors.Is(err, gabs.ErrNotArray) && !errors.Is(err, gabs.ErrNotFound)) {
return errors.Wrap(err, "error while parsing array element at path") return errors.WrapIf(err, "error while parsing array element at path")
} }
var t = make([]interface{}, 1) var t = make([]interface{}, 1)
@ -162,7 +162,7 @@ func setValueAtPath(c *gabs.Container, path string, value interface{}) error {
// an empty object if we have additional things to set on the array, or just an empty array type // an empty object if we have additional things to set on the array, or just an empty array type
// if there is not an object structure detected (no matches[3] available). // if there is not an object structure detected (no matches[3] available).
if _, err = c.SetP(t, matches[1]); err != nil { if _, err = c.SetP(t, matches[1]); err != nil {
return errors.Wrap(err, "failed to create empty array for missing element") return errors.WrapIf(err, "failed to create empty array for missing element")
} }
// Set our cursor to be the array element we expect, which in this case is just the first element // Set our cursor to be the array element we expect, which in this case is just the first element
@ -170,7 +170,7 @@ func setValueAtPath(c *gabs.Container, path string, value interface{}) error {
// to match additional elements. In those cases the server will just have to be rebooted or something. // to match additional elements. In those cases the server will just have to be rebooted or something.
ct, err = c.ArrayElementP(0, matches[1]) ct, err = c.ArrayElementP(0, matches[1])
if err != nil { if err != nil {
return errors.Wrap(err, "failed to find array element at path") return errors.WrapIf(err, "failed to find array element at path")
} }
} }
@ -187,7 +187,7 @@ func setValueAtPath(c *gabs.Container, path string, value interface{}) error {
} }
if err != nil { if err != nil {
return errors.Wrap(err, "failed to set value at config path: "+path) return errors.WrapIf(err, "failed to set value at config path: "+path)
} }
return nil return nil
@ -253,7 +253,7 @@ func (f *ConfigurationFile) LookupConfigurationValue(cfr ConfigurationFileReplac
match, _, _, err := jsonparser.Get(f.configuration, path...) match, _, _, err := jsonparser.Get(f.configuration, path...)
if err != nil { if err != nil {
if err != jsonparser.KeyPathNotFoundError { if err != jsonparser.KeyPathNotFoundError {
return string(match), errors.WithStack(err) return string(match), errors.WithStackIf(err)
} }
log.WithFields(log.Fields{"path": path, "filename": f.FileName}).Debug("attempted to load a configuration value that does not exist") log.WithFields(log.Fields{"path": path, "filename": f.FileName}).Debug("attempted to load a configuration value that does not exist")

View File

@ -2,13 +2,13 @@ package parser
import ( import (
"bufio" "bufio"
"emperror.dev/errors"
"encoding/json" "encoding/json"
"github.com/apex/log" "github.com/apex/log"
"github.com/beevik/etree" "github.com/beevik/etree"
"github.com/buger/jsonparser" "github.com/buger/jsonparser"
"github.com/icza/dyno" "github.com/icza/dyno"
"github.com/magiconair/properties" "github.com/magiconair/properties"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"gopkg.in/ini.v1" "gopkg.in/ini.v1"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
@ -166,17 +166,17 @@ func (f *ConfigurationFile) Parse(path string, internal bool) error {
b := strings.TrimSuffix(path, filepath.Base(path)) b := strings.TrimSuffix(path, filepath.Base(path))
if err := os.MkdirAll(b, 0755); err != nil { if err := os.MkdirAll(b, 0755); err != nil {
return errors.Wrap(err, "failed to create base directory for missing configuration file") return errors.WrapIf(err, "failed to create base directory for missing configuration file")
} else { } else {
if _, err := os.Create(path); err != nil { if _, err := os.Create(path); err != nil {
return errors.Wrap(err, "failed to create missing configuration file") return errors.WrapIf(err, "failed to create missing configuration file")
} }
} }
return f.Parse(path, true) return f.Parse(path, true)
} }
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// Parses an xml file. // Parses an xml file.
@ -348,12 +348,12 @@ func (f *ConfigurationFile) parseJsonFile(path string) error {
func (f *ConfigurationFile) parseYamlFile(path string) error { func (f *ConfigurationFile) parseYamlFile(path string) error {
b, err := readFileBytes(path) b, err := readFileBytes(path)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
i := make(map[string]interface{}) i := make(map[string]interface{})
if err := yaml.Unmarshal(b, &i); err != nil { if err := yaml.Unmarshal(b, &i); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// Unmarshal the yaml data into a JSON interface such that we can work with // Unmarshal the yaml data into a JSON interface such that we can work with
@ -361,20 +361,20 @@ func (f *ConfigurationFile) parseYamlFile(path string) error {
// makes working with unknown JSON significantly easier. // makes working with unknown JSON significantly easier.
jsonBytes, err := json.Marshal(dyno.ConvertMapI2MapS(i)) jsonBytes, err := json.Marshal(dyno.ConvertMapI2MapS(i))
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// Now that the data is converted, treat it just like JSON and pass it to the // Now that the data is converted, treat it just like JSON and pass it to the
// iterator function to update values as necessary. // iterator function to update values as necessary.
data, err := f.IterateOverJson(jsonBytes) data, err := f.IterateOverJson(jsonBytes)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// Remarshal the JSON into YAML format before saving it back to the disk. // Remarshal the JSON into YAML format before saving it back to the disk.
marshaled, err := yaml.Marshal(data.Data()) marshaled, err := yaml.Marshal(data.Data())
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return ioutil.WriteFile(path, marshaled, 0644) return ioutil.WriteFile(path, marshaled, 0644)
@ -386,7 +386,7 @@ func (f *ConfigurationFile) parseYamlFile(path string) error {
func (f *ConfigurationFile) parseTextFile(path string) error { func (f *ConfigurationFile) parseTextFile(path string) error {
input, err := ioutil.ReadFile(path) input, err := ioutil.ReadFile(path)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
lines := strings.Split(string(input), "\n") lines := strings.Split(string(input), "\n")
@ -403,7 +403,7 @@ func (f *ConfigurationFile) parseTextFile(path string) error {
} }
if err := ioutil.WriteFile(path, []byte(strings.Join(lines, "\n")), 0644); err != nil { if err := ioutil.WriteFile(path, []byte(strings.Join(lines, "\n")), 0644); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return nil return nil
@ -415,7 +415,7 @@ func (f *ConfigurationFile) parsePropertiesFile(path string) error {
// Open the file. // Open the file.
f2, err := os.Open(path) f2, err := os.Open(path)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
var s strings.Builder var s strings.Builder
@ -437,20 +437,20 @@ func (f *ConfigurationFile) parsePropertiesFile(path string) error {
// Handle any scanner errors. // Handle any scanner errors.
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// Decode the properties file. // Decode the properties file.
p, err := properties.LoadFile(path, properties.UTF8) p, err := properties.LoadFile(path, properties.UTF8)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// Replace any values that need to be replaced. // Replace any values that need to be replaced.
for _, replace := range f.Replace { for _, replace := range f.Replace {
data, err := f.LookupConfigurationValue(replace) data, err := f.LookupConfigurationValue(replace)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
v, ok := p.Get(replace.Match) v, ok := p.Get(replace.Match)
@ -462,7 +462,7 @@ func (f *ConfigurationFile) parsePropertiesFile(path string) error {
} }
if _, _, err := p.Set(replace.Match, data); err != nil { if _, _, err := p.Set(replace.Match, data); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
} }
@ -482,7 +482,7 @@ func (f *ConfigurationFile) parsePropertiesFile(path string) error {
// Open the file for writing. // Open the file for writing.
w, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) w, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
defer w.Close() defer w.Close()

View File

@ -1,11 +1,11 @@
package router package router
import ( import (
"emperror.dev/errors"
"fmt" "fmt"
"github.com/apex/log" "github.com/apex/log"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/server" "github.com/pterodactyl/wings/server"
"github.com/pterodactyl/wings/server/filesystem" "github.com/pterodactyl/wings/server/filesystem"
"net/http" "net/http"
@ -75,7 +75,7 @@ func (e *RequestError) AbortWithStatus(status int, c *gin.Context) {
if status >= 500 { if status >= 500 {
e.logger().WithField("error", e.Err).Error("encountered HTTP/500 error while handling request") e.logger().WithField("error", e.Err).Error("encountered HTTP/500 error while handling request")
c.Error(errors.WithStack(e)) c.Error(errors.WithStackIf(e))
} else { } else {
e.logger().WithField("error", e.Err).Debug("encountered non-HTTP/500 error while handling request") e.logger().WithField("error", e.Err).Debug("encountered non-HTTP/500 error while handling request")
} }
@ -99,38 +99,32 @@ func (e *RequestError) AbortWithServerError(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) { if errors.Is(e.Err, os.ErrNotExist) || filesystem.IsBadPathResolutionError(e.Err) {
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{ if filesystem.IsBadPathResolutionError(e.Err) {
"error": "The requested resource was not found.", e.logger().Warn(e.Err.Error())
}) }
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "The requested resource was not found."})
return return
} }
if errors.Is(e.Err, filesystem.ErrNotEnoughDiskSpace) { if errors.Is(e.Err, filesystem.ErrNotEnoughDiskSpace) {
c.AbortWithStatusJSON(http.StatusConflict, gin.H{ c.AbortWithStatusJSON(http.StatusConflict, gin.H{"error": "There is not enough disk space available to perform that action."})
"error": "There is not enough disk space available to perform that action.",
})
return return
} }
if strings.HasSuffix(e.Err.Error(), "file name too long") { if strings.HasSuffix(e.Err.Error(), "file name too long") {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "File name is too long."})
"error": "File name is too long.",
})
return return
} }
if e, ok := e.Err.(*os.SyscallError); ok && e.Syscall == "readdirent" { if e, ok := e.Err.(*os.SyscallError); ok && e.Syscall == "readdirent" {
c.AbortWithStatusJSON(http.StatusNotFound, gin.H{ c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "The requested directory does not exist."})
"error": "The requested directory does not exist.",
})
return return
} }
if strings.HasSuffix(e.Err.Error(), "file name too long") { if strings.HasSuffix(e.Err.Error(), "file name too long") {
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Cannot perform that action: file name is too long."})
"error": "Cannot perform that action: file name is too long.",
})
return return
} }

View File

@ -3,9 +3,9 @@ package router
import ( import (
"bytes" "bytes"
"context" "context"
"emperror.dev/errors"
"github.com/apex/log" "github.com/apex/log"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/router/tokens" "github.com/pterodactyl/wings/router/tokens"
"github.com/pterodactyl/wings/server" "github.com/pterodactyl/wings/server"
"net/http" "net/http"
@ -227,7 +227,7 @@ func deleteServer(c *gin.Context) {
if err := os.RemoveAll(p); err != nil { if err := os.RemoveAll(p); err != nil {
log.WithFields(log.Fields{ log.WithFields(log.Fields{
"path": p, "path": p,
"error": errors.WithStack(err), "error": errors.WithStackIf(err),
}).Warn("failed to remove server files during deletion process") }).Warn("failed to remove server files during deletion process")
} }
}(s.Filesystem().Path()) }(s.Filesystem().Path())

View File

@ -2,8 +2,8 @@ package router
import ( import (
"context" "context"
"emperror.dev/errors"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/router/tokens" "github.com/pterodactyl/wings/router/tokens"
"github.com/pterodactyl/wings/server" "github.com/pterodactyl/wings/server"
"github.com/pterodactyl/wings/server/filesystem" "github.com/pterodactyl/wings/server/filesystem"
@ -35,19 +35,19 @@ func getServerFileContents(c *gin.Context) {
return return
} }
c.Header("X-Mime-Type", st.Mimetype)
c.Header("Content-Length", strconv.Itoa(int(st.Info.Size())))
// If a download parameter is included in the URL go ahead and attach the necessary headers
// so that the file can be downloaded.
if c.Query("download") != "" {
c.Header("Content-Disposition", "attachment; filename="+st.Info.Name())
c.Header("Content-Type", "application/octet-stream")
}
if err := s.Filesystem().Readfile(p, c.Writer); err != nil { if err := s.Filesystem().Readfile(p, c.Writer); err != nil {
TrackedServerError(err, s).AbortFilesystemError(c) TrackedServerError(err, s).AbortFilesystemError(c)
return return
} else {
c.Header("X-Mime-Type", st.Mimetype)
c.Header("Content-Length", strconv.Itoa(int(st.Info.Size())))
// If a download parameter is included in the URL go ahead and attach the necessary headers
// so that the file can be downloaded.
if c.Query("download") != "" {
c.Header("Content-Disposition", "attachment; filename="+st.Info.Name())
c.Header("Content-Type", "application/octet-stream")
}
} }
} }
@ -413,12 +413,12 @@ func postServerUploadFiles(c *gin.Context) {
func handleFileUpload(p string, s *server.Server, header *multipart.FileHeader) error { func handleFileUpload(p string, s *server.Server, header *multipart.FileHeader) error {
file, err := header.Open() file, err := header.Open()
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
defer file.Close() defer file.Close()
if err := s.Filesystem().Writefile(p, file); err != nil { if err := s.Filesystem().Writefile(p, file); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return nil return nil

View File

@ -4,12 +4,12 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"crypto/sha256" "crypto/sha256"
"emperror.dev/errors"
"encoding/hex" "encoding/hex"
"github.com/apex/log" "github.com/apex/log"
"github.com/buger/jsonparser" "github.com/buger/jsonparser"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/mholt/archiver/v3" "github.com/mholt/archiver/v3"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api" "github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/installer" "github.com/pterodactyl/wings/installer"
@ -157,7 +157,7 @@ func postTransfer(c *gin.Context) {
// Make a new GET request to the URL the panel gave us. // Make a new GET request to the URL the panel gave us.
req, err := http.NewRequest("GET", url, nil) req, err := http.NewRequest("GET", url, nil)
if err != nil { if err != nil {
log.WithField("error", errors.WithStack(err)).Error("failed to create http request for archive transfer") log.WithField("error", errors.WithStackIf(err)).Error("failed to create http request for archive transfer")
return return
} }
@ -167,7 +167,7 @@ func postTransfer(c *gin.Context) {
// Execute the http request. // Execute the http request.
res, err := client.Do(req) res, err := client.Do(req)
if err != nil { if err != nil {
l.WithField("error", errors.WithStack(err)).Error("failed to send archive http request") l.WithField("error", errors.WithStackIf(err)).Error("failed to send archive http request")
return return
} }
defer res.Body.Close() defer res.Body.Close()
@ -176,12 +176,12 @@ func postTransfer(c *gin.Context) {
if res.StatusCode != 200 { if res.StatusCode != 200 {
_, err := ioutil.ReadAll(res.Body) _, err := ioutil.ReadAll(res.Body)
if err != nil { if err != nil {
l.WithField("error", errors.WithStack(err)).WithField("status", res.StatusCode).Error("failed read transfer response body") l.WithField("error", errors.WithStackIf(err)).WithField("status", res.StatusCode).Error("failed read transfer response body")
return return
} }
l.WithField("error", errors.WithStack(err)).WithField("status", res.StatusCode).Error("failed to request server archive") l.WithField("error", errors.WithStackIf(err)).WithField("status", res.StatusCode).Error("failed to request server archive")
return return
} }
@ -193,12 +193,12 @@ func postTransfer(c *gin.Context) {
_, err = os.Stat(archivePath) _, err = os.Stat(archivePath)
if err != nil { if err != nil {
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
l.WithField("error", errors.WithStack(err)).Error("failed to stat archive file") l.WithField("error", errors.WithStackIf(err)).Error("failed to stat archive file")
return return
} }
} else { } else {
if err := os.Remove(archivePath); err != nil { if err := os.Remove(archivePath); err != nil {
l.WithField("error", errors.WithStack(err)).Warn("failed to remove old archive file") l.WithField("error", errors.WithStackIf(err)).Warn("failed to remove old archive file")
return return
} }
@ -207,7 +207,7 @@ func postTransfer(c *gin.Context) {
// Create the file. // Create the file.
file, err := os.Create(archivePath) file, err := os.Create(archivePath)
if err != nil { if err != nil {
l.WithField("error", errors.WithStack(err)).Error("failed to open archive on disk") l.WithField("error", errors.WithStackIf(err)).Error("failed to open archive on disk")
return return
} }
@ -216,14 +216,14 @@ func postTransfer(c *gin.Context) {
buf := make([]byte, 1024*4) buf := make([]byte, 1024*4)
_, err = io.CopyBuffer(file, res.Body, buf) _, err = io.CopyBuffer(file, res.Body, buf)
if err != nil { if err != nil {
l.WithField("error", errors.WithStack(err)).Error("failed to copy archive file to disk") l.WithField("error", errors.WithStackIf(err)).Error("failed to copy archive file to disk")
return return
} }
// Close the file so it can be opened to verify the checksum. // Close the file so it can be opened to verify the checksum.
if err := file.Close(); err != nil { if err := file.Close(); err != nil {
l.WithField("error", errors.WithStack(err)).Error("failed to close archive file") l.WithField("error", errors.WithStackIf(err)).Error("failed to close archive file")
return return
} }
@ -233,7 +233,7 @@ func postTransfer(c *gin.Context) {
// Open the archive file for computing a checksum. // Open the archive file for computing a checksum.
file, err = os.Open(archivePath) file, err = os.Open(archivePath)
if err != nil { if err != nil {
l.WithField("error", errors.WithStack(err)).Error("failed to open archive on disk") l.WithField("error", errors.WithStackIf(err)).Error("failed to open archive on disk")
return return
} }
@ -241,7 +241,7 @@ func postTransfer(c *gin.Context) {
hash := sha256.New() hash := sha256.New()
buf = make([]byte, 1024*4) buf = make([]byte, 1024*4)
if _, err := io.CopyBuffer(hash, file, buf); err != nil { if _, err := io.CopyBuffer(hash, file, buf); err != nil {
l.WithField("error", errors.WithStack(err)).Error("failed to copy archive file for checksum verification") l.WithField("error", errors.WithStackIf(err)).Error("failed to copy archive file for checksum verification")
return return
} }
@ -253,7 +253,7 @@ func postTransfer(c *gin.Context) {
// Close the file. // Close the file.
if err := file.Close(); err != nil { if err := file.Close(); err != nil {
l.WithField("error", errors.WithStack(err)).Error("failed to close archive file after calculating checksum") l.WithField("error", errors.WithStackIf(err)).Error("failed to close archive file after calculating checksum")
return return
} }
@ -269,7 +269,7 @@ func postTransfer(c *gin.Context) {
// Create a new server installer (note this does not execute the install script) // Create a new server installer (note this does not execute the install script)
i, err := installer.New(serverData) i, err := installer.New(serverData)
if err != nil { if err != nil {
l.WithField("error", errors.WithStack(err)).Error("failed to validate received server data") l.WithField("error", errors.WithStackIf(err)).Error("failed to validate received server data")
return return
} }
@ -284,7 +284,7 @@ func postTransfer(c *gin.Context) {
// Un-archive the archive. That sounds weird.. // Un-archive the archive. That sounds weird..
if err := archiver.NewTarGz().Unarchive(archivePath, i.Server().Filesystem().Path()); err != nil { if err := archiver.NewTarGz().Unarchive(archivePath, i.Server().Filesystem().Path()); err != nil {
l.WithField("error", errors.WithStack(err)).Error("failed to extract server archive") l.WithField("error", errors.WithStackIf(err)).Error("failed to extract server archive")
return return
} }
@ -299,7 +299,7 @@ func postTransfer(c *gin.Context) {
err = api.New().SendTransferSuccess(serverID) err = api.New().SendTransferSuccess(serverID)
if err != nil { if err != nil {
if !api.IsRequestError(err) { if !api.IsRequestError(err) {
l.WithField("error", errors.WithStack(err)).Error("failed to notify panel of transfer success") l.WithField("error", errors.WithStackIf(err)).Error("failed to notify panel of transfer success")
return return
} }

View File

@ -2,13 +2,13 @@ package websocket
import ( import (
"context" "context"
"emperror.dev/errors"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/apex/log" "github.com/apex/log"
"github.com/gbrlsnchs/jwt/v3" "github.com/gbrlsnchs/jwt/v3"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
"github.com/pterodactyl/wings/environment/docker" "github.com/pterodactyl/wings/environment/docker"
@ -41,10 +41,10 @@ type Handler struct {
} }
var ( var (
ErrJwtNotPresent = errors.New("jwt: no jwt present") ErrJwtNotPresent = errors.Sentinel("jwt: no jwt present")
ErrJwtNoConnectPerm = errors.New("jwt: missing connect permission") ErrJwtNoConnectPerm = errors.Sentinel("jwt: missing connect permission")
ErrJwtUuidMismatch = errors.New("jwt: server uuid mismatch") ErrJwtUuidMismatch = errors.Sentinel("jwt: server uuid mismatch")
ErrJwtOnDenylist = errors.New("jwt: created too far in past (denylist)") ErrJwtOnDenylist = errors.Sentinel("jwt: created too far in past (denylist)")
) )
func IsJwtError(err error) bool { func IsJwtError(err error) bool {
@ -108,7 +108,7 @@ func GetHandler(s *server.Server, w http.ResponseWriter, r *http.Request) (*Hand
u, err := uuid.NewRandom() u, err := uuid.NewRandom()
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
return &Handler{ return &Handler{

View File

@ -2,9 +2,9 @@ package server
import ( import (
"crypto/sha256" "crypto/sha256"
"emperror.dev/errors"
"encoding/hex" "encoding/hex"
"github.com/mholt/archiver/v3" "github.com/mholt/archiver/v3"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/server/filesystem" "github.com/pterodactyl/wings/server/filesystem"
"io" "io"
@ -41,7 +41,7 @@ func (a *Archiver) Exists() bool {
func (a *Archiver) Stat() (*filesystem.Stat, error) { func (a *Archiver) Stat() (*filesystem.Stat, error) {
s, err := os.Stat(a.Path()) s, err := os.Stat(a.Path())
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
return &filesystem.Stat{ return &filesystem.Stat{
@ -99,7 +99,7 @@ func (a *Archiver) DeleteIfExists() error {
} }
if err := os.Remove(a.Path()); err != nil { if err := os.Remove(a.Path()); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return nil return nil

View File

@ -2,8 +2,8 @@ package server
import ( import (
"bufio" "bufio"
"emperror.dev/errors"
"github.com/apex/log" "github.com/apex/log"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api" "github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/server/backup" "github.com/pterodactyl/wings/server/backup"
"os" "os"
@ -80,7 +80,7 @@ func (s *Server) Backup(b backup.BackupInterface) error {
// Get the included files based on the root path and the ignored files provided. // Get the included files based on the root path and the ignored files provided.
inc, err := s.GetIncludedBackupFiles(b.Ignored()) inc, err := s.GetIncludedBackupFiles(b.Ignored())
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
ad, err := b.Generate(inc, s.Filesystem().Path()) ad, err := b.Generate(inc, s.Filesystem().Path())
@ -100,7 +100,7 @@ func (s *Server) Backup(b backup.BackupInterface) error {
"file_size": 0, "file_size": 0,
}) })
return errors.Wrap(err, "error while generating server backup") return errors.WrapIf(err, "error while generating server backup")
} }
// Try to notify the panel about the status of this backup. If for some reason this request // Try to notify the panel about the status of this backup. If for some reason this request

View File

@ -3,9 +3,9 @@ package backup
import ( import (
"archive/tar" "archive/tar"
"context" "context"
"emperror.dev/errors"
"github.com/apex/log" "github.com/apex/log"
gzip "github.com/klauspost/pgzip" gzip "github.com/klauspost/pgzip"
"github.com/pkg/errors"
"github.com/remeh/sizedwaitgroup" "github.com/remeh/sizedwaitgroup"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"io" "io"
@ -26,7 +26,7 @@ type Archive struct {
func (a *Archive) Create(dst string, ctx context.Context) error { func (a *Archive) Create(dst string, ctx context.Context) error {
f, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) f, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
defer f.Close() defer f.Close()
@ -58,7 +58,7 @@ func (a *Archive) Create(dst string, ctx context.Context) error {
select { select {
case <-ctx.Done(): case <-ctx.Done():
return errors.WithStack(ctx.Err()) return errors.WithStackIf(ctx.Err())
default: default:
return a.addToArchive(p, tw) return a.addToArchive(p, tw)
} }
@ -75,7 +75,7 @@ func (a *Archive) Create(dst string, ctx context.Context) error {
log.WithField("location", dst).Warn("failed to delete corrupted backup archive") log.WithField("location", dst).Warn("failed to delete corrupted backup archive")
} }
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return nil return nil
@ -91,7 +91,7 @@ func (a *Archive) addToArchive(p string, w *tar.Writer) error {
return nil return nil
} }
return errors.WithStack(err) return errors.WithStackIf(err)
} }
defer f.Close() defer f.Close()
@ -102,7 +102,7 @@ func (a *Archive) addToArchive(p string, w *tar.Writer) error {
return nil return nil
} }
return errors.WithStack(err) return errors.WithStackIf(err)
} }
header := &tar.Header{ header := &tar.Header{
@ -120,12 +120,12 @@ func (a *Archive) addToArchive(p string, w *tar.Writer) error {
defer a.Unlock() defer a.Unlock()
if err := w.WriteHeader(header); err != nil { if err := w.WriteHeader(header); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
buf := make([]byte, 4*1024) buf := make([]byte, 4*1024)
if _, err := io.CopyBuffer(w, f, buf); err != nil { if _, err := io.CopyBuffer(w, f, buf); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return nil return nil

View File

@ -2,9 +2,9 @@ package backup
import ( import (
"crypto/sha1" "crypto/sha1"
"emperror.dev/errors"
"encoding/hex" "encoding/hex"
"github.com/apex/log" "github.com/apex/log"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api" "github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"io" "io"
@ -87,7 +87,7 @@ func (b *Backup) Path() string {
func (b *Backup) Size() (int64, error) { func (b *Backup) Size() (int64, error) {
st, err := os.Stat(b.Path()) st, err := os.Stat(b.Path())
if err != nil { if err != nil {
return 0, errors.WithStack(err) return 0, errors.WithStackIf(err)
} }
return st.Size(), nil return st.Size(), nil
@ -99,7 +99,7 @@ func (b *Backup) Checksum() ([]byte, error) {
f, err := os.Open(b.Path()) f, err := os.Open(b.Path())
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
defer f.Close() defer f.Close()

View File

@ -2,7 +2,7 @@ package backup
import ( import (
"context" "context"
"github.com/pkg/errors" "emperror.dev/errors"
"os" "os"
) )
@ -24,7 +24,7 @@ func LocateLocal(uuid string) (*LocalBackup, os.FileInfo, error) {
st, err := os.Stat(b.Path()) st, err := os.Stat(b.Path())
if err != nil { if err != nil {
return nil, nil, errors.WithStack(err) return nil, nil, errors.WithStackIf(err)
} }
if st.IsDir() { if st.IsDir() {
@ -48,7 +48,7 @@ func (b *LocalBackup) Generate(included *IncludedFiles, prefix string) (*Archive
} }
if err := a.Create(b.Path(), context.Background()); err != nil { if err := a.Create(b.Path(), context.Background()); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
return b.Details(), nil return b.Details(), nil

View File

@ -1,8 +1,8 @@
package backup package backup
import ( import (
"emperror.dev/errors"
"fmt" "fmt"
"github.com/pkg/errors"
) )
type Request struct { type Request struct {

View File

@ -3,9 +3,9 @@ package backup
import ( import (
"bytes" "bytes"
"context" "context"
"emperror.dev/errors"
"fmt" "fmt"
"github.com/apex/log" "github.com/apex/log"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api" "github.com/pterodactyl/wings/api"
"io" "io"
"net/http" "net/http"
@ -31,17 +31,17 @@ func (s *S3Backup) Generate(included *IncludedFiles, prefix string) (*ArchiveDet
} }
if err := a.Create(s.Path(), context.Background()); err != nil { if err := a.Create(s.Path(), context.Background()); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
rc, err := os.Open(s.Path()) rc, err := os.Open(s.Path())
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
defer rc.Close() defer rc.Close()
if err := s.generateRemoteRequest(rc); err != nil { if err := s.generateRemoteRequest(rc); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
return s.Details(), err return s.Details(), err

View File

@ -2,9 +2,9 @@ package server
import ( import (
"context" "context"
"emperror.dev/errors"
"fmt" "fmt"
"github.com/mitchellh/colorstring" "github.com/mitchellh/colorstring"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/system" "github.com/pterodactyl/wings/system"
"sync" "sync"
@ -12,7 +12,7 @@ import (
"time" "time"
) )
var ErrTooMuchConsoleData = errors.New("console is outputting too much data") var ErrTooMuchConsoleData = errors.Sentinel("console is outputting too much data")
type ConsoleThrottler struct { type ConsoleThrottler struct {
mu sync.Mutex mu sync.Mutex

View File

@ -1,8 +1,8 @@
package server package server
import ( import (
"emperror.dev/errors"
"fmt" "fmt"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
"sync" "sync"
@ -57,7 +57,7 @@ func (s *Server) handleServerCrash() error {
exitCode, oomKilled, err := s.Environment.ExitState() exitCode, oomKilled, err := s.Environment.ExitState()
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// If the system is not configured to detect a clean exit code as a crash, and the // If the system is not configured to detect a clean exit code as a crash, and the

View File

@ -1,9 +1,9 @@
package server package server
import "github.com/pkg/errors" import "emperror.dev/errors"
var ErrIsRunning = errors.New("server is running") var ErrIsRunning = errors.Sentinel("server is running")
var ErrSuspended = errors.New("server is currently in a suspended state") var ErrSuspended = errors.Sentinel("server is currently in a suspended state")
type crashTooFrequent struct { type crashTooFrequent struct {
} }

View File

@ -1,7 +1,7 @@
package server package server
import ( import (
"github.com/pkg/errors" "emperror.dev/errors"
"github.com/pterodactyl/wings/server/filesystem" "github.com/pterodactyl/wings/server/filesystem"
"os" "os"
) )
@ -13,12 +13,12 @@ func (s *Server) Filesystem() *filesystem.Filesystem {
// Ensures that the data directory for the server instance exists. // Ensures that the data directory for the server instance exists.
func (s *Server) EnsureDataDirectoryExists() error { func (s *Server) EnsureDataDirectoryExists() error {
if _, err := os.Stat(s.fs.Path()); err != nil && !os.IsNotExist(err) { if _, err := os.Stat(s.fs.Path()); err != nil && !os.IsNotExist(err) {
return errors.WithStack(err) return errors.WithStackIf(err)
} else if err != nil { } else if err != nil {
// Create the server data directory because it does not currently exist // Create the server data directory because it does not currently exist
// on the system. // on the system.
if err := os.MkdirAll(s.fs.Path(), 0700); err != nil { if err := os.MkdirAll(s.fs.Path(), 0700); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
if err := s.fs.Chown("/"); err != nil { if err := s.fs.Chown("/"); err != nil {

View File

@ -2,9 +2,9 @@ package filesystem
import ( import (
"context" "context"
"emperror.dev/errors"
"fmt" "fmt"
"github.com/karrick/godirwalk" "github.com/karrick/godirwalk"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/server/backup" "github.com/pterodactyl/wings/server/backup"
ignore "github.com/sabhiram/go-gitignore" ignore "github.com/sabhiram/go-gitignore"
"os" "os"
@ -41,7 +41,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 errors.Is(err, ErrBadPathResolution) { if IsBadPathResolutionError(err) {
return godirwalk.SkipThis return godirwalk.SkipThis
} }
@ -65,7 +65,7 @@ func (fs *Filesystem) GetIncludedFiles(dir string, ignored []string) (*backup.In
}, },
}) })
return inc, errors.WithStack(err) return inc, errors.WithStackIf(err)
} }
// Compresses all of the files matching the given paths in the specified directory. This function // Compresses all of the files matching the given paths in the specified directory. This function
@ -115,7 +115,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 errors.Is(err, ErrBadPathResolution) { if IsBadPathResolutionError(err) {
return godirwalk.SkipThis return godirwalk.SkipThis
} }
@ -141,7 +141,7 @@ func (fs *Filesystem) CompressFiles(dir string, paths []string) (os.FileInfo, er
d := path.Join(cleanedRootDir, fmt.Sprintf("archive-%s.tar.gz", strings.ReplaceAll(time.Now().Format(time.RFC3339), ":", ""))) d := path.Join(cleanedRootDir, fmt.Sprintf("archive-%s.tar.gz", strings.ReplaceAll(time.Now().Format(time.RFC3339), ":", "")))
if err := a.Create(d, context.Background()); err != nil { if err := a.Create(d, context.Background()); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
f, err := os.Stat(d) f, err := os.Stat(d)

View File

@ -4,9 +4,9 @@ import (
"archive/tar" "archive/tar"
"archive/zip" "archive/zip"
"compress/gzip" "compress/gzip"
"emperror.dev/errors"
"fmt" "fmt"
"github.com/mholt/archiver/v3" "github.com/mholt/archiver/v3"
"github.com/pkg/errors"
"os" "os"
"path/filepath" "path/filepath"
"reflect" "reflect"
@ -47,10 +47,10 @@ func (fs *Filesystem) SpaceAvailableForDecompression(dir string, file string) (b
return false, ErrUnknownArchiveFormat return false, ErrUnknownArchiveFormat
} }
return false, errors.WithStack(err) return false, errors.WithStackIf(err)
} }
return true, errors.WithStack(err) return true, errors.WithStackIf(err)
} }
// Decompress a file in a given directory by using the archiver tool to infer the file // Decompress a file in a given directory by using the archiver tool to infer the file
@ -60,12 +60,12 @@ func (fs *Filesystem) SpaceAvailableForDecompression(dir string, file string) (b
func (fs *Filesystem) DecompressFile(dir string, file string) error { func (fs *Filesystem) DecompressFile(dir string, file string) error {
source, err := fs.SafePath(filepath.Join(dir, file)) source, err := fs.SafePath(filepath.Join(dir, file))
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// Make sure the file exists basically. // Make sure the file exists basically.
if _, err := os.Stat(source); err != nil { if _, err := os.Stat(source); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// Walk over all of the files spinning up an additional go-routine for each file we've encountered // Walk over all of the files spinning up an additional go-routine for each file we've encountered
@ -93,17 +93,17 @@ func (fs *Filesystem) DecompressFile(dir string, file string) error {
p, err := fs.SafePath(filepath.Join(dir, name)) p, err := fs.SafePath(filepath.Join(dir, name))
if err != nil { if err != nil {
return errors.Wrap(err, "failed to generate a safe path to server file") return errors.WrapIf(err, "failed to generate a safe path to server file")
} }
return errors.Wrap(fs.Writefile(p, f), "could not extract file from archive") return errors.WrapIf(fs.Writefile(p, f), "could not extract file from archive")
}) })
if err != nil { if err != nil {
if strings.HasPrefix(err.Error(), "format ") { if strings.HasPrefix(err.Error(), "format ") {
return errors.WithStack(ErrUnknownArchiveFormat) return errors.WithStackIf(ErrUnknownArchiveFormat)
} }
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return nil return nil

View File

@ -1,9 +1,9 @@
package filesystem package filesystem
import ( import (
"emperror.dev/errors"
"github.com/apex/log" "github.com/apex/log"
"github.com/karrick/godirwalk" "github.com/karrick/godirwalk"
"github.com/pkg/errors"
"sync" "sync"
"sync/atomic" "sync/atomic"
"syscall" "syscall"
@ -153,7 +153,7 @@ func (fs *Filesystem) updateCachedDiskUsage() (int64, error) {
func (fs *Filesystem) DirectorySize(dir string) (int64, error) { func (fs *Filesystem) DirectorySize(dir string) (int64, error) {
d, err := fs.SafePath(dir) d, err := fs.SafePath(dir)
if err != nil { if err != nil {
return 0, errors.WithStack(err) return 0, errors.WithStackIf(err)
} }
var size int64 var size int64
@ -167,7 +167,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 errors.Is(err, ErrBadPathResolution) { if IsBadPathResolutionError(err) {
return godirwalk.SkipThis return godirwalk.SkipThis
} }
@ -184,7 +184,7 @@ func (fs *Filesystem) DirectorySize(dir string) (int64, error) {
}, },
}) })
return size, errors.WithStack(err) return size, errors.WithStackIf(err)
} }
// Helper function to determine if a server has space available for a file of a given size. // Helper function to determine if a server has space available for a file of a given size.

View File

@ -1,16 +1,43 @@
package filesystem package filesystem
import ( import (
"emperror.dev/errors"
"fmt"
"github.com/apex/log" "github.com/apex/log"
"github.com/pkg/errors"
"os" "os"
"path/filepath" "path/filepath"
) )
var ErrIsDirectory = errors.New("filesystem: is a directory") var ErrIsDirectory = errors.Sentinel("filesystem: is a directory")
var ErrNotEnoughDiskSpace = errors.New("filesystem: not enough disk space") var ErrNotEnoughDiskSpace = errors.Sentinel("filesystem: not enough disk space")
var ErrBadPathResolution = errors.New("filesystem: invalid path resolution") var ErrUnknownArchiveFormat = errors.Sentinel("filesystem: unknown archive format")
var ErrUnknownArchiveFormat = errors.New("filesystem: unknown archive format")
type BadPathResolutionError struct {
path string
resolved string
}
// Returns the specific error for a bad path resolution.
func (b *BadPathResolutionError) Error() string {
r := b.resolved
if r == "" {
r = "<empty>"
}
return fmt.Sprintf("filesystem: server path [%s] resolves to a location outside the server root: %s", b.path, r)
}
// Returns a new BadPathResolution error.
func NewBadPathResolution(path string, resolved string) *BadPathResolutionError {
return &BadPathResolutionError{path, resolved}
}
// Determines if the given error is a bad path resolution error.
func IsBadPathResolutionError(err error) bool {
if _, ok := err.(*BadPathResolutionError); ok {
return true
}
return false
}
// Generates an error logger instance with some basic information. // Generates an error logger instance with some basic information.
func (fs *Filesystem) error(err error) *log.Entry { func (fs *Filesystem) error(err error) *log.Entry {
@ -23,8 +50,8 @@ 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 !errors.Is(err, ErrBadPathResolution) { if !IsBadPathResolutionError(err) {
return err return errors.WithStackIf(err)
} }
if f != nil && f.IsDir() { if f != nil && f.IsDir() {
@ -32,4 +59,4 @@ func (fs *Filesystem) handleWalkerError(err error, f os.FileInfo) error {
} }
return nil return nil
} }

View File

@ -2,9 +2,9 @@ package filesystem
import ( import (
"bufio" "bufio"
"emperror.dev/errors"
"github.com/gabriel-vasile/mimetype" "github.com/gabriel-vasile/mimetype"
"github.com/karrick/godirwalk" "github.com/karrick/godirwalk"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/system" "github.com/pterodactyl/wings/system"
"io" "io"
@ -80,7 +80,7 @@ func (fs *Filesystem) Readfile(p string, w io.Writer) error {
func (fs *Filesystem) Writefile(p string, r io.Reader) error { func (fs *Filesystem) Writefile(p string, r io.Reader) error {
cleaned, err := fs.SafePath(p) cleaned, err := fs.SafePath(p)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
var currentSize int64 var currentSize int64
@ -88,15 +88,15 @@ func (fs *Filesystem) Writefile(p string, r io.Reader) error {
// to it and an empty file. We'll then write to it later on after this completes. // 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 stat, err := os.Stat(cleaned); err != nil {
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
if err := os.MkdirAll(filepath.Dir(cleaned), 0755); err != nil { if err := os.MkdirAll(filepath.Dir(cleaned), 0755); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
if err := fs.Chown(filepath.Dir(cleaned)); err != nil { if err := fs.Chown(filepath.Dir(cleaned)); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
} else { } else {
if stat.IsDir() { if stat.IsDir() {
@ -119,7 +119,7 @@ func (fs *Filesystem) Writefile(p string, r io.Reader) error {
// truncate the existing file. // truncate the existing file.
file, err := o.open(cleaned, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) file, err := o.open(cleaned, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
defer file.Close() defer file.Close()
@ -138,7 +138,7 @@ func (fs *Filesystem) Writefile(p string, r io.Reader) error {
func (fs *Filesystem) CreateDirectory(name string, p string) error { func (fs *Filesystem) CreateDirectory(name string, p string) error {
cleaned, err := fs.SafePath(path.Join(p, name)) cleaned, err := fs.SafePath(path.Join(p, name))
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return os.MkdirAll(cleaned, 0755) return os.MkdirAll(cleaned, 0755)
@ -148,12 +148,12 @@ func (fs *Filesystem) CreateDirectory(name string, p string) error {
func (fs *Filesystem) Rename(from string, to string) error { func (fs *Filesystem) Rename(from string, to string) error {
cleanedFrom, err := fs.SafePath(from) cleanedFrom, err := fs.SafePath(from)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
cleanedTo, err := fs.SafePath(to) cleanedTo, err := fs.SafePath(to)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// If the target file or directory already exists the rename function will fail, so just // If the target file or directory already exists the rename function will fail, so just
@ -171,7 +171,7 @@ func (fs *Filesystem) Rename(from string, to string) error {
// we're not at the root directory level. // we're not at the root directory level.
if d != fs.Path() { if d != fs.Path() {
if mkerr := os.MkdirAll(d, 0755); mkerr != nil { if mkerr := os.MkdirAll(d, 0755); mkerr != nil {
return errors.Wrap(mkerr, "failed to create directory structure for file rename") return errors.WrapIf(mkerr, "failed to create directory structure for file rename")
} }
} }
@ -185,7 +185,7 @@ func (fs *Filesystem) Rename(from string, to string) error {
func (fs *Filesystem) Chown(path string) error { func (fs *Filesystem) Chown(path string) error {
cleaned, err := fs.SafePath(path) cleaned, err := fs.SafePath(path)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
if fs.isTest { if fs.isTest {
@ -197,7 +197,7 @@ func (fs *Filesystem) Chown(path string) error {
// Start by just chowning the initial path that we received. // Start by just chowning the initial path that we received.
if err := os.Chown(cleaned, uid, gid); err != nil { if err := os.Chown(cleaned, uid, gid); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// If this is not a directory we can now return from the function, there is nothing // If this is not a directory we can now return from the function, there is nothing
@ -268,12 +268,12 @@ func (fs *Filesystem) findCopySuffix(dir string, name string, extension string)
func (fs *Filesystem) Copy(p string) error { func (fs *Filesystem) Copy(p string) error {
cleaned, err := fs.SafePath(p) cleaned, err := fs.SafePath(p)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
s, err := os.Stat(cleaned) s, err := os.Stat(cleaned)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} else if s.IsDir() || !s.Mode().IsRegular() { } else if s.IsDir() || !s.Mode().IsRegular() {
// If this is a directory or not a regular file, just throw a not-exist error // If this is a directory or not a regular file, just throw a not-exist error
// since anything calling this function should understand what that means. // since anything calling this function should understand what that means.
@ -300,7 +300,7 @@ func (fs *Filesystem) Copy(p string) error {
source, err := os.Open(cleaned) source, err := os.Open(cleaned)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
defer source.Close() defer source.Close()
@ -324,7 +324,7 @@ func (fs *Filesystem) Delete(p string) error {
// exists within the data directory. // exists within the data directory.
resolved := fs.unsafeFilePath(p) resolved := fs.unsafeFilePath(p)
if !fs.unsafeIsInDataDirectory(resolved) { if !fs.unsafeIsInDataDirectory(resolved) {
return ErrBadPathResolution return NewBadPathResolution(p, resolved)
} }
// Block any whoopsies. // Block any whoopsies.

View File

@ -134,22 +134,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).IsTrue()
g.Assert(p).Equal("") g.Assert(p).Equal("")
}) })
}) })
@ -185,7 +185,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).IsTrue()
}) })
}) })
@ -195,7 +195,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).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() {
@ -203,7 +203,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).IsTrue()
}) })
}) })
@ -211,19 +211,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).IsTrue()
}) })
}) })
@ -231,13 +231,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).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() {
@ -245,7 +245,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).IsTrue()
}) })
}) })
@ -253,13 +253,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).IsTrue()
}) })
}) })
@ -267,7 +267,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).IsTrue()
}) })
}) })
@ -325,7 +325,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, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).IsTrue()
}) })
g.AfterEach(func() { g.AfterEach(func() {
@ -386,7 +386,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).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() {
@ -477,7 +477,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).IsTrue()
}) })
g.It("should not increment the disk usage", func() { g.It("should not increment the disk usage", func() {
@ -527,7 +527,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).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() {
@ -535,7 +535,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).IsTrue()
}) })
g.It("allows a file to be renamed", func() { g.It("allows a file to be renamed", func() {
@ -613,7 +613,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).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() {
@ -625,11 +625,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).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() {
@ -721,7 +721,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(errors.Is(err, ErrBadPathResolution)).IsTrue() g.Assert(IsBadPathResolutionError(err)).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

@ -2,6 +2,7 @@ package filesystem
import ( import (
"context" "context"
"emperror.dev/errors"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"os" "os"
"path/filepath" "path/filepath"
@ -23,9 +24,9 @@ func (fs *Filesystem) SafePath(p string) (string, error) {
// At the same time, evaluate the symlink status and determine where this file or folder // At the same time, evaluate the symlink status and determine where this file or folder
// is truly pointing to. // is truly pointing to.
p, err := filepath.EvalSymlinks(r) ep, err := filepath.EvalSymlinks(r)
if err != nil && !os.IsNotExist(err) { if err != nil && !os.IsNotExist(err) {
return "", err return "", errors.WithStackIf(err)
} else if os.IsNotExist(err) { } else if os.IsNotExist(err) {
// The requested directory doesn't exist, so at this point we need to iterate up the // The requested directory doesn't exist, so at this point we need to iterate up the
// path chain until we hit a directory that _does_ exist and can be validated. // path chain until we hit a directory that _does_ exist and can be validated.
@ -53,7 +54,7 @@ func (fs *Filesystem) SafePath(p string) (string, error) {
// attempt going on, and we should NOT resolve this path for them. // attempt going on, and we should NOT resolve this path for them.
if nonExistentPathResolution != "" { if nonExistentPathResolution != "" {
if !fs.unsafeIsInDataDirectory(nonExistentPathResolution) { if !fs.unsafeIsInDataDirectory(nonExistentPathResolution) {
return "", ErrBadPathResolution return "", NewBadPathResolution(p, nonExistentPathResolution)
} }
// If the nonExistentPathResolution variable is not empty then the initial path requested // If the nonExistentPathResolution variable is not empty then the initial path requested
@ -66,11 +67,11 @@ func (fs *Filesystem) SafePath(p string) (string, error) {
// If the requested directory from EvalSymlinks begins with the server root directory go // If the requested directory from EvalSymlinks begins with the server root directory go
// ahead and return it. If not we'll return an error which will block any further action // ahead and return it. If not we'll return an error which will block any further action
// on the file. // on the file.
if fs.unsafeIsInDataDirectory(p) { if fs.unsafeIsInDataDirectory(ep) {
return p, nil return ep, nil
} }
return "", ErrBadPathResolution return "", NewBadPathResolution(p, r)
} }
// Generate a path to the file by cleaning it up and appending the root server path to it. This // Generate a path to the file by cleaning it up and appending the root server path to it. This

View File

@ -1,6 +1,7 @@
package filesystem package filesystem
import ( import (
"emperror.dev/errors"
"encoding/json" "encoding/json"
"github.com/gabriel-vasile/mimetype" "github.com/gabriel-vasile/mimetype"
"os" "os"
@ -50,14 +51,14 @@ func (fs *Filesystem) Stat(p string) (*Stat, error) {
func (fs *Filesystem) unsafeStat(p string) (*Stat, error) { func (fs *Filesystem) unsafeStat(p string) (*Stat, error) {
s, err := os.Stat(p) s, err := os.Stat(p)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStackIf(err)
} }
var m *mimetype.MIME var m *mimetype.MIME
if !s.IsDir() { if !s.IsDir() {
m, err = mimetype.DetectFile(p) m, err = mimetype.DetectFile(p)
if err != nil { if err != nil {
return nil, err return nil, errors.WithStackIf(err)
} }
} }

View File

@ -4,12 +4,12 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"context" "context"
"emperror.dev/errors"
"github.com/apex/log" "github.com/apex/log"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/mount" "github.com/docker/docker/api/types/mount"
"github.com/docker/docker/client" "github.com/docker/docker/client"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api" "github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
@ -90,7 +90,7 @@ func (s *Server) internalInstall() error {
script, err := api.New().GetInstallationScript(s.Id()) script, err := api.New().GetInstallationScript(s.Id())
if err != nil { if err != nil {
if !api.IsRequestError(err) { if !api.IsRequestError(err) {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return errors.New(err.Error()) return errors.New(err.Error())
@ -98,7 +98,7 @@ func (s *Server) internalInstall() error {
p, err := NewInstallationProcess(s, &script) p, err := NewInstallationProcess(s, &script)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
s.Log().Info("beginning installation process for server") s.Log().Info("beginning installation process for server")
@ -130,7 +130,7 @@ func NewInstallationProcess(s *Server, script *api.InstallationScript) (*Install
s.installer.cancel = &cancel s.installer.cancel = &cancel
if c, err := environment.DockerClient(); err != nil { if c, err := environment.DockerClient(); err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} else { } else {
proc.client = c proc.client = c
proc.context = ctx proc.context = ctx
@ -193,7 +193,7 @@ func (ip *InstallationProcess) RemoveContainer() {
}) })
if err != nil && !client.IsErrNotFound(err) { if err != nil && !client.IsErrNotFound(err) {
ip.Server.Log().WithField("error", errors.WithStack(err)).Warn("failed to delete server install container") ip.Server.Log().WithField("error", errors.WithStackIf(err)).Warn("failed to delete server install container")
} }
} }
@ -218,14 +218,14 @@ func (ip *InstallationProcess) Run() error {
}() }()
if err := ip.BeforeExecute(); err != nil { if err := ip.BeforeExecute(); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
cid, err := ip.Execute() cid, err := ip.Execute()
if err != nil { if err != nil {
ip.RemoveContainer() ip.RemoveContainer()
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// If this step fails, log a warning but don't exit out of the process. This is completely // If this step fails, log a warning but don't exit out of the process. This is completely
@ -248,12 +248,12 @@ func (ip *InstallationProcess) writeScriptToDisk() error {
// Make sure the temp directory root exists before trying to make a directory within it. The // Make sure the temp directory root exists before trying to make a directory within it. The
// ioutil.TempDir call expects this base to exist, it won't create it for you. // ioutil.TempDir call expects this base to exist, it won't create it for you.
if err := os.MkdirAll(ip.tempDir(), 0700); err != nil { if err := os.MkdirAll(ip.tempDir(), 0700); err != nil {
return errors.Wrap(err, "could not create temporary directory for install process") return errors.WrapIf(err, "could not create temporary directory for install process")
} }
f, err := os.OpenFile(filepath.Join(ip.tempDir(), "install.sh"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) f, err := os.OpenFile(filepath.Join(ip.tempDir(), "install.sh"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil { if err != nil {
return errors.Wrap(err, "failed to write server installation script to disk before mount") return errors.WrapIf(err, "failed to write server installation script to disk before mount")
} }
defer f.Close() defer f.Close()
@ -265,7 +265,7 @@ func (ip *InstallationProcess) writeScriptToDisk() error {
} }
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
w.Flush() w.Flush()
@ -277,7 +277,7 @@ func (ip *InstallationProcess) writeScriptToDisk() error {
func (ip *InstallationProcess) pullInstallationImage() error { func (ip *InstallationProcess) pullInstallationImage() error {
r, err := ip.client.ImagePull(ip.context, ip.Script.ContainerImage, types.ImagePullOptions{}) r, err := ip.client.ImagePull(ip.context, ip.Script.ContainerImage, types.ImagePullOptions{})
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// Block continuation until the image has been pulled successfully. // Block continuation until the image has been pulled successfully.
@ -287,7 +287,7 @@ func (ip *InstallationProcess) pullInstallationImage() error {
} }
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return nil return nil
@ -298,11 +298,11 @@ func (ip *InstallationProcess) pullInstallationImage() error {
// manner, if either one fails the error is returned. // manner, if either one fails the error is returned.
func (ip *InstallationProcess) BeforeExecute() error { func (ip *InstallationProcess) BeforeExecute() error {
if err := ip.writeScriptToDisk(); err != nil { if err := ip.writeScriptToDisk(); err != nil {
return errors.Wrap(err, "failed to write installation script to disk") return errors.WrapIf(err, "failed to write installation script to disk")
} }
if err := ip.pullInstallationImage(); err != nil { if err := ip.pullInstallationImage(); err != nil {
return errors.Wrap(err, "failed to pull updated installation container image for server") return errors.WrapIf(err, "failed to pull updated installation container image for server")
} }
opts := types.ContainerRemoveOptions{ opts := types.ContainerRemoveOptions{
@ -312,7 +312,7 @@ func (ip *InstallationProcess) BeforeExecute() error {
if err := ip.client.ContainerRemove(ip.context, ip.Server.Id()+"_installer", opts); err != nil { if err := ip.client.ContainerRemove(ip.context, ip.Server.Id()+"_installer", opts); err != nil {
if !client.IsErrNotFound(err) { if !client.IsErrNotFound(err) {
return errors.Wrap(err, "failed to remove existing install container for server") return errors.WrapIf(err, "failed to remove existing install container for server")
} }
} }
@ -338,12 +338,12 @@ func (ip *InstallationProcess) AfterExecute(containerId string) error {
}) })
if err != nil && !client.IsErrNotFound(err) { if err != nil && !client.IsErrNotFound(err) {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
f, err := os.OpenFile(ip.GetLogPath(), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) f, err := os.OpenFile(ip.GetLogPath(), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
defer f.Close() defer f.Close()
@ -372,15 +372,15 @@ func (ip *InstallationProcess) AfterExecute(containerId string) error {
| ------------------------------ | ------------------------------
`) `)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
if err := tmpl.Execute(f, ip); err != nil { if err := tmpl.Execute(f, ip); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
if _, err := io.Copy(f, reader); err != nil { if _, err := io.Copy(f, reader); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return nil return nil
@ -448,7 +448,7 @@ func (ip *InstallationProcess) Execute() (string, error) {
r, err := ip.client.ContainerCreate(ip.context, conf, hostConf, nil, ip.Server.Id()+"_installer") r, err := ip.client.ContainerCreate(ip.context, conf, hostConf, nil, ip.Server.Id()+"_installer")
if err != nil { if err != nil {
return "", errors.WithStack(err) return "", errors.WithStackIf(err)
} }
ip.Server.Log().WithField("container_id", r.ID).Info("running installation script for server in container") ip.Server.Log().WithField("container_id", r.ID).Info("running installation script for server in container")
@ -468,7 +468,7 @@ func (ip *InstallationProcess) Execute() (string, error) {
select { select {
case err := <-eChan: case err := <-eChan:
if err != nil { if err != nil {
return "", errors.WithStack(err) return "", errors.WithStackIf(err)
} }
case <-sChan: case <-sChan:
} }
@ -487,7 +487,7 @@ func (ip *InstallationProcess) StreamOutput(id string) error {
}) })
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
defer reader.Close() defer reader.Close()
@ -500,7 +500,7 @@ func (ip *InstallationProcess) StreamOutput(id string) error {
if err := s.Err(); err != nil { if err := s.Err(); err != nil {
ip.Server.Log().WithFields(log.Fields{ ip.Server.Log().WithFields(log.Fields{
"container_id": id, "container_id": id,
"error": errors.WithStack(err), "error": errors.WithStackIf(err),
}).Warn("error processing scanner line in installation output for server") }).Warn("error processing scanner line in installation output for server")
} }
@ -515,7 +515,7 @@ func (s *Server) SyncInstallState(successful bool) error {
err := api.New().SendInstallationStatus(s.Id(), successful) err := api.New().SendInstallationStatus(s.Id(), successful)
if err != nil { if err != nil {
if !api.IsRequestError(err) { if !api.IsRequestError(err) {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return errors.New(err.Error()) return errors.New(err.Error())

View File

@ -1,9 +1,9 @@
package server package server
import ( import (
"emperror.dev/errors"
"encoding/json" "encoding/json"
"github.com/apex/log" "github.com/apex/log"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api" "github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
@ -77,7 +77,7 @@ func (s *Server) StartEventListeners() {
s.Environment.SetState(environment.ProcessRunningState) s.Environment.SetState(environment.ProcessRunningState)
} }
s.Log().WithField("error", errors.WithStack(err)).Error("failed to terminate environment after triggering throttle") s.Log().WithField("error", errors.WithStackIf(err)).Error("failed to terminate environment after triggering throttle")
} }
}() }()
} }
@ -106,7 +106,7 @@ func (s *Server) StartEventListeners() {
stats := func(e events.Event) { stats := func(e events.Event) {
st := new(environment.Stats) st := new(environment.Stats)
if err := json.Unmarshal([]byte(e.Data), st); err != nil { if err := json.Unmarshal([]byte(e.Data), st); err != nil {
s.Log().WithField("error", errors.WithStack(err)).Warn("failed to unmarshal server environment stats") s.Log().WithField("error", errors.WithStackIf(err)).Warn("failed to unmarshal server environment stats")
return return
} }

View File

@ -1,12 +1,12 @@
package server package server
import ( import (
"emperror.dev/errors"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/apex/log" "github.com/apex/log"
"github.com/creasty/defaults" "github.com/creasty/defaults"
"github.com/gammazero/workerpool" "github.com/gammazero/workerpool"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api" "github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
@ -35,7 +35,7 @@ func LoadDirectory() error {
configs, err := api.New().GetServers() configs, err := api.New().GetServers()
if err != nil { if err != nil {
if !api.IsRequestError(err) { if !api.IsRequestError(err) {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return errors.New(err.Error()) return errors.New(err.Error())
@ -89,12 +89,12 @@ func LoadDirectory() error {
func FromConfiguration(data api.ServerConfigurationResponse) (*Server, error) { func FromConfiguration(data api.ServerConfigurationResponse) (*Server, error) {
cfg := Configuration{} cfg := Configuration{}
if err := defaults.Set(&cfg); err != nil { if err := defaults.Set(&cfg); err != nil {
return nil, errors.Wrap(err, "failed to set struct defaults for server configuration") return nil, errors.WrapIf(err, "failed to set struct defaults for server configuration")
} }
s := new(Server) s := new(Server)
if err := defaults.Set(s); err != nil { if err := defaults.Set(s); err != nil {
return nil, errors.Wrap(err, "failed to set struct defaults for server") return nil, errors.WrapIf(err, "failed to set struct defaults for server")
} }
s.cfg = cfg s.cfg = cfg

View File

@ -2,7 +2,7 @@ package server
import ( import (
"context" "context"
"github.com/pkg/errors" "emperror.dev/errors"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
"github.com/pterodactyl/wings/server/filesystem" "github.com/pterodactyl/wings/server/filesystem"
@ -80,13 +80,13 @@ func (s *Server) HandlePowerAction(action PowerAction, waitSeconds ...int) error
// time than that passes an error will be propagated back up the chain and this // time than that passes an error will be propagated back up the chain and this
// request will be aborted. // request will be aborted.
if err := s.powerLock.Acquire(ctx, 1); err != nil { if err := s.powerLock.Acquire(ctx, 1); err != nil {
return errors.Wrap(err, "could not acquire lock on power state") return errors.WrapIf(err, "could not acquire lock on power state")
} }
} else { } else {
// If no wait duration was provided we will attempt to immediately acquire the lock // If no wait duration was provided we will attempt to immediately acquire the lock
// and bail out with a context deadline error if it is not acquired immediately. // and bail out with a context deadline error if it is not acquired immediately.
if ok := s.powerLock.TryAcquire(1); !ok { if ok := s.powerLock.TryAcquire(1); !ok {
return errors.Wrap(context.DeadlineExceeded, "could not acquire lock on power state") return errors.WrapIf(context.DeadlineExceeded, "could not acquire lock on power state")
} }
} }
@ -149,7 +149,7 @@ func (s *Server) HandlePowerAction(action PowerAction, waitSeconds ...int) error
func (s *Server) onBeforeStart() error { func (s *Server) onBeforeStart() error {
s.Log().Info("syncing server configuration with panel") s.Log().Info("syncing server configuration with panel")
if err := s.Sync(); err != nil { if err := s.Sync(); err != nil {
return errors.Wrap(err, "unable to sync server data from Panel instance") return errors.WrapIf(err, "unable to sync server data from Panel instance")
} }
// Disallow start & restart if the server is suspended. Do this check after performing a sync // Disallow start & restart if the server is suspended. Do this check after performing a sync
@ -185,7 +185,7 @@ func (s *Server) onBeforeStart() error {
s.PublishConsoleOutputFromDaemon("Ensuring file permissions are set correctly, this could take a few seconds...") s.PublishConsoleOutputFromDaemon("Ensuring file permissions are set correctly, this could take a few seconds...")
// Ensure all of the server file permissions are set correctly before booting the process. // Ensure all of the server file permissions are set correctly before booting the process.
if err := s.Filesystem().Chown("/"); err != nil { if err := s.Filesystem().Chown("/"); err != nil {
return errors.Wrap(err, "failed to chown root server directory during pre-boot process") return errors.WrapIf(err, "failed to chown root server directory during pre-boot process")
} }
} }

View File

@ -2,9 +2,9 @@ package server
import ( import (
"context" "context"
"emperror.dev/errors"
"fmt" "fmt"
"github.com/apex/log" "github.com/apex/log"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api" "github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
@ -115,7 +115,7 @@ func (s *Server) Sync() error {
cfg, err := api.New().GetServerConfiguration(s.Id()) cfg, err := api.New().GetServerConfiguration(s.Id())
if err != nil { if err != nil {
if !api.IsRequestError(err) { if !api.IsRequestError(err) {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
if err.(*api.RequestError).Status == "404" { if err.(*api.RequestError).Status == "404" {
@ -131,7 +131,7 @@ func (s *Server) Sync() error {
func (s *Server) SyncWithConfiguration(cfg api.ServerConfigurationResponse) error { func (s *Server) SyncWithConfiguration(cfg api.ServerConfigurationResponse) error {
// Update the data structure and persist it to the disk. // Update the data structure and persist it to the disk.
if err := s.UpdateDataStructure(cfg.Settings); err != nil { if err := s.UpdateDataStructure(cfg.Settings); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
s.Lock() s.Lock()
@ -171,7 +171,7 @@ func (s *Server) IsBootable() bool {
func (s *Server) CreateEnvironment() error { func (s *Server) CreateEnvironment() error {
// Ensure the data directory exists before getting too far through this process. // Ensure the data directory exists before getting too far through this process.
if err := s.EnsureDataDirectoryExists(); err != nil { if err := s.EnsureDataDirectoryExists(); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return s.Environment.Create() return s.Environment.Create()

View File

@ -1,8 +1,8 @@
package server package server
import ( import (
"emperror.dev/errors"
"encoding/json" "encoding/json"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
"io" "io"
@ -22,14 +22,14 @@ func CachedServerStates() (map[string]string, error) {
// Open the states file. // Open the states file.
f, err := os.OpenFile(config.Get().System.GetStatesPath(), os.O_RDONLY|os.O_CREATE, 0644) f, err := os.OpenFile(config.Get().System.GetStatesPath(), os.O_RDONLY|os.O_CREATE, 0644)
if err != nil { if err != nil {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
defer f.Close() defer f.Close()
// Convert the json object to a map. // Convert the json object to a map.
states := map[string]string{} states := map[string]string{}
if err := json.NewDecoder(f).Decode(&states); err != nil && err != io.EOF { if err := json.NewDecoder(f).Decode(&states); err != nil && err != io.EOF {
return nil, errors.WithStack(err) return nil, errors.WithStackIf(err)
} }
return states, nil return states, nil
@ -46,7 +46,7 @@ func saveServerStates() error {
// Convert the map to a json object. // Convert the map to a json object.
data, err := json.Marshal(states) data, err := json.Marshal(states)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
stateMutex.Lock() stateMutex.Lock()
@ -54,7 +54,7 @@ func saveServerStates() error {
// Write the data to the file // Write the data to the file
if err := ioutil.WriteFile(config.Get().System.GetStatesPath(), data, 0644); err != nil { if err := ioutil.WriteFile(config.Get().System.GetStatesPath(), data, 0644); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
return nil return nil

View File

@ -1,10 +1,10 @@
package server package server
import ( import (
"emperror.dev/errors"
"encoding/json" "encoding/json"
"github.com/buger/jsonparser" "github.com/buger/jsonparser"
"github.com/imdario/mergo" "github.com/imdario/mergo"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/environment" "github.com/pterodactyl/wings/environment"
) )
@ -18,7 +18,7 @@ import (
func (s *Server) UpdateDataStructure(data []byte) error { func (s *Server) UpdateDataStructure(data []byte) error {
src := new(Configuration) src := new(Configuration)
if err := json.Unmarshal(data, src); err != nil { if err := json.Unmarshal(data, src); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// Don't allow obviously corrupted data to pass through into this function. If the UUID // Don't allow obviously corrupted data to pass through into this function. If the UUID
@ -47,7 +47,7 @@ func (s *Server) UpdateDataStructure(data []byte) error {
// Merge the new data object that we have received with the existing server data object // Merge the new data object that we have received with the existing server data object
// and then save it to the disk so it is persistent. // and then save it to the disk so it is persistent.
if err := mergo.Merge(&c, src, mergo.WithOverride); err != nil { if err := mergo.Merge(&c, src, mergo.WithOverride); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// Don't explode if we're setting CPU limits to 0. Mergo sees that as an empty value // Don't explode if we're setting CPU limits to 0. Mergo sees that as an empty value
@ -65,7 +65,7 @@ func (s *Server) UpdateDataStructure(data []byte) error {
// request is going to be boolean. Allegedly. // request is going to be boolean. Allegedly.
if v, err := jsonparser.GetBoolean(data, "container", "oom_disabled"); err != nil { if v, err := jsonparser.GetBoolean(data, "container", "oom_disabled"); err != nil {
if err != jsonparser.KeyPathNotFoundError { if err != jsonparser.KeyPathNotFoundError {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
} else { } else {
c.Build.OOMDisabled = v c.Build.OOMDisabled = v
@ -74,7 +74,7 @@ func (s *Server) UpdateDataStructure(data []byte) error {
// Mergo also cannot handle this boolean value. // Mergo also cannot handle this boolean value.
if v, err := jsonparser.GetBoolean(data, "suspended"); err != nil { if v, err := jsonparser.GetBoolean(data, "suspended"); err != nil {
if err != jsonparser.KeyPathNotFoundError { if err != jsonparser.KeyPathNotFoundError {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
} else { } else {
c.Suspended = v c.Suspended = v
@ -82,7 +82,7 @@ func (s *Server) UpdateDataStructure(data []byte) error {
if v, err := jsonparser.GetBoolean(data, "skip_egg_scripts"); err != nil { if v, err := jsonparser.GetBoolean(data, "skip_egg_scripts"); err != nil {
if err != jsonparser.KeyPathNotFoundError { if err != jsonparser.KeyPathNotFoundError {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
} else { } else {
c.SkipEggScripts = v c.SkipEggScripts = v

View File

@ -7,7 +7,7 @@ import (
) )
type WebsocketBag struct { type WebsocketBag struct {
mu sync.Mutex mu sync.Mutex
conns map[uuid.UUID]*context.CancelFunc conns map[uuid.UUID]*context.CancelFunc
} }
@ -58,4 +58,4 @@ func (w *WebsocketBag) CancelAll() {
// Reset the connections. // Reset the connections.
w.conns = make(map[uuid.UUID]*context.CancelFunc) w.conns = make(map[uuid.UUID]*context.CancelFunc)
} }

View File

@ -1,9 +1,9 @@
package sftp package sftp
import ( import (
"emperror.dev/errors"
"github.com/apex/log" "github.com/apex/log"
"github.com/patrickmn/go-cache" "github.com/patrickmn/go-cache"
"github.com/pkg/errors"
"github.com/pkg/sftp" "github.com/pkg/sftp"
"io" "io"
"io/ioutil" "io/ioutil"
@ -58,14 +58,14 @@ func (fs FileSystem) Fileread(request *sftp.Request) (io.ReaderAt, error) {
if _, err := os.Stat(p); os.IsNotExist(err) { if _, err := os.Stat(p); os.IsNotExist(err) {
return nil, sftp.ErrSshFxNoSuchFile return nil, sftp.ErrSshFxNoSuchFile
} else if err != nil { } else if err != nil {
fs.logger.WithField("error", errors.WithStack(err)).Error("error while processing file stat") fs.logger.WithField("error", errors.WithStackIf(err)).Error("error while processing file stat")
return nil, sftp.ErrSshFxFailure return nil, sftp.ErrSshFxFailure
} }
file, err := os.Open(p) file, err := os.Open(p)
if err != nil { if err != nil {
fs.logger.WithField("source", p).WithField("error", errors.WithStack(err)).Error("could not open file for reading") fs.logger.WithField("source", p).WithField("error", errors.WithStackIf(err)).Error("could not open file for reading")
return nil, sftp.ErrSshFxFailure return nil, sftp.ErrSshFxFailure
} }
@ -108,7 +108,7 @@ func (fs FileSystem) Filewrite(request *sftp.Request) (io.WriterAt, error) {
if err := os.MkdirAll(filepath.Dir(p), 0755); err != nil { if err := os.MkdirAll(filepath.Dir(p), 0755); err != nil {
l.WithFields(log.Fields{ l.WithFields(log.Fields{
"path": filepath.Dir(p), "path": filepath.Dir(p),
"error": errors.WithStack(err), "error": errors.WithStackIf(err),
}).Error("error making path for file") }).Error("error making path for file")
return nil, sftp.ErrSshFxFailure return nil, sftp.ErrSshFxFailure
@ -116,7 +116,7 @@ func (fs FileSystem) Filewrite(request *sftp.Request) (io.WriterAt, error) {
file, err := os.Create(p) file, err := os.Create(p)
if err != nil { if err != nil {
l.WithField("error", errors.WithStack(err)).Error("failed to create file") l.WithField("error", errors.WithStackIf(err)).Error("failed to create file")
return nil, sftp.ErrSshFxFailure return nil, sftp.ErrSshFxFailure
} }
@ -124,7 +124,7 @@ func (fs FileSystem) Filewrite(request *sftp.Request) (io.WriterAt, error) {
// Not failing here is intentional. We still made the file, it is just owned incorrectly // Not failing here is intentional. We still made the file, it is just owned incorrectly
// and will likely cause some issues. // and will likely cause some issues.
if err := os.Chown(p, fs.User.Uid, fs.User.Gid); err != nil { if err := os.Chown(p, fs.User.Uid, fs.User.Gid); err != nil {
l.WithField("error", errors.WithStack(err)).Warn("failed to set permissions on file") l.WithField("error", errors.WithStackIf(err)).Warn("failed to set permissions on file")
} }
return file, nil return file, nil
@ -133,7 +133,7 @@ func (fs FileSystem) Filewrite(request *sftp.Request) (io.WriterAt, error) {
// If the stat error isn't about the file not existing, there is some other issue // If the stat error isn't about the file not existing, there is some other issue
// at play and we need to go ahead and bail out of the process. // at play and we need to go ahead and bail out of the process.
if statErr != nil { if statErr != nil {
l.WithField("error", errors.WithStack(statErr)).Error("encountered error performing file stat") l.WithField("error", errors.WithStackIf(statErr)).Error("encountered error performing file stat")
return nil, sftp.ErrSshFxFailure return nil, sftp.ErrSshFxFailure
} }
@ -159,14 +159,14 @@ func (fs FileSystem) Filewrite(request *sftp.Request) (io.WriterAt, error) {
return nil, sftp.ErrSSHFxNoSuchFile return nil, sftp.ErrSSHFxNoSuchFile
} }
l.WithField("flags", request.Flags).WithField("error", errors.WithStack(err)).Error("failed to open existing file on system") l.WithField("flags", request.Flags).WithField("error", errors.WithStackIf(err)).Error("failed to open existing file on system")
return nil, sftp.ErrSshFxFailure return nil, sftp.ErrSshFxFailure
} }
// Not failing here is intentional. We still made the file, it is just owned incorrectly // Not failing here is intentional. We still made the file, it is just owned incorrectly
// and will likely cause some issues. // and will likely cause some issues.
if err := os.Chown(p, fs.User.Uid, fs.User.Gid); err != nil { if err := os.Chown(p, fs.User.Uid, fs.User.Gid); err != nil {
l.WithField("error", errors.WithStack(err)).Warn("error chowning file") l.WithField("error", errors.WithStackIf(err)).Warn("error chowning file")
} }
return file, nil return file, nil
@ -220,7 +220,7 @@ func (fs FileSystem) Filecmd(request *sftp.Request) error {
return sftp.ErrSSHFxNoSuchFile return sftp.ErrSSHFxNoSuchFile
} }
l.WithField("error", errors.WithStack(err)).Error("failed to perform setstat on item") l.WithField("error", errors.WithStackIf(err)).Error("failed to perform setstat on item")
return sftp.ErrSSHFxFailure return sftp.ErrSSHFxFailure
} }
return nil return nil
@ -234,7 +234,7 @@ func (fs FileSystem) Filecmd(request *sftp.Request) error {
return sftp.ErrSSHFxNoSuchFile return sftp.ErrSSHFxNoSuchFile
} }
l.WithField("target", target).WithField("error", errors.WithStack(err)).Error("failed to rename file") l.WithField("target", target).WithField("error", errors.WithStackIf(err)).Error("failed to rename file")
return sftp.ErrSshFxFailure return sftp.ErrSshFxFailure
} }
@ -246,7 +246,7 @@ func (fs FileSystem) Filecmd(request *sftp.Request) error {
} }
if err := os.RemoveAll(p); err != nil { if err := os.RemoveAll(p); err != nil {
l.WithField("error", errors.WithStack(err)).Error("failed to remove directory") l.WithField("error", errors.WithStackIf(err)).Error("failed to remove directory")
return sftp.ErrSshFxFailure return sftp.ErrSshFxFailure
} }
@ -258,7 +258,7 @@ func (fs FileSystem) Filecmd(request *sftp.Request) error {
} }
if err := os.MkdirAll(p, 0755); err != nil { if err := os.MkdirAll(p, 0755); err != nil {
l.WithField("error", errors.WithStack(err)).Error("failed to create directory") l.WithField("error", errors.WithStackIf(err)).Error("failed to create directory")
return sftp.ErrSshFxFailure return sftp.ErrSshFxFailure
} }
@ -270,7 +270,7 @@ func (fs FileSystem) Filecmd(request *sftp.Request) error {
} }
if err := os.Symlink(p, target); err != nil { if err := os.Symlink(p, target); err != nil {
l.WithField("target", target).WithField("error", errors.WithStack(err)).Error("failed to create symlink") l.WithField("target", target).WithField("error", errors.WithStackIf(err)).Error("failed to create symlink")
return sftp.ErrSshFxFailure return sftp.ErrSshFxFailure
} }
@ -286,7 +286,7 @@ func (fs FileSystem) Filecmd(request *sftp.Request) error {
return sftp.ErrSSHFxNoSuchFile return sftp.ErrSSHFxNoSuchFile
} }
l.WithField("error", errors.WithStack(err)).Error("failed to remove a file") l.WithField("error", errors.WithStackIf(err)).Error("failed to remove a file")
return sftp.ErrSshFxFailure return sftp.ErrSshFxFailure
} }
@ -305,7 +305,7 @@ func (fs FileSystem) Filecmd(request *sftp.Request) error {
// and will likely cause some issues. There is no logical check for if the file was removed // and will likely cause some issues. There is no logical check for if the file was removed
// because both of those cases (Rmdir, Remove) have an explicit return rather than break. // because both of those cases (Rmdir, Remove) have an explicit return rather than break.
if err := os.Chown(fileLocation, fs.User.Uid, fs.User.Gid); err != nil { if err := os.Chown(fileLocation, fs.User.Uid, fs.User.Gid); err != nil {
l.WithField("error", errors.WithStack(err)).Warn("error chowning file") l.WithField("error", errors.WithStackIf(err)).Warn("error chowning file")
} }
return sftp.ErrSshFxOk return sftp.ErrSshFxOk
@ -327,7 +327,7 @@ func (fs FileSystem) Filelist(request *sftp.Request) (sftp.ListerAt, error) {
files, err := ioutil.ReadDir(p) files, err := ioutil.ReadDir(p)
if err != nil { if err != nil {
fs.logger.WithField("error", errors.WithStack(err)).Error("error while listing directory") fs.logger.WithField("error", errors.WithStackIf(err)).Error("error while listing directory")
return nil, sftp.ErrSshFxFailure return nil, sftp.ErrSshFxFailure
} }
@ -342,7 +342,7 @@ func (fs FileSystem) Filelist(request *sftp.Request) (sftp.ListerAt, error) {
if os.IsNotExist(err) { if os.IsNotExist(err) {
return nil, sftp.ErrSshFxNoSuchFile return nil, sftp.ErrSshFxNoSuchFile
} else if err != nil { } else if err != nil {
fs.logger.WithField("source", p).WithField("error", errors.WithStack(err)).Error("error performing stat on file") fs.logger.WithField("source", p).WithField("error", errors.WithStackIf(err)).Error("error performing stat on file")
return nil, sftp.ErrSshFxFailure return nil, sftp.ErrSshFxFailure
} }

View File

@ -1,8 +1,8 @@
package sftp package sftp
import ( import (
"emperror.dev/errors"
"github.com/apex/log" "github.com/apex/log"
"github.com/pkg/errors"
"github.com/pterodactyl/wings/api" "github.com/pterodactyl/wings/api"
"github.com/pterodactyl/wings/config" "github.com/pterodactyl/wings/config"
"github.com/pterodactyl/wings/server" "github.com/pterodactyl/wings/server"
@ -28,14 +28,14 @@ func Initialize(config config.SystemConfiguration) error {
} }
if err := New(s); err != nil { if err := New(s); err != nil {
return errors.WithStack(err) return errors.WithStackIf(err)
} }
// Initialize the SFTP server in a background thread since this is // Initialize the SFTP server in a background thread since this is
// a long running operation. // a long running operation.
go func(s *Server) { go func(s *Server) {
if err := s.Initialize(); err != nil { if err := s.Initialize(); err != nil {
log.WithField("subsystem", "sftp").WithField("error", errors.WithStack(err)).Error("failed to initialize SFTP subsystem") log.WithField("subsystem", "sftp").WithField("error", errors.WithStackIf(err)).Error("failed to initialize SFTP subsystem")
} }
}(s) }(s)