1
2
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
18
19 package fs
20
21 import (
22 "context"
23 "os"
24
25 "bazil.org/fuse"
26 fusefs "bazil.org/fuse/fs"
27 )
28
29 type atDir struct {
30 fs *CamliFileSystem
31 }
32
33 var (
34 _ fusefs.Node = (*atDir)(nil)
35 _ fusefs.HandleReadDirAller = (*atDir)(nil)
36 _ fusefs.NodeStringLookuper = (*atDir)(nil)
37 )
38
39 func (n *atDir) Attr(ctx context.Context, a *fuse.Attr) error {
40 a.Mode = os.ModeDir | 0500
41 a.Uid = uint32(os.Getuid())
42 a.Gid = uint32(os.Getgid())
43 return nil
44 }
45
46 func (n *atDir) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
47 return []fuse.Dirent{
48 {Name: "README.txt"},
49 }, nil
50 }
51
52 const atReadme = `You are now in the "at" filesystem, where you can look into the past.
53
54 Locations in the top-level of this directory are dynamically created
55 as you request them. A dynamic directory is designated by a
56 timestamp. Once you enter a directory, you'll have a read-only view
57 of all of the roots that existed as of the specified time.
58
59 Example:
60
61 If you had a root called "importantstuff" and a file in it called
62 "todo.txt", you can look at the contents of that file as it existed
63 back before Christmas like this (from the location you mounted
64 camlistore):
65
66 cat at/2013-12-24/importantstuff/todo.txt
67
68 If you cd into "at/2013-12-24/importantstuff" you can also see all the
69 files that you deleted since (but none that were created after).
70
71 Timestamps are specified in UTC unless otherwise specified, and may be
72 in any of the following forms:
73
74 With Nanosecond Granularity
75
76 * 2012-08-28T21:24:35.37465188Z - RFC3339 (this is the canonical format)
77 * 1346189075374651880 - nanoseconds since 1970-1-1
78
79 With Millisecond Granularity
80
81 * 1346189075374 - milliseconds since 1970-1-1, common in java
82
83 With Second Granularity
84
85 * 1346189075 - seconds since 1970-1-1, common in unix
86 * 2012-08-28T21:24:35Z - RFC3339
87 * 2012-08-28T21:24:35-08:00 - RFC3339 with numeric timezone
88 * Tue, 28 Aug 2012 21:24:35 +0000 - RFC1123 + numeric timezone
89 * Tue, 28 Aug 2012 21:24:35 UTC - RFC1123
90 * Tue Aug 28 21:24:35 UTC 2012 - Unix date
91 * Tue Aug 28 21:24:35 2012 - ansi C timestamp
92 * Tue Aug 28 21:24:35 +0000 2012 - ruby datestamp
93
94 With More Coarse Granularities
95
96 * 2012-08-28T21:24 (This will be considered the same as 2012-08-28T21:24:00Z)
97 * 2012-08-28T21 (This will be considered the same as 2012-08-28T21:00:00Z)
98 * 2012-08-28 (This will be considered the same as 2012-08-28T00:00:00Z)
99 * 2012-08 (This will be considered the same as 2012-08-01T00:00:00Z)
100 * 2012 (This will be considered the same as 2012-01-01T00:00:00Z)
101 `
102
103 func (n *atDir) Lookup(ctx context.Context, name string) (fusefs.Node, error) {
104 Logger.Printf("fs.atDir: Lookup(%q)", name)
105
106 if name == "README.txt" {
107 return staticFileNode(atReadme), nil
108 }
109
110 asOf, err := parseTime(name)
111 if err != nil {
112 Logger.Printf("Can't parse time: %v", err)
113 return nil, fuse.ENOENT
114 }
115
116 return &rootsDir{fs: n.fs, at: asOf}, nil
117 }