github.com/slspeek/camlistore_namedsearch@v0.0.0-20140519202248-ed6f70f7721a/pkg/fs/at.go (about) 1 // +build linux darwin 2 3 /* 4 Copyright 2012 Google Inc. 5 6 Licensed under the Apache License, Version 2.0 (the "License"); 7 you may not use this file except in compliance with the License. 8 You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 See the License for the specific language governing permissions and 16 limitations under the License. 17 */ 18 19 package fs 20 21 import ( 22 "log" 23 "os" 24 25 "camlistore.org/third_party/bazil.org/fuse" 26 fusefs "camlistore.org/third_party/bazil.org/fuse/fs" 27 ) 28 29 type atDir struct { 30 noXattr 31 fs *CamliFileSystem 32 } 33 34 func (n *atDir) Attr() fuse.Attr { 35 return fuse.Attr{ 36 Mode: os.ModeDir | 0500, 37 Uid: uint32(os.Getuid()), 38 Gid: uint32(os.Getgid()), 39 } 40 } 41 42 func (n *atDir) ReadDir(intr fusefs.Intr) ([]fuse.Dirent, fuse.Error) { 43 return []fuse.Dirent{ 44 {Name: "README.txt"}, 45 }, nil 46 } 47 48 const atReadme = `You are now in the "at" filesystem, where you can look into the past. 49 50 Locations in the top-level of this directory are dynamically created 51 as you request them. A dynamic directory is designated by a 52 timestamp. Once you enter a directory, you'll have a read-only view 53 of all of the roots that existed as of the specified time. 54 55 Example: 56 57 If you had a root called "importantstuff" and a file in it called 58 "todo.txt", you can look at the contents of that file as it existed 59 back before Christmas like this (from the location you mounted 60 camlistore): 61 62 cat at/2013-12-24/importantstuff/todo.txt 63 64 If you cd into "at/2013-12-24/importantstuff" you can also see all the 65 files that you deleted since (but none that were created after). 66 67 Timestamps are specified in UTC unless otherwise specified, and may be 68 in any of the following forms: 69 70 With Nanosecond Granularity 71 72 * 2012-08-28T21:24:35.37465188Z - RFC3339 (this is the canonical format) 73 * 1346189075374651880 - nanoseconds since 1970-1-1 74 75 With Millisecond Granularity 76 77 * 1346189075374 - milliseconds since 1970-1-1, common in java 78 79 With Second Granularity 80 81 * 1346189075 - seconds since 1970-1-1, common in unix 82 * 2012-08-28T21:24:35Z - RFC3339 83 * 2012-08-28T21:24:35-08:00 - RFC3339 with numeric timezone 84 * Tue, 28 Aug 2012 21:24:35 +0000 - RFC1123 + numeric timezone 85 * Tue, 28 Aug 2012 21:24:35 UTC RFC1123 86 * Tue Aug 28 21:24:35 UTC 2012 - Unix date 87 * Tue Aug 28 21:24:35 2012 - ansi C timestamp 88 * Tue Aug 28 21:24:35 +0000 2012 - ruby datestamp 89 90 With More Coarse Granularities 91 92 * 2012-08-28T21:24 (This will be considered the same as 2012-08-28T21:24:00Z) 93 * 2012-08-28T21 (This will be considered the same as 2012-08-28T21:00:00Z) 94 * 2012-08-28 (This will be considered the same as 2012-08-28T00:00:00Z) 95 * 2012-08 (This will be considered the same as 2012-08-01T00:00:00Z) 96 * 2012 (This will be considered the same as 2012-01-01T00:00:00Z) 97 ` 98 99 func (n *atDir) Lookup(name string, intr fusefs.Intr) (fusefs.Node, fuse.Error) { 100 log.Printf("fs.atDir: Lookup(%q)", name) 101 102 if name == "README.txt" { 103 return staticFileNode(atReadme), nil 104 } 105 106 asOf, err := parseTime(name) 107 if err != nil { 108 log.Printf("Can't parse time: %v", err) 109 return nil, fuse.ENOENT 110 } 111 112 return &rootsDir{fs: n.fs, at: asOf}, nil 113 }