diff --git a/backend/local/local.go b/backend/local/local.go index 7cb11ad45..9b3aa7b76 100644 --- a/backend/local/local.go +++ b/backend/local/local.go @@ -456,8 +456,8 @@ func (f *Fs) List(ctx context.Context, dir string) (entries fs.DirEntries, err e if f.opt.FollowSymlinks && (mode&os.ModeSymlink) != 0 { localPath := filepath.Join(fsDirPath, name) fi, err = os.Stat(localPath) - if os.IsNotExist(err) { - // Skip bad symlinks + if os.IsNotExist(err) || isCircularSymlinkError(err) { + // Skip bad symlinks and circular symlinks err = fserrors.NoRetryError(errors.Wrap(err, "symlink")) fs.Errorf(newRemote, "Listing error: %v", err) err = accounting.Stats(ctx).Error(err) diff --git a/backend/local/symlink.go b/backend/local/symlink.go new file mode 100644 index 000000000..cf49c7282 --- /dev/null +++ b/backend/local/symlink.go @@ -0,0 +1,22 @@ +// +build !windows,!plan9,!js + +package local + +import ( + "os" + "syscall" +) + +// isCircularSymlinkError checks if the current error code is because of a circular symlink +func isCircularSymlinkError(err error) bool { + if err != nil { + if newerr, ok := err.(*os.PathError); ok { + if errcode, ok := newerr.Err.(syscall.Errno); ok { + if errcode == syscall.ELOOP { + return true + } + } + } + } + return false +} diff --git a/backend/local/symlink_other.go b/backend/local/symlink_other.go new file mode 100644 index 000000000..36e012768 --- /dev/null +++ b/backend/local/symlink_other.go @@ -0,0 +1,17 @@ +// +build windows plan9 js + +package local + +import ( + "strings" +) + +// isCircularSymlinkError checks if the current error code is because of a circular symlink +func isCircularSymlinkError(err error) bool { + if err != nil { + if strings.Contains(err.Error(), "The name of the file cannot be resolved by the system") { + return true + } + } + return false +}