Skip to content

Commit 60c0ffe

Browse files
committed
fix: fix recursive symlinks
1 parent da6af1c commit 60c0ffe

File tree

8 files changed

+53
-4
lines changed

8 files changed

+53
-4
lines changed

helper/server/downstream.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"compress/gzip"
66
"context"
77
"github.com/loft-sh/devspace/helper/util/pingtimeout"
8+
"github.com/loft-sh/devspace/pkg/util/fsutil"
89
logpkg "github.com/loft-sh/devspace/pkg/util/log"
910
"io"
1011
"io/ioutil"
@@ -526,6 +527,9 @@ func walkDir(basePath string, path string, ignoreMatcher ignoreparser.IgnorePars
526527

527528
for _, f := range files {
528529
absolutePath := filepath.Join(path, f.Name())
530+
if fsutil.IsRecursiveSymlink(f, absolutePath) {
531+
continue
532+
}
529533

530534
// Stat is necessary here, because readdir does not follow symlinks and
531535
// IsDir() returns false for symlinked folders

helper/server/tar.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package server
33
import (
44
"archive/tar"
55
"compress/gzip"
6+
"github.com/loft-sh/devspace/pkg/util/fsutil"
67
"io"
78
"io/ioutil"
89
"os"
@@ -213,6 +214,10 @@ func tarFolder(basePath string, fileInformation *fileInformation, writtenFiles m
213214

214215
if !skipContents {
215216
for _, f := range files {
217+
if fsutil.IsRecursiveSymlink(f, path.Join(fileInformation.Name, f.Name())) {
218+
continue
219+
}
220+
216221
if err := recursiveTar(basePath, path.Join(fileInformation.Name, f.Name()), writtenFiles, tw, skipContents); err != nil {
217222
return errors.Wrap(err, "recursive tar")
218223
}

helper/server/upstream.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/loft-sh/devspace/helper/util/crc32"
99
"github.com/loft-sh/devspace/helper/util/pingtimeout"
1010
"github.com/loft-sh/devspace/helper/util/stderrlog"
11+
"github.com/loft-sh/devspace/pkg/util/fsutil"
1112
logpkg "github.com/loft-sh/devspace/pkg/util/log"
1213
"github.com/pkg/errors"
1314
"google.golang.org/grpc"
@@ -191,6 +192,9 @@ func (u *Upstream) removeRecursive(absolutePath string) error {
191192
// Loop over directory contents and check if we should delete the contents
192193
for _, f := range files {
193194
absoluteChildPath := filepath.Join(absolutePath, f.Name())
195+
if fsutil.IsRecursiveSymlink(f, absoluteChildPath) {
196+
continue
197+
}
194198

195199
// Check if ignored
196200
if u.ignoreMatcher != nil && !u.ignoreMatcher.RequireFullScan() && u.ignoreMatcher.Matches(absolutePath[len(u.options.UploadPath):], f.IsDir()) {

pkg/devspace/hook/upload.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package hook
33
import (
44
"archive/tar"
55
"compress/gzip"
6+
"github.com/loft-sh/devspace/pkg/util/fsutil"
67
"io"
78
"io/ioutil"
89
"os"
@@ -129,6 +130,10 @@ func recursiveTar(srcBase, srcFile, destBase, destFile string, tw *tar.Writer) e
129130
}
130131
}
131132
for _, f := range files {
133+
if fsutil.IsRecursiveSymlink(f, path.Join(fpath, f.Name())) {
134+
continue
135+
}
136+
132137
if err := recursiveTar(srcBase, path.Join(srcFile, f.Name()), destBase, path.Join(destFile, f.Name()), tw); err != nil {
133138
return err
134139
}

pkg/devspace/sync/downstream.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ package sync
33
import (
44
"context"
55
"fmt"
6+
"github.com/loft-sh/devspace/pkg/util/fsutil"
67
"io"
78
"io/ioutil"
89
"os"
10+
"path"
911
"path/filepath"
1012
"strings"
1113
"time"
@@ -437,6 +439,10 @@ func (d *downstream) deleteSafeRecursive(relativePath string, deleteChanges []*r
437439

438440
// Loop over directory contents and check if we should delete the contents
439441
for _, f := range files {
442+
if fsutil.IsRecursiveSymlink(f, path.Join(relativePath, f.Name())) {
443+
continue
444+
}
445+
440446
childRelativePath := filepath.ToSlash(filepath.Join(relativePath, f.Name()))
441447
childAbsFilepath := filepath.Join(d.sync.LocalPath, childRelativePath)
442448
if shouldRemoveLocal(childAbsFilepath, d.sync.fileIndex.fileMap[childRelativePath], d.sync, force) {

pkg/devspace/sync/initial.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package sync
22

33
import (
44
"github.com/loft-sh/devspace/helper/server/ignoreparser"
5+
"github.com/loft-sh/devspace/pkg/util/fsutil"
56
"io/ioutil"
67
"os"
78
"path"
@@ -356,6 +357,11 @@ func (i *initialSyncer) calculateLocalDirState(absPath string, stat os.FileInfo,
356357
}
357358

358359
for _, f := range files {
360+
if fsutil.IsRecursiveSymlink(f, filepath.Join(absPath, f.Name())) {
361+
i.o.Log.Debugf("Found recursive symlink at %v", filepath.Join(absPath, f.Name()))
362+
continue
363+
}
364+
359365
err := i.CalculateLocalState(filepath.Join(absPath, f.Name()), localState, ignore)
360366
if err != nil {
361367
return errors.Wrap(err, f.Name())

pkg/devspace/sync/tar.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package sync
33
import (
44
"archive/tar"
55
"compress/gzip"
6+
"github.com/loft-sh/devspace/pkg/util/fsutil"
67
"io"
78
"io/ioutil"
89
"os"
@@ -283,8 +284,8 @@ func (a *Archiver) AddToArchive(relativePath string) error {
283284
}
284285

285286
func (a *Archiver) tarFolder(target *FileInformation, targetStat os.FileInfo) error {
286-
filepath := path.Join(a.basePath, target.Name)
287-
files, err := ioutil.ReadDir(filepath)
287+
filePath := path.Join(a.basePath, target.Name)
288+
files, err := ioutil.ReadDir(filePath)
288289
if err != nil {
289290
// config.Logf("[Upstream] Couldn't read dir %s: %s\n", filepath, err.Error())
290291
return nil
@@ -294,7 +295,7 @@ func (a *Archiver) tarFolder(target *FileInformation, targetStat os.FileInfo) er
294295
// check if not excluded
295296
if a.ignoreMatcher == nil || !a.ignoreMatcher.RequireFullScan() || !a.ignoreMatcher.Matches(target.Name, true) {
296297
// Case empty directory
297-
hdr, _ := tar.FileInfoHeader(targetStat, filepath)
298+
hdr, _ := tar.FileInfoHeader(targetStat, filePath)
298299
hdr.Uid = 0
299300
hdr.Gid = 0
300301
hdr.Mode = fillGo18FileTypeBits(int64(chmodTarEntry(os.FileMode(hdr.Mode))), targetStat)
@@ -308,6 +309,10 @@ func (a *Archiver) tarFolder(target *FileInformation, targetStat os.FileInfo) er
308309
}
309310

310311
for _, f := range files {
312+
if fsutil.IsRecursiveSymlink(f, path.Join(filePath, f.Name())) {
313+
continue
314+
}
315+
311316
if err := a.AddToArchive(path.Join(target.Name, f.Name())); err != nil {
312317
return errors.Wrap(err, "recursive tar "+f.Name())
313318
}
@@ -325,7 +330,7 @@ func (a *Archiver) tarFile(target *FileInformation, targetStat os.FileInfo) erro
325330
}
326331

327332
targetStat, err = os.Stat(filepath)
328-
if err != nil {
333+
if err != nil || targetStat.IsDir() {
329334
// We ignore open file and just treat it as okay
330335
return nil
331336
}

pkg/util/fsutil/filesystem.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,20 @@ import (
1111
recursiveCopy "github.com/otiai10/copy"
1212
)
1313

14+
// IsRecursiveSymlink checks if the provided non-resolved file info
15+
// is a recursive symlink
16+
func IsRecursiveSymlink(f os.FileInfo, symlinkPath string) bool {
17+
// check if recursive symlink
18+
if f.Mode()&os.ModeSymlink == os.ModeSymlink {
19+
resolvedPath, err := filepath.EvalSymlinks(symlinkPath)
20+
if err != nil || strings.HasPrefix(symlinkPath, filepath.ToSlash(resolvedPath)) {
21+
return true
22+
}
23+
}
24+
25+
return false
26+
}
27+
1428
// WriteToFile writes data to a file
1529
func WriteToFile(data []byte, filePath string) error {
1630
err := os.MkdirAll(filepath.Dir(filePath), 0755)

0 commit comments

Comments
 (0)