statik
statik copied to clipboard
Symlinks are not properly handled
The generateSource
function in main package statik.go
is not handling symlinks correctly in all situations:
- on the one hand, symlinks to regular files work ok (-ish, see below) and are included into the embedding
- symlinks to directories cause failures that are hard to diagnose. While the WalkFunc ignores directory entries, it doesn't check whether the entry is a symlink and subsequently tries to read the entry. Reading fails and the program terminates with the confusing error message "read ${symlinked dir}: is a directory"
This is because WalkFunc injects a FileInfo that was generated by os.Lstat
which provides the link's FileInfo instead of os.Stat
describing the underlying file. Regular directory's response to IsDir
and are ignored, symlinked directories pass the directory check.
The immediate problem can be corrected with this patch:
diff --git a/statik.go b/statik.go
index 0b0ad29..92572c7 100644
--- a/statik.go
+++ b/statik.go
@@ -210,6 +210,19 @@ func generateSource(srcPath string, includes string) (file *os.File, err error)
if fi.IsDir() || strings.HasPrefix(fi.Name(), ".") {
return nil
}
+
+ if os.ModeSymlink == (fi.Mode() & os.ModeSymlink) {
+ fi_, err := os.Stat(path)
+ if err != nil {
+ return err
+ }
+ if fi_.IsDir() {
+ // warn that walk won't follow symlinked dir
+ // or, preferably, walk down manually.
+ return nil
+ }
+ }
+
relPath, err := filepath.Rel(srcPath, path)
if err != nil {
return err
But:
- at least in my expectation, symlinked dirs should be followed (this is problematic in itself because
filePath.Walk
does not follow symlinks ... - if however symlinks aren't followed, the user should be warned, regular symlinked files should arguably also not be embedded and finally, the modification time of the zip entry is incorrectly set to the mtime of the underlying file (currently it's set to the mtime of the symlink).