...
1 package rifs
2
3 import (
4 "io"
5 "os"
6 "path"
7
8 "github.com/dsoprea/go-logging"
9 )
10
11
12 type FileListFilterPredicate func(parent string, child os.FileInfo) (hit bool, err error)
13
14
15 type VisitedFile struct {
16 Filepath string
17 Info os.FileInfo
18 Index int
19 }
20
21
22
23
24
25 func ListFiles(rootPath string, cb FileListFilterPredicate) (filesC chan VisitedFile, count int, errC chan error) {
26 defer func() {
27 if state := recover(); state != nil {
28 err := log.Wrap(state.(error))
29 log.Panic(err)
30 }
31 }()
32
33
34
35 f, err := os.Open(rootPath)
36 log.PanicIf(err)
37
38 f.Close()
39
40
41
42 filesC = make(chan VisitedFile, 100)
43 errC = make(chan error, 1)
44 index := 0
45
46 go func() {
47 defer func() {
48 if state := recover(); state != nil {
49 err := log.Wrap(state.(error))
50 errC <- err
51 }
52 }()
53
54 queue := []string{rootPath}
55 for len(queue) > 0 {
56
57 var thisPath string
58 thisPath, queue = queue[0], queue[1:]
59
60
61
62 fi, err := os.Lstat(thisPath)
63 log.PanicIf(err)
64
65 if (fi.Mode() & os.ModeSymlink) > 0 {
66 continue
67 }
68
69
70
71 folderF, err := os.Open(thisPath)
72 if err != nil {
73 errC <- log.Wrap(err)
74 return
75 }
76
77
78
79 for {
80 children, err := folderF.Readdir(1000)
81 if err == io.EOF {
82 break
83 } else if err != nil {
84 errC <- log.Wrap(err)
85 return
86 }
87
88 for _, child := range children {
89 filepath := path.Join(thisPath, child.Name())
90
91
92
93 fi, err := os.Lstat(filepath)
94 log.PanicIf(err)
95
96 if (fi.Mode() & os.ModeSymlink) > 0 {
97 continue
98 }
99
100
101
102 if cb != nil {
103 hit, err := cb(thisPath, child)
104
105 if err != nil {
106 errC <- log.Wrap(err)
107 return
108 }
109
110 if hit == false {
111 continue
112 }
113 }
114
115 index++
116
117
118
119 vf := VisitedFile{
120 Filepath: filepath,
121 Info: child,
122 Index: index,
123 }
124
125 filesC <- vf
126
127
128
129 if child.IsDir() == true {
130 queue = append(queue, filepath)
131 }
132 }
133 }
134
135 folderF.Close()
136 }
137
138 close(filesC)
139 close(errC)
140 }()
141
142 return filesC, index, errC
143 }
144
View as plain text