Home Download Docs Code Community
     1	//go:build linux
     2	
     3	/*
     4	Copyright 2012 The Perkeep Authors
     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		"context"
    23		"log"
    24		"os"
    25		"sync"
    26	
    27		"bazil.org/fuse"
    28		"bazil.org/fuse/fs"
    29		"perkeep.org/pkg/blob"
    30	)
    31	
    32	// root implements fuse.Node and is the typical root of a
    33	// CamliFilesystem with a little hello message and the ability to
    34	// search and browse static snapshots, etc.
    35	type root struct {
    36		fs *CamliFileSystem
    37	
    38		mu          sync.Mutex
    39		recent      *recentDir
    40		roots       *rootsDir
    41		atDir       *atDir
    42		versionsDir *versionsDir
    43	}
    44	
    45	var (
    46		_ fs.Node               = (*root)(nil)
    47		_ fs.HandleReadDirAller = (*root)(nil)
    48		_ fs.NodeStringLookuper = (*root)(nil)
    49	)
    50	
    51	func (n *root) Attr(ctx context.Context, a *fuse.Attr) error {
    52		a.Mode = os.ModeDir | 0700
    53		a.Uid = uint32(os.Getuid())
    54		a.Gid = uint32(os.Getgid())
    55		return nil
    56	}
    57	
    58	func (n *root) ReadDirAll(ctx context.Context) ([]fuse.Dirent, error) {
    59		return []fuse.Dirent{
    60			{Name: "WELCOME.txt"},
    61			{Name: "tag"},
    62			{Name: "date"},
    63			{Name: "recent"},
    64			{Name: "roots"},
    65			{Name: "at"},
    66			{Name: "sha1-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},
    67			{Name: "sha224-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},
    68			{Name: "versions"},
    69		}, nil
    70	}
    71	
    72	func (n *root) getRecentDir() *recentDir {
    73		n.mu.Lock()
    74		defer n.mu.Unlock()
    75		if n.recent == nil {
    76			n.recent = &recentDir{fs: n.fs}
    77		}
    78		return n.recent
    79	}
    80	
    81	func (n *root) getRootsDir() *rootsDir {
    82		n.mu.Lock()
    83		defer n.mu.Unlock()
    84		if n.roots == nil {
    85			n.roots = &rootsDir{fs: n.fs}
    86		}
    87		return n.roots
    88	}
    89	
    90	func (n *root) getAtDir() *atDir {
    91		n.mu.Lock()
    92		defer n.mu.Unlock()
    93		if n.atDir == nil {
    94			n.atDir = &atDir{fs: n.fs}
    95		}
    96		return n.atDir
    97	}
    98	
    99	func (n *root) getVersionsDir() *versionsDir {
   100		n.mu.Lock()
   101		defer n.mu.Unlock()
   102		if n.versionsDir == nil {
   103			n.versionsDir = &versionsDir{fs: n.fs}
   104		}
   105		return n.versionsDir
   106	}
   107	
   108	func (n *root) Lookup(ctx context.Context, name string) (fs.Node, error) {
   109		Logger.Printf("root.Lookup(%s)", name)
   110		switch name {
   111		case ".quitquitquit":
   112			log.Fatalf("Shutting down due to root .quitquitquit lookup.")
   113		case "WELCOME.txt":
   114			return staticFileNode("Welcome to PerkeepFS.\n\nMore information is available in the pk-mount documentation.\n\nSee https://perkeep.org/cmd/pk-mount/ , or run 'go doc perkeep.org/cmd/pk-mount'.\n"), nil
   115		case "recent":
   116			return n.getRecentDir(), nil
   117		case "tag", "date":
   118			return notImplementDirNode{}, nil
   119		case "at":
   120			return n.getAtDir(), nil
   121		case "roots":
   122			return n.getRootsDir(), nil
   123		case "versions":
   124			return n.getVersionsDir(), nil
   125		case "sha1-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx":
   126			return notImplementDirNode{}, nil
   127		case "sha224-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx":
   128			return notImplementDirNode{}, nil
   129		case ".camli_fs_stats":
   130			return statsDir{}, nil
   131		case "mach_kernel", ".hidden", "._.":
   132			// Just quiet some log noise on OS X.
   133			return nil, fuse.ENOENT
   134		}
   135	
   136		if br, ok := blob.Parse(name); ok {
   137			Logger.Printf("Root lookup of blobref. %q => %v", name, br)
   138			node := &node{fs: n.fs, blobref: br}
   139			if _, err := node.schema(ctx); err != nil {
   140				if os.IsNotExist(err) {
   141					return nil, fuse.ENOENT
   142				} else {
   143					return nil, handleEIOorEINTR(err)
   144				}
   145			}
   146			return node, nil
   147		}
   148		Logger.Printf("Bogus root lookup of %q", name)
   149		return nil, fuse.ENOENT
   150	}
Website layout inspired by memcached.
Content by the authors.