123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- package gdrivefs
- import (
- "fmt"
- "os"
- "strings"
- "sync"
- drive "google.golang.org/api/drive/v3"
- "github.com/jacobsa/fuse/fuseops"
- )
- type FileContainer struct {
- fileEntries map[fuseops.InodeID]*FileEntry
- tree *FileEntry
- fs *GDriveFS
- uid uint32
- gid uint32
- inodeMU *sync.Mutex
- }
- func NewFileContainer(fs *GDriveFS) *FileContainer {
- fc := &FileContainer{
- fileEntries: map[fuseops.InodeID]*FileEntry{},
- fs: fs,
- inodeMU: &sync.Mutex{},
- uid: fs.config.UID,
- gid: fs.config.GID,
- }
- rootEntry := fc.FileEntry(nil, fuseops.RootInodeID)
- rootEntry.Attr.Mode = os.FileMode(0755) | os.ModeDir
- fc.tree = rootEntry
- return fc
- }
- func (fc *FileContainer) FindByInode(inode fuseops.InodeID) *FileEntry {
- return fc.fileEntries[inode]
- }
- func (fc *FileContainer) FindByGID(gid string) *FileEntry {
- for _, v := range fc.fileEntries {
- if v.GFile != nil && v.GFile.Id == gid {
- return v
- }
- }
- return nil
- }
- func (fc *FileContainer) LookupByGID(parentGID string, name string) *FileEntry {
- for _, entry := range fc.fileEntries {
- if entry.HasParentGID(parentGID) && entry.Name == name {
- return entry
- }
- }
- return nil
- }
- func (fc *FileContainer) ListByParentGID(parentGID string) []*FileEntry {
- ret := []*FileEntry{}
- for _, entry := range fc.fileEntries {
- if entry.HasParentGID(parentGID) {
- ret = append(ret, entry)
- }
- }
- return ret
- }
- //Return or create inode // Pass name maybe?
- func (fc *FileContainer) FileEntry(gfile *drive.File, inodeOps ...fuseops.InodeID) *FileEntry {
- fc.inodeMU.Lock()
- defer fc.inodeMU.Unlock()
- var inode fuseops.InodeID
- if len(inodeOps) > 0 {
- inode = inodeOps[0]
- if fe, ok := fc.fileEntries[inode]; ok {
- return fe
- }
- } else { // generate new inode
- // Max Inode Number
- for inode = 2; inode < 99999; inode++ {
- _, ok := fc.fileEntries[inode]
- if !ok {
- break
- }
- }
- }
- name := ""
- if gfile != nil {
- name = gfile.Name
- count := 1
- nameParts := strings.Split(name, ".")
- for {
- // We find if we have a GFile in same parent with same name
- var entry *FileEntry
- for _, p := range gfile.Parents {
- entry = fc.LookupByGID(p, name)
- if entry != nil {
- break
- }
- }
- if entry == nil { // Not found return
- break
- }
- count++
- if len(nameParts) > 1 {
- name = fmt.Sprintf("%s(%d).%s", nameParts[0], count, strings.Join(nameParts[1:], "."))
- } else {
- name = fmt.Sprintf("%s(%d)", nameParts[0], count)
- }
- log.Printf("Conflicting name generated new '%s' as '%s'", gfile.Name, name)
- }
- }
- fe := &FileEntry{
- GFile: gfile,
- Inode: inode,
- container: fc,
- Name: name,
- //children: []*FileEntry{},
- Attr: fuseops.InodeAttributes{
- Uid: fc.uid,
- Gid: fc.gid,
- },
- }
- fe.SetGFile(gfile)
- fc.fileEntries[inode] = fe
- return fe
- }
- func (fc *FileContainer) AddEntry(entry *FileEntry) {
- fc.fileEntries[entry.Inode] = entry
- }
- // RemoveEntry remove file entry
- func (fc *FileContainer) RemoveEntry(entry *FileEntry) {
- var inode fuseops.InodeID
- for k, e := range fc.fileEntries {
- if e == entry {
- inode = k
- }
- }
- delete(fc.fileEntries, inode)
- }
- func (fc *FileContainer) AddGFile(gfile *drive.File) *FileEntry {
- entry := fc.FindByGID(gfile.Id)
- if entry != nil {
- return entry
- }
- // Create new Entry
- entry = fc.FileEntry(gfile)
- entry.SetGFile(gfile)
- return entry
- }
|