source: code/trunk/vendor/modernc.org/cc/v3/filesystem.go@ 823

Last change on this file since 823 was 822, checked in by yakumo.izuru, 22 months ago

Prefer immortal.run over runit and rc.d, use vendored modules
for convenience.

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 3.7 KB
Line 
1// Copyright 2019 The CC Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package cc
6
7import (
8 "io"
9 "io/ioutil"
10 "os"
11 "path"
12 "strings"
13 "time"
14)
15
16// Filesystem abstraction used in CC. The underlying value must be comparable (e.g. pointer) to be used in map keys.
17type Filesystem interface {
18 // Stat is an analog of os.Stat, but also accepts a flag to indicate a system include (<file.h>).
19 Stat(path string, sys bool) (os.FileInfo, error)
20 // Open is an analog of os.Open, but also accepts a flag to indicate a system include (<file.h>).
21 Open(path string, sys bool) (io.ReadCloser, error)
22}
23
24// LocalFS returns a local filesystem implementation.
25func LocalFS() Filesystem {
26 return localFS{}
27}
28
29type localFS struct{}
30
31// Stat implements Filesystem.
32func (localFS) Stat(path string, sys bool) (os.FileInfo, error) {
33 return os.Stat(path)
34}
35
36// Open implements Filesystem.
37func (localFS) Open(path string, sys bool) (io.ReadCloser, error) {
38 return os.Open(path)
39}
40
41// WorkingDir is a filesystem implementation that resolves paths relative to a given directory.
42// If filesystem is not specified, the local one will be used.
43func WorkingDir(wd string, fs Filesystem) Filesystem {
44 if fs == nil {
45 fs = LocalFS()
46 }
47 return workDir{fs: fs, wd: wd}
48}
49
50type workDir struct {
51 fs Filesystem
52 wd string
53}
54
55// Stat implements Filesystem.
56func (fs workDir) Stat(fname string, sys bool) (os.FileInfo, error) {
57 if !path.IsAbs(fname) {
58 fname = path.Join(fs.wd, fname)
59 }
60 return fs.fs.Stat(fname, sys)
61}
62
63// Open implements Filesystem.
64func (fs workDir) Open(fname string, sys bool) (io.ReadCloser, error) {
65 if !path.IsAbs(fname) {
66 fname = path.Join(fs.wd, fname)
67 }
68 return fs.fs.Open(fname, sys)
69}
70
71// Overlay is a filesystem implementation that first check if the file is available in the primary FS
72// and if not, falls back to a secondary FS.
73func Overlay(pri, sec Filesystem) Filesystem {
74 return overlayFS{pri: pri, sec: sec}
75}
76
77type overlayFS struct {
78 pri, sec Filesystem
79}
80
81// Stat implements Filesystem.
82func (fs overlayFS) Stat(path string, sys bool) (os.FileInfo, error) {
83 st, err := fs.pri.Stat(path, sys)
84 if err == nil || !os.IsNotExist(err) {
85 return st, err
86 }
87 return fs.sec.Stat(path, sys)
88}
89
90// Open implements Filesystem.
91func (fs overlayFS) Open(path string, sys bool) (io.ReadCloser, error) {
92 f, err := fs.pri.Open(path, sys)
93 if err == nil || !os.IsNotExist(err) {
94 return f, err
95 }
96 return fs.sec.Open(path, sys)
97}
98
99// StaticFS implements filesystem interface by serving string values form the provided map.
100func StaticFS(files map[string]string) Filesystem {
101 return &staticFS{m: files, ts: time.Now()}
102}
103
104type staticFS struct {
105 ts time.Time
106 m map[string]string
107}
108
109// Stat implements Filesystem.
110func (fs *staticFS) Stat(path string, sys bool) (os.FileInfo, error) {
111 v, ok := fs.m[path]
112 if !ok {
113 return nil, &os.PathError{"stat", path, os.ErrNotExist}
114 }
115 return staticFileInfo{name: path, size: int64(len(v)), mode: 0, mod: fs.ts}, nil
116}
117
118// Open implements Filesystem.
119func (fs *staticFS) Open(path string, sys bool) (io.ReadCloser, error) {
120 v, ok := fs.m[path]
121 if !ok {
122 return nil, &os.PathError{"open", path, os.ErrNotExist}
123 }
124 return ioutil.NopCloser(strings.NewReader(v)), nil
125}
126
127type staticFileInfo struct {
128 name string
129 size int64
130 mode os.FileMode
131 mod time.Time
132}
133
134func (fi staticFileInfo) Name() string {
135 return fi.name
136}
137
138func (fi staticFileInfo) Size() int64 {
139 return fi.size
140}
141
142func (fi staticFileInfo) Mode() os.FileMode {
143 return fi.mode
144}
145
146func (fi staticFileInfo) ModTime() time.Time {
147 return fi.mod
148}
149
150func (fi staticFileInfo) IsDir() bool {
151 return fi.mode.IsDir()
152}
153
154func (fi staticFileInfo) Sys() interface{} {
155 return fi
156}
Note: See TracBrowser for help on using the repository browser.