misc/getfiles: fix infinite recursion loop when given a symlink

This fixes an infinite recursion loop in getFile caused by:

1) `os.Stat(file)` resolves a symlink so that `fileInfo.isDir()` returns True
2) `filepath.Walk()` starts iterating on the root directory (in this case the symlink)
3) `filepath.Walk()` uses `os.Lstat` internally, which does NOT dereference the symlink
4) in the walk func, `f.isDir()` returns False, and the walk func calls `getFile()` on it
5) goto 1

fixes #47

Part-of: https://gitlab.postmarketos.org/postmarketOS/postmarketos-mkinitfs/-/merge_requests/65
This commit is contained in:
Clayton Craft
2025-08-01 23:23:07 -07:00
parent 4f6af31a7a
commit 7a07a16ecb

View File

@@ -3,6 +3,7 @@ package misc
import (
"debug/elf"
"fmt"
"io/fs"
"os"
"path/filepath"
@@ -39,6 +40,24 @@ func getFile(file string, required bool) (files []string, err error) {
return RemoveDuplicates(files), nil
}
// If the file is a symlink we need to do this to prevent an infinite recursion
// loop:
// Symlinks need special handling to prevent infinite recursion:
// 1) add the symlink to the list of files
// 2) set file to dereferenced target
// 4) continue this function to either walk it if the target is a dir or add the
// target to the list of files
if s, err := os.Lstat(file); err != nil {
return files, err
} else if s.Mode()&fs.ModeSymlink != 0 {
files = append(files, file)
if target, err := filepath.EvalSymlinks(file); err != nil {
return files, err
} else {
file = target
}
}
fileInfo, err := os.Stat(file)
if err != nil {
// Check if there is a Zstd-compressed version of the file