-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
fs.go
125 lines (107 loc) · 3.13 KB
/
fs.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
/*
* Copyright (c) 2023 Gilles Chehade <gilles@poolp.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package fs
import (
"fmt"
"io"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/PlakarLabs/plakar/vfs"
"github.com/PlakarLabs/plakar/vfs/importer"
"github.com/iafan/cwalk"
)
type FSImporter struct {
importer.ImporterBackend
config string
}
func init() {
importer.Register("fs", NewFSImporter)
}
func NewFSImporter() importer.ImporterBackend {
return &FSImporter{}
}
func (p *FSImporter) Scan() (<-chan importer.ImporterRecord, <-chan error, error) {
c := make(chan importer.ImporterRecord)
cerr := make(chan error)
go func() {
directory := filepath.Clean(p.config)
atoms := strings.Split(directory, string(os.PathSeparator))
for i := 0; i < len(atoms)-1; i++ {
path := filepath.Clean(fmt.Sprintf("%s%s", string(os.PathSeparator), strings.Join(atoms[0:i+1], string(os.PathSeparator))))
if runtime.GOOS == "windows" {
path = path[1:]
}
f, err := os.Stat(path)
if err != nil {
cerr <- err
close(cerr)
return
}
fileinfo := vfs.FileInfoFromStat(f)
c <- importer.ImporterRecord{Pathname: filepath.ToSlash(path), Stat: fileinfo}
}
err := cwalk.Walk(directory, func(path string, f os.FileInfo, err error) error {
if err != nil {
cerr <- err
return nil
}
pathname := filepath.Join(directory, path)
fileinfo := vfs.FileInfoFromStat(f)
c <- importer.ImporterRecord{Pathname: filepath.ToSlash(pathname), Stat: fileinfo}
if !fileinfo.Mode().IsDir() && !fileinfo.Mode().IsRegular() {
lstat, err := os.Lstat(pathname)
if err != nil {
cerr <- err
return nil
}
lfileinfo := vfs.FileInfoFromStat(lstat)
if lfileinfo.Mode()&os.ModeSymlink != 0 {
originFile, err := os.Readlink(lfileinfo.Name())
if err != nil {
cerr <- err
return nil
}
_ = originFile
c <- importer.ImporterRecord{Pathname: filepath.ToSlash(pathname), Stat: lfileinfo}
// need to figure out how to notidy fakefs
// that a pathname actually link to another
}
}
return nil
})
if err != nil {
cerr <- err
}
close(cerr)
close(c)
}()
return c, cerr, nil
}
func (p *FSImporter) Open(pathname string) (io.ReadCloser, error) {
return os.Open(pathname)
}
func (p *FSImporter) Begin(config string) error {
if strings.HasPrefix(config, "fs://") {
config = config[4:]
}
p.config = config
return nil
}
func (p *FSImporter) End() error {
return nil
}