-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfile.go
132 lines (106 loc) · 2.78 KB
/
file.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package squashfs
import (
"io"
"io/fs"
"path"
"time"
)
// File is a convience object allowing using an inode as if it was a regular file
type File struct {
*io.SectionReader
ino *Inode
name string
}
// FileDir is a convenience object allowing using a dir inode as if it was a regular file
type FileDir struct {
ino *Inode
name string
r *dirReader
}
type fileinfo struct {
ino *Inode
name string
}
// Ensure File respects fs.File & others
var _ fs.File = (*File)(nil)
var _ io.ReaderAt = (*File)(nil)
var _ fs.ReadDirFile = (*FileDir)(nil)
var _ fs.FileInfo = (*fileinfo)(nil)
// OpenFile returns a fs.File for a given inode. If the file is a directory, the returned object will implement
// fs.ReadDirFile. If it is a regular file it will also implement io.Seeker.
func (ino *Inode) OpenFile(name string) fs.File {
switch ino.Type {
case 1, 8:
return &FileDir{ino: ino, name: name}
default:
sec := io.NewSectionReader(ino, 0, int64(ino.Size))
return &File{SectionReader: sec, ino: ino, name: name}
}
}
// (File)
// Stat returns the details of the open file
func (f *File) Stat() (fs.FileInfo, error) {
return &fileinfo{name: path.Base(f.name), ino: f.ino}, nil
}
// Sys returns a *Inode object for this file
func (f *File) Sys() any {
return f.ino
}
// Close actually does nothing and exists to comply with fs.File
func (f *File) Close() error {
return nil
}
// (FileDir)
// Read on a directory is invalid and will always fail
func (d *FileDir) Read(p []byte) (int, error) {
return 0, fs.ErrInvalid
}
// Stat returns details on the file
func (d *FileDir) Stat() (fs.FileInfo, error) {
return &fileinfo{name: path.Base(d.name), ino: d.ino}, nil
}
// Sys returns a *inode object for this file, similar to calling Stat().Sys()
func (d *FileDir) Sys() any {
return d.ino
}
// Close resets the dir reader
func (d *FileDir) Close() error {
d.r = nil
return nil
}
func (d *FileDir) ReadDir(n int) ([]fs.DirEntry, error) {
if d.r == nil {
dr, err := d.ino.sb.dirReader(d.ino, nil)
if err != nil {
return nil, err
}
d.r = dr
}
return d.r.ReadDir(n)
}
// (fileinfo)
// Name returns the file's base name
func (fi *fileinfo) Name() string {
return fi.name
}
// Size returns the file's size
func (fi *fileinfo) Size() int64 {
return int64(fi.ino.Size)
}
// Mode returns the file's mode
func (fi *fileinfo) Mode() fs.FileMode {
return fi.ino.Mode()
}
// ModTime returns the file's latest modified time. Note that squashfs stores
// this as a int32, which means it'll stop working after 2038.
func (fi *fileinfo) ModTime() time.Time {
return time.Unix(int64(fi.ino.ModTime), 0)
}
// IsDir returns true if this is a directory
func (fi *fileinfo) IsDir() bool {
return fi.ino.IsDir()
}
// Sys returns the *Inode object matching this file
func (fi *fileinfo) Sys() any {
return fi.ino
}