97 lines
1.8 KiB
Go
97 lines
1.8 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
type JoinedFilesystem struct {
|
|
DefaultSystem http.FileSystem
|
|
Systems map[string]http.FileSystem
|
|
}
|
|
|
|
func Stat(fs http.FileSystem, filename string) (os.FileInfo, error) {
|
|
file, err := fs.Open(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return file.Stat()
|
|
}
|
|
|
|
func Readdir(fs http.FileSystem, filename string) ([]os.FileInfo, error) {
|
|
file, err := fs.Open(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return file.Readdir(-1)
|
|
}
|
|
|
|
func (s *JoinedFilesystem) GetRoot() (http.File, error) {
|
|
root, err := s.DefaultSystem.Open("/")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
rootStat, err := root.Stat()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
rootContent, err := root.Readdir(-1)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for prefix, fs := range s.Systems {
|
|
fsRoot, err := fs.Open("/")
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
continue
|
|
}
|
|
|
|
fsRootStat, err := fsRoot.Stat()
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
continue
|
|
}
|
|
|
|
rootContent = append(rootContent, ChangeFileInfoName(fsRootStat, prefix))
|
|
}
|
|
|
|
return FakeDir{Self: rootStat, Content: rootContent}, nil
|
|
}
|
|
|
|
func (s *JoinedFilesystem) Open(filename string) (http.File, error) {
|
|
if filename == "/" {
|
|
return s.GetRoot()
|
|
}
|
|
|
|
parts := strings.Split(filename, "/")
|
|
var newFilename string
|
|
if len(parts) == 2 {
|
|
newFilename = "/"
|
|
} else {
|
|
newFilename = strings.Join(parts[2:], "/")
|
|
}
|
|
|
|
for prefix, fs := range s.Systems {
|
|
if parts[1] == prefix {
|
|
file, err := fs.Open(newFilename)
|
|
if err == nil {
|
|
return file, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
return s.DefaultSystem.Open(filename)
|
|
}
|
|
|
|
func (s *JoinedFilesystem) Register(prefix string, system http.FileSystem) {
|
|
s.Systems[prefix] = system
|
|
}
|
|
|
|
func JoinedFS(def http.FileSystem) *JoinedFilesystem {
|
|
return &JoinedFilesystem{DefaultSystem: def, Systems: map[string]http.FileSystem{}}
|
|
}
|