Where os.File implements FileInfo()?

Hi,

I was searching about how to unzip files with go and trying to understand what’s happening on the code, I’ve get stucked on this step: f.FileInfo().

Where’s the implementation of FileInfo() function from os.File?

I’ve searched on go repository at github without success, somebody can help me indicating the location?

Here’s the code I’m using as base (from https://golangcode.com/unzip-files-in-go/)

package main

import (
    "archive/zip"
    "fmt"
    "io"
    "log"
    "os"
    "path/filepath"
    "strings"
)

func main() {

    files, err := Unzip("done.zip", "output-folder")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println("Unzipped:\n" + strings.Join(files, "\n"))
}

// Unzip will decompress a zip archive, moving all files and folders
// within the zip file (parameter 1) to an output directory (parameter 2).
func Unzip(src string, dest string) ([]string, error) {

    var filenames []string

    r, err := zip.OpenReader(src)
    if err != nil {
        return filenames, err
    }
    defer r.Close()

    for _, f := range r.File {

        // Store filename/path for returning and using later on
        fpath := filepath.Join(dest, f.Name)

        // Check for ZipSlip. More Info: http://bit.ly/2MsjAWE
        if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
            return filenames, fmt.Errorf("%s: illegal file path", fpath)
        }

        filenames = append(filenames, fpath)

        if f.FileInfo().IsDir() {
            // Make Folder
            os.MkdirAll(fpath, os.ModePerm)
            continue
        }

        // Make File
        if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
            return filenames, err
        }

        outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
        if err != nil {
            return filenames, err
        }

        rc, err := f.Open()
        if err != nil {
            return filenames, err
        }

        _, err = io.Copy(outFile, rc)

        // Close the file without defer to close before next iteration of loop
        outFile.Close()
        rc.Close()

        if err != nil {
            return filenames, err
        }
    }
    return filenames, nil
}

1 Like

FileInfo is an interface

type FileInfo interface {
    Name() string       // base name of the file
    Size() int64        // length in bytes for regular files; system-dependent for others
    Mode() FileMode     // file mode bits
    ModTime() time.Time // modification time
    IsDir() bool        // abbreviation for Mode().IsDir()
    Sys() interface{}   // underlying data source (can return nil)
}
1 Like

Yes, but file doesn’t implement this interface (https://github.com/golang/go/blob/release-branch.go1.13/src/os/types.go#L16)

// File represents an open file descriptor.
type File struct {
	*file // os specific
}

Neither on https://github.com/golang/go/blob/release-branch.go1.13/src/os/file_unix.go#L45:

// file is the real representation of *File.
// The extra level of indirection ensures that no clients of os
// can overwrite this data, which could cause the finalizer
// to close the wrong file descriptor.
type file struct {
	pfd         poll.FD
	name        string
	dirinfo     *dirInfo // nil unless directory being read
	nonblock    bool     // whether we set nonblocking mode
	stdoutOrErr bool     // whether this is stdout or stderr
	appendMode  bool     // whether file is opened for appending
}

How can I call a interface as a function without implement their functions?

1 Like

It something like

zip 
  FileHeader
    FileInfoHeader  
	   FileHeader  
	      FileInfo
1 Like

Oh sorry, I’ve misunderstood the docs, I’ve thought the struct Reader (implemented by ReadCloser from archive/zip) use os.File but it’s using File from archive/zip (which implements the FileHeader, as suggested)

type Reader struct {
        r             io.ReaderAt
        File          []*File
        Comment       string
        decompressors map[uint16]Decompressor
}

type ReadCloser struct {
        f *os.File
        Reader
}

type File struct {
        FileHeader
        zip          *Reader
        zipr         io.ReaderAt
        zipsize      int64
        headerOffset int64
}

Thanks!

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.