You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1Panel/backend/utils/files/fileinfo.go

148 lines
3.2 KiB

package files
import (
"fmt"
"github.com/pkg/errors"
"github.com/spf13/afero"
"os"
"path"
"path/filepath"
"syscall"
"time"
)
type FileInfo struct {
Fs afero.Fs `json:"-"`
Path string `json:"path"`
Name string `json:"name"`
User string `json:"user"`
Group string `json:"group"`
Extension string `json:"extension"`
Content string `json:"content"`
Size int64 `json:"size"`
IsDir bool `json:"isDir"`
IsSymlink bool `json:"isSymlink"`
LinkPath string `json:"linkPath"`
Type string `json:"type"`
Mode string `json:"mode"`
MimeType string `json:"mimeType"`
UpdateTime time.Time `json:"updateTime"`
ModTime time.Time `json:"modTime"`
FileMode os.FileMode `json:"-"`
Items []*FileInfo `json:"items"`
}
type FileOption struct {
Path string `json:"path"`
Search string `json:"search"`
Expand bool `json:"expand"`
}
func NewFileInfo(op FileOption) (*FileInfo, error) {
var appFs = afero.NewOsFs()
info, err := appFs.Stat(op.Path)
if err != nil {
return nil, err
}
file := &FileInfo{
Fs: appFs,
Path: op.Path,
Name: info.Name(),
IsDir: info.IsDir(),
FileMode: info.Mode(),
ModTime: info.ModTime(),
Size: info.Size(),
IsSymlink: IsSymlink(info.Mode()),
Extension: filepath.Ext(info.Name()),
Mode: fmt.Sprintf("%04o", info.Mode().Perm()),
User: GetUsername(info.Sys().(*syscall.Stat_t).Uid),
Group: GetGroup(info.Sys().(*syscall.Stat_t).Gid),
MimeType: GetMimeType(op.Path),
}
if file.IsSymlink {
file.LinkPath = GetSymlink(op.Path)
}
if op.Search != "" {
}
if op.Expand {
if file.IsDir {
if err := file.listChildren(); err != nil {
return nil, err
}
return file, nil
} else {
if err := file.getContent(); err != nil {
return nil, err
}
}
}
return file, nil
}
func (f *FileInfo) listChildren() error {
afs := &afero.Afero{Fs: f.Fs}
dir, err := afs.ReadDir(f.Path)
if err != nil {
return err
}
var items []*FileInfo
for _, df := range dir {
name := df.Name()
fPath := path.Join(f.Path, df.Name())
isSymlink, isInvalidLink := false, false
if IsSymlink(df.Mode()) {
isSymlink = true
info, err := f.Fs.Stat(fPath)
if err == nil {
df = info
} else {
isInvalidLink = true
}
}
file := &FileInfo{
Fs: f.Fs,
Name: name,
Size: df.Size(),
ModTime: df.ModTime(),
FileMode: df.Mode(),
IsDir: df.IsDir(),
IsSymlink: isSymlink,
Extension: filepath.Ext(name),
Path: fPath,
Mode: fmt.Sprintf("%04o", df.Mode().Perm()),
User: GetUsername(df.Sys().(*syscall.Stat_t).Uid),
Group: GetGroup(df.Sys().(*syscall.Stat_t).Gid),
MimeType: GetMimeType(fPath),
}
if isSymlink {
file.LinkPath = GetSymlink(fPath)
}
if isInvalidLink {
file.Type = "invalid_link"
}
items = append(items, file)
}
f.Items = items
return nil
}
func (f *FileInfo) getContent() error {
if f.Size <= 10*1024*1024 {
afs := &afero.Afero{Fs: f.Fs}
cByte, err := afs.ReadFile(f.Path)
if err != nil {
return nil
}
f.Content = string(cByte)
return nil
} else {
return errors.New("file is too large!")
}
}