/
directory.go
83 lines (78 loc) · 1.96 KB
/
directory.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
package squashfslow
import (
"errors"
"io/fs"
"path/filepath"
"slices"
"strings"
"github.com/CalebQ42/squashfs/internal/metadata"
"github.com/CalebQ42/squashfs/internal/toreader"
"github.com/CalebQ42/squashfs/low/directory"
"github.com/CalebQ42/squashfs/low/inode"
)
type Directory struct {
FileBase
Entries []directory.Entry
}
func (r *Reader) directoryFromRef(ref uint64, name string) (*Directory, error) {
i, err := r.InodeFromRef(ref)
if err != nil {
return nil, err
}
var blockStart uint32
var size uint32
var offset uint16
switch i.Type {
case inode.Dir:
blockStart = i.Data.(inode.Directory).BlockStart
size = uint32(i.Data.(inode.Directory).Size)
offset = i.Data.(inode.Directory).Offset
case inode.EDir:
blockStart = i.Data.(inode.EDirectory).BlockStart
size = i.Data.(inode.EDirectory).Size
offset = i.Data.(inode.EDirectory).Offset
default:
return nil, errors.New("not a directory")
}
dirRdr := metadata.NewReader(toreader.NewReader(r.r, int64(r.Superblock.DirTableStart)+int64(blockStart)), r.d)
defer dirRdr.Close()
_, err = dirRdr.Read(make([]byte, offset))
if err != nil {
return nil, err
}
entries, err := directory.ReadDirectory(dirRdr, size)
if err != nil {
return nil, err
}
return &Directory{
FileBase: *r.BaseFromInode(i, name),
Entries: entries,
}, nil
}
func (d *Directory) Open(r *Reader, path string) (*FileBase, error) {
path = filepath.Clean(path)
if path == "." || path == "" {
return &d.FileBase, nil
}
split := strings.Split(path, "/")
i, found := slices.BinarySearchFunc(d.Entries, split[0], func(e directory.Entry, name string) int {
return strings.Compare(e.Name, name)
})
if !found {
return nil, fs.ErrNotExist
}
b, err := r.BaseFromEntry(d.Entries[i])
if err != nil {
return nil, err
}
if len(split) == 1 {
return b, nil
} else if !b.IsDir() {
return nil, fs.ErrNotExist
}
dir, err := b.ToDir(r)
if err != nil {
return nil, err
}
return dir.Open(r, strings.Join(split[1:], "/"))
}