36533f7c3f
Fixes for new geth version
179 lines
3.9 KiB
Go
179 lines
3.9 KiB
Go
package files
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
// serialFile implements Node, and reads from a path on the OS filesystem.
|
|
// No more than one file will be opened at a time (directories will advance
|
|
// to the next file when NextFile() is called).
|
|
type serialFile struct {
|
|
path string
|
|
files []os.FileInfo
|
|
stat os.FileInfo
|
|
handleHiddenFiles bool
|
|
}
|
|
|
|
type serialIterator struct {
|
|
files []os.FileInfo
|
|
handleHiddenFiles bool
|
|
path string
|
|
|
|
curName string
|
|
curFile Node
|
|
|
|
err error
|
|
}
|
|
|
|
// TODO: test/document limitations
|
|
func NewSerialFile(path string, hidden bool, stat os.FileInfo) (Node, error) {
|
|
switch mode := stat.Mode(); {
|
|
case mode.IsRegular():
|
|
file, err := os.Open(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return NewReaderPathFile(path, file, stat)
|
|
case mode.IsDir():
|
|
// for directories, stat all of the contents first, so we know what files to
|
|
// open when NextFile() is called
|
|
contents, err := ioutil.ReadDir(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &serialFile{path, contents, stat, hidden}, nil
|
|
case mode&os.ModeSymlink != 0:
|
|
target, err := os.Readlink(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return NewLinkFile(target, stat), nil
|
|
default:
|
|
return nil, fmt.Errorf("unrecognized file type for %s: %s", path, mode.String())
|
|
}
|
|
}
|
|
|
|
func (it *serialIterator) Name() string {
|
|
return it.curName
|
|
}
|
|
|
|
func (it *serialIterator) Node() Node {
|
|
return it.curFile
|
|
}
|
|
|
|
func (it *serialIterator) Next() bool {
|
|
// if there aren't any files left in the root directory, we're done
|
|
if len(it.files) == 0 {
|
|
return false
|
|
}
|
|
|
|
stat := it.files[0]
|
|
it.files = it.files[1:]
|
|
for !it.handleHiddenFiles && strings.HasPrefix(stat.Name(), ".") {
|
|
if len(it.files) == 0 {
|
|
return false
|
|
}
|
|
|
|
stat = it.files[0]
|
|
it.files = it.files[1:]
|
|
}
|
|
|
|
// open the next file
|
|
filePath := filepath.ToSlash(filepath.Join(it.path, stat.Name()))
|
|
|
|
// recursively call the constructor on the next file
|
|
// if it's a regular file, we will open it as a ReaderFile
|
|
// if it's a directory, files in it will be opened serially
|
|
sf, err := NewSerialFile(filePath, it.handleHiddenFiles, stat)
|
|
if err != nil {
|
|
it.err = err
|
|
return false
|
|
}
|
|
|
|
it.curName = stat.Name()
|
|
it.curFile = sf
|
|
return true
|
|
}
|
|
|
|
func (it *serialIterator) Err() error {
|
|
return it.err
|
|
}
|
|
|
|
func (f *serialFile) Entries() DirIterator {
|
|
return &serialIterator{
|
|
path: f.path,
|
|
files: f.files,
|
|
handleHiddenFiles: f.handleHiddenFiles,
|
|
}
|
|
}
|
|
|
|
func (f *serialFile) NextFile() (string, Node, error) {
|
|
// if there aren't any files left in the root directory, we're done
|
|
if len(f.files) == 0 {
|
|
return "", nil, io.EOF
|
|
}
|
|
|
|
stat := f.files[0]
|
|
f.files = f.files[1:]
|
|
|
|
for !f.handleHiddenFiles && strings.HasPrefix(stat.Name(), ".") {
|
|
if len(f.files) == 0 {
|
|
return "", nil, io.EOF
|
|
}
|
|
|
|
stat = f.files[0]
|
|
f.files = f.files[1:]
|
|
}
|
|
|
|
// open the next file
|
|
filePath := filepath.ToSlash(filepath.Join(f.path, stat.Name()))
|
|
|
|
// recursively call the constructor on the next file
|
|
// if it's a regular file, we will open it as a ReaderFile
|
|
// if it's a directory, files in it will be opened serially
|
|
sf, err := NewSerialFile(filePath, f.handleHiddenFiles, stat)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
|
|
return stat.Name(), sf, nil
|
|
}
|
|
|
|
func (f *serialFile) Close() error {
|
|
return nil
|
|
}
|
|
|
|
func (f *serialFile) Stat() os.FileInfo {
|
|
return f.stat
|
|
}
|
|
|
|
func (f *serialFile) Size() (int64, error) {
|
|
if !f.stat.IsDir() {
|
|
//something went terribly, terribly wrong
|
|
return 0, errors.New("serialFile is not a directory")
|
|
}
|
|
|
|
var du int64
|
|
err := filepath.Walk(f.path, func(p string, fi os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if fi != nil && fi.Mode().IsRegular() {
|
|
du += fi.Size()
|
|
}
|
|
return nil
|
|
})
|
|
|
|
return du, err
|
|
}
|
|
|
|
var _ Directory = &serialFile{}
|
|
var _ DirIterator = &serialIterator{}
|