138 lines
2.8 KiB
Go
138 lines
2.8 KiB
Go
package squashfs
|
|
|
|
import (
|
|
"io"
|
|
"io/fs"
|
|
"time"
|
|
|
|
"github.com/CalebQ42/squashfs/internal/directory"
|
|
"github.com/CalebQ42/squashfs/internal/inode"
|
|
)
|
|
|
|
//DirEntry is a child of a directory.
|
|
type DirEntry struct {
|
|
en *directory.Entry
|
|
parent *FS
|
|
r *Reader
|
|
}
|
|
|
|
func (r *Reader) newDirEntry(en *directory.Entry, parent *FS) *DirEntry {
|
|
return &DirEntry{
|
|
en: en,
|
|
parent: parent,
|
|
r: r,
|
|
}
|
|
}
|
|
|
|
//Name returns the DirEntry's name
|
|
func (d DirEntry) Name() string {
|
|
return d.en.Name
|
|
}
|
|
|
|
//IsDir Yep.
|
|
func (d DirEntry) IsDir() bool {
|
|
return d.en.Type == inode.DirType
|
|
}
|
|
|
|
//Type returns the type bits of fs.FileMode of the DirEntry.
|
|
func (d DirEntry) Type() fs.FileMode {
|
|
switch d.en.Type {
|
|
case inode.DirType:
|
|
return fs.ModeDir
|
|
case inode.SymType:
|
|
return fs.ModeSymlink
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
//Info returns the fs.FileInfo for the given DirEntry.
|
|
func (d DirEntry) Info() (fs.FileInfo, error) {
|
|
in, err := d.r.getInodeFromEntry(d.en)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &FileInfo{
|
|
name: d.en.Name,
|
|
i: in,
|
|
parent: d.parent,
|
|
r: d.r,
|
|
}, nil
|
|
}
|
|
|
|
//GetInodeFromEntry returns the inode associated with a given directory.Entry
|
|
func (r *Reader) getInodeFromEntry(en *directory.Entry) (*inode.Inode, error) {
|
|
br, err := r.newMetadataReader(int64(r.super.InodeTableStart + uint64(en.InodeOffset)))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
_, err = br.Seek(int64(en.InodeBlockOffset), io.SeekStart)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
i, err := inode.ProcessInode(br, r.super.BlockSize)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return i, nil
|
|
}
|
|
|
|
//FileInfo is a fs.FileInfo for a file.
|
|
type FileInfo struct {
|
|
i *inode.Inode
|
|
parent *FS
|
|
r *Reader
|
|
name string
|
|
}
|
|
|
|
//Name is the file's name.
|
|
func (f FileInfo) Name() string {
|
|
return f.name
|
|
}
|
|
|
|
//Size is the file's size if it's a regular file. Otherwise, returns 0.
|
|
func (f FileInfo) Size() int64 {
|
|
switch f.i.Type {
|
|
case inode.FileType:
|
|
return int64(f.i.Info.(inode.File).Size)
|
|
case inode.ExtFileType:
|
|
return int64(f.i.Info.(inode.ExtFile).Size)
|
|
}
|
|
return 0
|
|
}
|
|
|
|
//Mode returns the fs.FileMode bits of the file.
|
|
func (f FileInfo) Mode() fs.FileMode {
|
|
mode := fs.FileMode(f.i.Permissions)
|
|
switch f.i.Type {
|
|
case inode.DirType | inode.ExtDirType:
|
|
return mode | fs.ModeDir
|
|
case inode.ExtDirType:
|
|
return mode | fs.ModeDir
|
|
case inode.SymType:
|
|
return mode | fs.ModeSymlink
|
|
case inode.ExtSymType:
|
|
return mode | fs.ModeSymlink
|
|
}
|
|
return mode
|
|
}
|
|
|
|
//ModTime is the last time the file was modified.
|
|
func (f FileInfo) ModTime() time.Time {
|
|
return time.Unix(int64(f.i.ModifiedTime), 0)
|
|
}
|
|
|
|
//IsDir yep.
|
|
func (f FileInfo) IsDir() bool {
|
|
return f.i.Type == inode.DirType || f.i.Type == inode.ExtDirType
|
|
}
|
|
|
|
//Sys returns the File for the FileInfo. If something goes wrong, nil is returned.
|
|
func (f FileInfo) Sys() interface{} {
|
|
fil, err := f.File()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return fil
|
|
}
|