Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions internal/ufs/fs_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,30 @@ func (fs *UnixFS) OpenFileat(dirfd int, name string, flag int, mode FileMode) (F
return os.NewFile(uintptr(fd), name), nil
}

// Readlinkat reads the destination of the named symbolic link.
//
// If the file is not a symbolic link, it will return an error.
// This is like Readlink but allows passing an existing directory file
// descriptor rather than needing to resolve one.
//
// If there is an error, it will be of type *PathError.
func (fs *UnixFS) Readlinkat(dirfd int, name string) (string, error) {
// Automatically guess the buffer size
for size := 128; ; size *= 2 {
buf := make([]byte, size)
n, err := unix.Readlinkat(dirfd, name, buf)
if err != nil {
return "", err
}

if n < size {
return string(buf[:n]), nil
}

// Continue if buffer size is too small
}
}

// ReadDir reads the named directory,
//
// returning all its directory entries sorted by filename.
Expand Down
12 changes: 11 additions & 1 deletion server/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"emperror.dev/errors"
"github.com/apex/log"
"github.com/docker/docker/client"
"github.com/mholt/archives"

"github.com/pterodactyl/wings/environment"
"github.com/pterodactyl/wings/remote"
Expand Down Expand Up @@ -151,9 +152,18 @@ func (s *Server) RestoreBackup(b backup.BackupInterface, reader io.ReadCloser) (
// Attempt to restore the backup to the server by running through each entry
// in the file one at a time and writing them to the disk.
s.Log().Debug("starting file writing process for backup restoration")
err = b.Restore(s.Context(), reader, func(file string, info fs.FileInfo, r io.ReadCloser) error {
err = b.Restore(s.Context(), reader, func(file string, info archives.FileInfo, r io.ReadCloser) error {
defer r.Close()
s.Events().Publish(DaemonMessageEvent, "(restoring): "+file)

// Handle symlinks
if info.Mode()&fs.ModeSymlink != 0 {
if err := s.Filesystem().Symlink(info.LinkTarget, file); err != nil {
return err
}
return nil
}

// TODO: since this will be called a lot, it may be worth adding an optimized
// Write with Chtimes method to the UnixFS that is able to re-use the
// same dirfd and file name.
Expand Down
3 changes: 1 addition & 2 deletions server/backup/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"crypto/sha1"
"encoding/hex"
"io"
"io/fs"
"os"
"path"

Expand Down Expand Up @@ -34,7 +33,7 @@ const (

// RestoreCallback is a generic restoration callback that exists for both local
// and remote backups allowing the files to be restored.
type RestoreCallback func(file string, info fs.FileInfo, r io.ReadCloser) error
type RestoreCallback func(file string, info archives.FileInfo, r io.ReadCloser) error

// noinspection GoNameStartsWithPackageName
type BackupInterface interface {
Expand Down
2 changes: 1 addition & 1 deletion server/backup/backup_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (b *LocalBackup) Restore(ctx context.Context, _ io.Reader, callback Restore
}
defer r.Close()

return callback(f.NameInArchive, f.FileInfo, r)
return callback(f.NameInArchive, f, r)
}); err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion server/backup/backup_s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func (s *S3Backup) Restore(ctx context.Context, r io.Reader, callback RestoreCal
}
defer r.Close()

return callback(f.NameInArchive, f.FileInfo, r)
return callback(f.NameInArchive, f, r)
}); err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion server/filesystem/archive.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ func (a *Archive) addToArchive(dirfd int, name, relative string, entry ufs.DirEn
// the logs, but we're not going to stop the backup. There are far too many cases of
// symlinks causing all sorts of unnecessary pain in this process. Sucks to suck if
// it doesn't work.
target, err = os.Readlink(s.Name())
target, err = a.Filesystem.unixFS.Readlinkat(dirfd, name)
if err != nil {
// Ignore the not exist errors specifically, since there is nothing important about that.
if !os.IsNotExist(err) {
Expand Down
9 changes: 9 additions & 0 deletions server/filesystem/compress.go
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,15 @@ func (fs *Filesystem) extractStream(ctx context.Context, opts extractStreamOptio
if err := fs.IsIgnored(p); err != nil {
return nil
}

// Handle symlinks
if f.Mode()&iofs.ModeSymlink != 0 {
if err := fs.Symlink(f.LinkTarget, p); err != nil {
return wrapError(err, opts.FileName)
}
return nil
}

r, err := f.Open()
if err != nil {
return err
Expand Down