// UGH - copy & paste. // for tests: func StatForTest(t *testing.T, n string) *fuse.Attr { t.Logf("test stat %q", n) f, _ := os.Lstat(n) if f == nil { return nil } return fuse.ToAttr(f) }
func getattr(filename string) (*fuse.Attr, fuse.Status) { stat, err := os.Stat(filename) if err != nil { // TODO report error return nil, fuse.EIO } return fuse.ToAttr(stat), fuse.OK }
func GetattrForTest(t *testing.T, n string) *attr.FileAttr { t.Logf("test getattr %q", n) fi, _ := os.Lstat(n) var fa *fuse.Attr if fi != nil { fa = fuse.ToAttr(fi) } a := attr.FileAttr{ Attr: fa, } if !a.Deletion() { a.ReadFromFs(n, crypto.MD5) } return &a }
func (gitfs *GitFs) GetAttr(name string, _ *fuse.Context) (attr *fuse.Attr, status fuse.Status) { defer gitfs.showPanicError() user, repo, path := splitPath(name) gitfs.logger.Debugf("GetAttr: user = %s, repo = %s, path = %s", user, repo, path) if /* user == "" || */ repo == "" { dirInfo, err := os.Stat(gitfs.GitRepoDir + "/" + user) if err != nil { return nil, fuse.ToStatus(err) } attr = fuse.ToAttr(dirInfo) attr.Mode &= ^uint32(0222) return attr, fuse.OK } repoPath := gitfs.GitRepoDir + "/" + user + "/" + repo + ".git" attr, status = gitfs.getGitAttrByPath(repoPath, path) return }
func (me *FileAttr) ReadFromFs(p string, hashFunc crypto.Hash) { var err error switch { case me.IsRegular(): if c, e := ioutil.ReadFile(p); e == nil { h := hashFunc.New() h.Write(c) me.Hash = string(h.Sum(nil)) } else { err = e } case me.IsDir(): d, e := ioutil.ReadDir(p) if e == nil { me.NameModeMap = make(map[string]FileMode, len(d)) for _, v := range d { a := fuse.ToAttr(v) if a != nil { // attr == nil may happen for fuse mounts that have died. me.NameModeMap[v.Name()] = FileMode(a.Mode &^ 07777) } } } else { err = e } case me.IsSymlink(): if l, e := os.Readlink(p); e == nil { me.Link = l } else { err = e } } if err != nil { log.Println("Error reading %q (%s): %v", me.Attr.Mode, p, err) me.Attr = nil } }
func TestMemUnionFsUpdate(t *testing.T) { wd, ufs, clean := setupMemUfs(t) defer clean() err := ioutil.WriteFile(wd+"/ro/file1", []byte("blablabla"), 0644) CheckSuccess(err) _, err = os.Lstat(wd + "/mnt/file1") CheckSuccess(err) if fi, _ := os.Lstat(wd + "/mnt/file2"); fi != nil { t.Fatal("file2 should not exist", fi) } if fi, _ := os.Lstat(wd + "/mnt/symlink"); fi != nil { t.Fatal("symlink should not exist", fi) } err = os.Remove(wd + "/ro/file1") CheckSuccess(err) err = ioutil.WriteFile(wd+"/ro/file2", []byte("foobar"), 0644) CheckSuccess(err) err = os.Symlink("target", wd+"/ro/symlink") CheckSuccess(err) // Still have cached attributes. fi, err := os.Lstat(wd + "/mnt/file1") CheckSuccess(err) if fi, _ := os.Lstat(wd + "/mnt/file2"); fi != nil { t.Fatal("file2 should not exist") } if fi, _ := os.Lstat(wd + "/mnt/symlink"); fi != nil { t.Fatal("symlink should not exist", fi) } roF2fi, err := os.Lstat(wd + "/ro/file2") CheckSuccess(err) roF2 := fuse.ToAttr(roF2fi) roSymlinkFi, err := os.Lstat(wd + "/ro/symlink") CheckSuccess(err) roSymlink := fuse.ToAttr(roSymlinkFi) updates := map[string]*Result{ "file1": { nil, "", "", "", }, "file2": { roF2, "", "", "", }, "symlink": { roSymlink, "", "", "target", }, } ufs.Update(updates) // Cached attributes flushed. if fi, _ := os.Lstat(wd + "/mnt/file1"); fi != nil { t.Fatal("file1 should have disappeared", fi) } fi, err = os.Lstat(wd + "/mnt/file2") CheckSuccess(err) if roF2.ModTime().UnixNano() != fi.ModTime().UnixNano() { t.Fatalf("file2 attribute mismatch: got %v want %v", fi, roF2) } val, err := os.Readlink(wd + "/mnt/symlink") CheckSuccess(err) if val != "target" { t.Error("symlink value got %q want %v", val, "target") } }
func (gitfs *GitFs) getGitAttrByPath(repoPath string, path string) (*fuse.Attr, fuse.Status) { repo, _, _, tree, err := gitfs.getMasterTreeFromRepo(repoPath) if err != nil { return nil, fuse.EPERM } repoInfo, err := os.Stat(repoPath) if err != nil { gitfs.logger.Debugf("Failed to Stat %s due to %s", repoPath, err) return nil, fuse.ToStatus(err) } if path == "" { attr := fuse.ToAttr(repoInfo) attr.Mode &= ^uint32(0222) attr.Nlink = 2 + gitfs.treeEntryCount(tree, repoPath) return attr, fuse.OK } entry, err := tree.EntryByPath(path) if err != nil { gitfs.logger.Debugf("Cannot find path %s from tree %s of Git Repository %s due to %s", path, tree.Id().String(), repoPath, err) return nil, fuse.ENOENT } gitfs.logger.Debugf("Found path %s from tree %s of Git Repository %s", path, tree.Id().String(), repoPath) var attr fuse.Attr attr.Mode = toFileMode(entry.Filemode) if stat, ok := repoInfo.Sys().(*syscall.Stat_t); ok { attr.Uid = stat.Uid attr.Gid = stat.Gid attr.Blksize = uint32(stat.Blksize) attr.Rdev = uint32(stat.Rdev) } attr.Ino = crc64.Checksum(entry.Id[:], crc64.MakeTable(crc64.ECMA)) now := time.Now() attr.SetTimes(&now, &now, &now) switch entry.Type { case libgit2.ObjectTree: tree, err := repo.LookupTree(entry.Id) if err != nil { gitfs.logger.Errorf("Failed to find tree %s from Git Repository %s", entry.Id, repoPath) return nil, fuse.EPERM } defer tree.Free() gitfs.logger.Debugf("Found tree %s of Git Repository %s", tree.Id().String(), repoPath) attr.Size = 4096 attr.Nlink = 2 + gitfs.treeEntryCount(tree, repoPath) case libgit2.ObjectBlob: blob, err := repo.LookupBlob(entry.Id) if err != nil { gitfs.logger.Errorf("Failed to find blob %s from Git Repository %s", entry.Id, repoPath) return nil, fuse.EPERM } defer blob.Free() gitfs.logger.Debugf("Found blob %s of Git Repository %s", blob.Id().String(), repoPath) attr.Nlink = 1 attr.Size = uint64(blob.Size()) default: gitfs.logger.Debugf("GetAttr: Unsupported object type %s of %s from Git Repository %s", entry.Type.String(), entry.Id, repoPath) return nil, fuse.ENOENT } attr.Blocks = (attr.Size + 511) / 512 return &attr, fuse.OK }