statik icon indicating copy to clipboard operation
statik copied to clipboard

Symlinks are not properly handled

Open a2800276 opened this issue 4 years ago • 0 comments

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).

a2800276 avatar Oct 18 '20 14:10 a2800276