| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // +build !build_with_native_toolchain |
| |
| package pkgfs |
| |
| import ( |
| "log" |
| "strings" |
| "sync" |
| "time" |
| |
| "go.fuchsia.dev/fuchsia/src/lib/thinfs/fs" |
| ) |
| |
| type ctlDirectory struct { |
| unsupportedDirectory |
| fs *Filesystem |
| mu sync.RWMutex |
| dirs map[string]fs.Directory |
| } |
| |
| func (d *ctlDirectory) Dup() (fs.Directory, error) { |
| return d, nil |
| } |
| |
| func (d *ctlDirectory) Open(name string, flags fs.OpenFlags) (fs.File, fs.Directory, *fs.Remote, error) { |
| name = clean(name) |
| if name == "" { |
| return nil, d, nil, nil |
| } |
| |
| parts := strings.SplitN(name, "/", 2) |
| |
| d.mu.RLock() |
| subdir, ok := d.dirs[parts[0]] |
| d.mu.RUnlock() |
| if !ok { |
| return nil, nil, nil, fs.ErrNotFound |
| } |
| |
| if len(parts) == 1 { |
| return nil, subdir, nil, nil |
| } |
| |
| return subdir.Open(parts[1], flags) |
| } |
| |
| func (d *ctlDirectory) Read() ([]fs.Dirent, error) { |
| |
| d.mu.RLock() |
| dirs := make([]fs.Dirent, 0, len(d.dirs)) |
| for n := range d.dirs { |
| dirs = append(dirs, dirDirEnt(n)) |
| } |
| d.mu.RUnlock() |
| return dirs, nil |
| } |
| |
| func (d *ctlDirectory) Close() error { |
| return nil |
| } |
| |
| func (d *ctlDirectory) Stat() (int64, time.Time, time.Time, error) { |
| return 0, d.fs.mountTime, d.fs.mountTime, nil |
| } |
| |
| func (d *ctlDirectory) Unlink(path string) error { |
| // the "garbage" file is a special control file. When it is unlinked, |
| // we trigger garbage collection. |
| if path == "do-not-use-this-garbage" { |
| if err := d.fs.GC(); err != nil { |
| log.Printf("unlink garbage: %s", err) |
| } |
| return nil |
| } |
| |
| return d.unsupportedDirectory.Unlink(path) |
| } |
| |
| func (d *ctlDirectory) Sync() error { |
| return d.fs.blobfs.Sync() |
| } |