code/go/internal/linkedfiles/fs.go (48 lines of code) (raw):

// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one // or more contributor license agreements. Licensed under the Elastic License; // you may not use this file except in compliance with the Elastic License. package linkedfiles import ( "errors" "fmt" "io/fs" "os" "path/filepath" ) const linkExtension = ".link" var ( _ fs.FS = (*FS)(nil) _ fs.FS = (*BlockFS)(nil) // ErrUnsupportedLinkFile is returned when a linked file is not supported. ErrUnsupportedLinkFile = errors.New("linked files are not supported in this filesystem") ) // FS is a filesystem that handles linked files. // It wraps another filesystem and checks for linked files with the ".link" extension. // If a linked file is found, it reads the link file to determine the target file // and its checksum. If the target file is up to date, it returns the target file. // Otherwise, it returns an error. type FS struct { workDir string inner fs.FS } // NewFS creates a new FS. func NewFS(workDir string, inner fs.FS) *FS { return &FS{workDir: workDir, inner: inner} } // Open opens a file in the filesystem. func (lfs *FS) Open(name string) (fs.File, error) { if filepath.Ext(name) != linkExtension { return lfs.inner.Open(name) } pathName := filepath.Join(lfs.workDir, name) l, err := NewLinkedFile(pathName) if err != nil { return nil, err } if !l.UpToDate { return nil, fmt.Errorf("linked file %s is not up to date", name) } includedPath := filepath.Join(lfs.workDir, filepath.Dir(name), l.IncludedFilePath) return os.Open(includedPath) } // BlockFS is a filesystem that blocks use of linked files. type BlockFS struct { inner fs.FS } // NewBlockFS creates a new BlockFS. func NewBlockFS(inner fs.FS) *BlockFS { return &BlockFS{inner: inner} } // Open opens a file in the filesystem. func (bfs *BlockFS) Open(name string) (fs.File, error) { if filepath.Ext(name) == linkExtension { return nil, ErrUnsupportedLinkFile } return bfs.inner.Open(name) }