This repository has been archived by the owner on Feb 26, 2020. It is now read-only.
/
symlink.go
98 lines (80 loc) · 2.03 KB
/
symlink.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package svfs
import (
"os"
"bazil.org/fuse"
"bazil.org/fuse/fs"
"github.com/xlucas/swift"
"golang.org/x/net/context"
)
const (
objectSymlinkHeader = objectMetaHeader + "Symlink-Target"
)
// Symlink represents a symbolic link to an object within a container.
type Symlink struct {
name string
path string
so *swift.Object
sh swift.Headers
c *swift.Container
p *Directory
}
// Attr fills the file attributes for a symlink node.
func (s *Symlink) Attr(ctx context.Context, a *fuse.Attr) (err error) {
a.Size = uint64(s.so.Bytes)
a.BlockSize = 0
a.Blocks = 0
a.Mode = os.ModeSymlink | os.FileMode(DefaultMode)
a.Gid = uint32(DefaultGID)
a.Uid = uint32(DefaultUID)
a.Mtime = getMtime(s.so, s.sh)
a.Ctime = a.Mtime
a.Crtime = a.Mtime
return nil
}
// Export converts this symlink node to a direntry.
func (s *Symlink) Export() fuse.Dirent {
return fuse.Dirent{Name: s.Name(), Type: fuse.DT_Link}
}
// Name gets the name of the underlying swift object.
func (s *Symlink) Name() string {
return s.name
}
// Readlink gets the symlink target path.
func (s *Symlink) Readlink(ctx context.Context, req *fuse.ReadlinkRequest) (string, error) {
return s.sh[objectSymlinkHeader], nil
}
func (s *Symlink) copy(dir *Directory, name string) (*Symlink, error) {
_, err := SwiftConnection.ObjectCopy(s.c.Name, s.path, dir.c.Name, dir.path+name, nil)
if err != nil {
return nil, err
}
link := *s
*link.so = *s.so
link.c = dir.c
link.p = dir
link.name = name
link.path = dir.path + name
directoryCache.Set(dir.c.Name, dir.path, name, &link)
return &link, nil
}
func (s *Symlink) delete() error {
directoryCache.Delete(s.c.Name, s.p.path, s.name)
return SwiftConnection.ObjectDelete(s.c.Name, s.path)
}
func (s *Symlink) rename(dir *Directory, name string) error {
copy, err := s.copy(dir, name)
if err != nil {
return err
}
err = s.delete()
if err != nil {
return err
}
*s = *copy
return nil
}
var (
_ Node = (*Symlink)(nil)
_ fs.Node = (*Symlink)(nil)
_ fs.NodeReadlinker = (*Symlink)(nil)
)