afero icon indicating copy to clipboard operation
afero copied to clipboard

zipfs cannot read some directories

Open HartBlanc opened this issue 3 years ago • 0 comments

Problem

As far as I can tell the zipfs.Fs backend is intended to behave similarly to a BasePathFs which references an OsFs.

i.e. if your application supports providing input as a zip archive or as a directory - then the application should be able to use a BasePathFs or a zipfs.Fs without excessive consideration of which FS implementation has been used (based on the discussion in #146 and the source in the referenced spyre project repo).

However, there are cases where the filesystems behaviour differs:

Directory with no explicit entry in zip archive

Steps to reproduce

  1. Create a directory with the following structure at /path/to/dir:
subdir_a/
├─ a_file.yaml
  1. Create an archive of the same directory at /path/to/dir.zip using cd /path/to/dir; zip ..dir.zip subdir_a/a_file.yaml. This creates an archive with a single entry. Note that while there is no explicit entry for subdir_a/, if the archive is unzipped the resulting directory is identical to /path/to/dir.
  2. Run the following code
package main

import (
	"archive/zip"
	"fmt"

	"github.com/spf13/afero"
	"github.com/spf13/afero/zipfs"
)

func main() {
	bpFS := afero.NewBasePathFs(afero.NewOsFs(), "/path/to/dir")
	files, err := afero.ReadDir(bpFS, "/")
	fmt.Printf("num_files: %v, err: %v\n", len(files), err)

	zrc, err := zip.OpenReader("/path/to/dir.zip")
	zipFS := zipfs.New(&zrc.Reader)
	files, err = afero.ReadDir(zipFS, "/")
	fmt.Printf("num_files: %v, err: %v\n", len(files), err)
}

Expected Output

num_files: 1, err: <nil>
num_files: 1, err: <nil>

Actual Output

num_files: 1, err: <nil>
num_files: 0, err: readdir /: no such file or directory

Empty zip file

Steps to reproduce

  1. Create an empty directory at /path/to/empty
  2. Create an empty archive of the same directory at /path/to/empty.zip by creating an archive with a single file and then deleting the file:
zip empty.zip anyfile
zip -d empty.zip anyfile
  1. Run the following code
package main

import (
	"archive/zip"
	"fmt"

	"github.com/spf13/afero"
	"github.com/spf13/afero/zipfs"
)

func main() {
	bpFS := afero.NewBasePathFs(afero.NewOsFs(), "/path/to/empty")
	files, err := afero.ReadDir(bpFS, "/")
	fmt.Printf("num_files: %v, err: %v\n", len(files), err)

	zrc, err := zip.OpenReader("/path/to/empty.zip")
	zipFS := zipfs.New(&zrc.Reader)
	files, err = afero.ReadDir(zipFS, "/")
	fmt.Printf("num_files: %v, err: %v\n", len(files), err)
}

Expected Output

num_files: 0, err: <nil>
num_files: 0, err: <nil>

Actual Output

num_files: 0, err: <nil>
num_files: 0, err: readdir /: no such file or directory

HartBlanc avatar Sep 02 '21 09:09 HartBlanc