Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alist-org
GitHub Repository: alist-org/alist
Path: blob/main/internal/archive/archives/archives.go
1562 views
1
package archives
2
3
import (
4
"io"
5
"io/fs"
6
"os"
7
stdpath "path"
8
"strings"
9
10
"github.com/alist-org/alist/v3/internal/archive/tool"
11
"github.com/alist-org/alist/v3/internal/model"
12
"github.com/alist-org/alist/v3/internal/stream"
13
"github.com/alist-org/alist/v3/pkg/utils"
14
)
15
16
type Archives struct {
17
}
18
19
func (Archives) AcceptedExtensions() []string {
20
return []string{
21
".br", ".bz2", ".gz", ".lz4", ".lz", ".sz", ".s2", ".xz", ".zz", ".zst", ".tar",
22
}
23
}
24
25
func (Archives) AcceptedMultipartExtensions() map[string]tool.MultipartExtension {
26
return map[string]tool.MultipartExtension{}
27
}
28
29
func (Archives) GetMeta(ss []*stream.SeekableStream, args model.ArchiveArgs) (model.ArchiveMeta, error) {
30
fsys, err := getFs(ss[0], args)
31
if err != nil {
32
return nil, err
33
}
34
files, err := fsys.ReadDir(".")
35
if err != nil {
36
return nil, filterPassword(err)
37
}
38
39
tree := make([]model.ObjTree, 0, len(files))
40
for _, file := range files {
41
info, err := file.Info()
42
if err != nil {
43
continue
44
}
45
tree = append(tree, &model.ObjectTree{Object: *toModelObj(info)})
46
}
47
return &model.ArchiveMetaInfo{
48
Comment: "",
49
Encrypted: false,
50
Tree: tree,
51
}, nil
52
}
53
54
func (Archives) List(ss []*stream.SeekableStream, args model.ArchiveInnerArgs) ([]model.Obj, error) {
55
fsys, err := getFs(ss[0], args.ArchiveArgs)
56
if err != nil {
57
return nil, err
58
}
59
innerPath := strings.TrimPrefix(args.InnerPath, "/")
60
if innerPath == "" {
61
innerPath = "."
62
}
63
obj, err := fsys.ReadDir(innerPath)
64
if err != nil {
65
return nil, filterPassword(err)
66
}
67
return utils.SliceConvert(obj, func(src os.DirEntry) (model.Obj, error) {
68
info, err := src.Info()
69
if err != nil {
70
return nil, err
71
}
72
return toModelObj(info), nil
73
})
74
}
75
76
func (Archives) Extract(ss []*stream.SeekableStream, args model.ArchiveInnerArgs) (io.ReadCloser, int64, error) {
77
fsys, err := getFs(ss[0], args.ArchiveArgs)
78
if err != nil {
79
return nil, 0, err
80
}
81
file, err := fsys.Open(strings.TrimPrefix(args.InnerPath, "/"))
82
if err != nil {
83
return nil, 0, filterPassword(err)
84
}
85
stat, err := file.Stat()
86
if err != nil {
87
return nil, 0, filterPassword(err)
88
}
89
return file, stat.Size(), nil
90
}
91
92
func (Archives) Decompress(ss []*stream.SeekableStream, outputPath string, args model.ArchiveInnerArgs, up model.UpdateProgress) error {
93
fsys, err := getFs(ss[0], args.ArchiveArgs)
94
if err != nil {
95
return err
96
}
97
isDir := false
98
path := strings.TrimPrefix(args.InnerPath, "/")
99
if path == "" {
100
isDir = true
101
path = "."
102
} else {
103
stat, err := fsys.Stat(path)
104
if err != nil {
105
return filterPassword(err)
106
}
107
if stat.IsDir() {
108
isDir = true
109
outputPath = stdpath.Join(outputPath, stat.Name())
110
err = os.Mkdir(outputPath, 0700)
111
if err != nil {
112
return filterPassword(err)
113
}
114
}
115
}
116
if isDir {
117
err = fs.WalkDir(fsys, path, func(p string, d fs.DirEntry, err error) error {
118
if err != nil {
119
return err
120
}
121
relPath := strings.TrimPrefix(p, path+"/")
122
dstPath := stdpath.Join(outputPath, relPath)
123
if d.IsDir() {
124
err = os.MkdirAll(dstPath, 0700)
125
} else {
126
dir := stdpath.Dir(dstPath)
127
err = decompress(fsys, p, dir, func(_ float64) {})
128
}
129
return err
130
})
131
} else {
132
err = decompress(fsys, path, outputPath, up)
133
}
134
return filterPassword(err)
135
}
136
137
var _ tool.Tool = (*Archives)(nil)
138
139
func init() {
140
tool.RegisterTool(Archives{})
141
}
142
143