xref: /aosp_15_r20/external/bazelbuild-rules_go/go/runfiles/fs.go (revision 9bb1b549b6a84214c53be0924760be030e66b93a)
1*9bb1b549SSpandan Das// Copyright 2021, 2022 Google LLC
2*9bb1b549SSpandan Das//
3*9bb1b549SSpandan Das// Licensed under the Apache License, Version 2.0 (the "License");
4*9bb1b549SSpandan Das// you may not use this file except in compliance with the License.
5*9bb1b549SSpandan Das// You may obtain a copy of the License at
6*9bb1b549SSpandan Das//
7*9bb1b549SSpandan Das//     https://www.apache.org/licenses/LICENSE-2.0
8*9bb1b549SSpandan Das//
9*9bb1b549SSpandan Das// Unless required by applicable law or agreed to in writing, software
10*9bb1b549SSpandan Das// distributed under the License is distributed on an "AS IS" BASIS,
11*9bb1b549SSpandan Das// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9bb1b549SSpandan Das// See the License for the specific language governing permissions and
13*9bb1b549SSpandan Das// limitations under the License.
14*9bb1b549SSpandan Das
15*9bb1b549SSpandan Das//go:build go1.16
16*9bb1b549SSpandan Das// +build go1.16
17*9bb1b549SSpandan Das
18*9bb1b549SSpandan Daspackage runfiles
19*9bb1b549SSpandan Das
20*9bb1b549SSpandan Dasimport (
21*9bb1b549SSpandan Das	"errors"
22*9bb1b549SSpandan Das	"io"
23*9bb1b549SSpandan Das	"io/fs"
24*9bb1b549SSpandan Das	"os"
25*9bb1b549SSpandan Das	"time"
26*9bb1b549SSpandan Das)
27*9bb1b549SSpandan Das
28*9bb1b549SSpandan Das// Open implements fs.FS.Open.
29*9bb1b549SSpandan Dasfunc (r *Runfiles) Open(name string) (fs.File, error) {
30*9bb1b549SSpandan Das	if !fs.ValidPath(name) {
31*9bb1b549SSpandan Das		return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrInvalid}
32*9bb1b549SSpandan Das	}
33*9bb1b549SSpandan Das	p, err := r.Rlocation(name)
34*9bb1b549SSpandan Das	if errors.Is(err, ErrEmpty) {
35*9bb1b549SSpandan Das		return emptyFile(name), nil
36*9bb1b549SSpandan Das	}
37*9bb1b549SSpandan Das	if err != nil {
38*9bb1b549SSpandan Das		return nil, pathError("open", name, err)
39*9bb1b549SSpandan Das	}
40*9bb1b549SSpandan Das	return os.Open(p)
41*9bb1b549SSpandan Das}
42*9bb1b549SSpandan Das
43*9bb1b549SSpandan Das// Stat implements fs.StatFS.Stat.
44*9bb1b549SSpandan Dasfunc (r *Runfiles) Stat(name string) (fs.FileInfo, error) {
45*9bb1b549SSpandan Das	if !fs.ValidPath(name) {
46*9bb1b549SSpandan Das		return nil, &fs.PathError{Op: "stat", Path: name, Err: fs.ErrInvalid}
47*9bb1b549SSpandan Das	}
48*9bb1b549SSpandan Das	p, err := r.Rlocation(name)
49*9bb1b549SSpandan Das	if errors.Is(err, ErrEmpty) {
50*9bb1b549SSpandan Das		return emptyFileInfo(name), nil
51*9bb1b549SSpandan Das	}
52*9bb1b549SSpandan Das	if err != nil {
53*9bb1b549SSpandan Das		return nil, pathError("stat", name, err)
54*9bb1b549SSpandan Das	}
55*9bb1b549SSpandan Das	return os.Stat(p)
56*9bb1b549SSpandan Das}
57*9bb1b549SSpandan Das
58*9bb1b549SSpandan Das// ReadFile implements fs.ReadFileFS.ReadFile.
59*9bb1b549SSpandan Dasfunc (r *Runfiles) ReadFile(name string) ([]byte, error) {
60*9bb1b549SSpandan Das	if !fs.ValidPath(name) {
61*9bb1b549SSpandan Das		return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrInvalid}
62*9bb1b549SSpandan Das	}
63*9bb1b549SSpandan Das	p, err := r.Rlocation(name)
64*9bb1b549SSpandan Das	if errors.Is(err, ErrEmpty) {
65*9bb1b549SSpandan Das		return nil, nil
66*9bb1b549SSpandan Das	}
67*9bb1b549SSpandan Das	if err != nil {
68*9bb1b549SSpandan Das		return nil, pathError("open", name, err)
69*9bb1b549SSpandan Das	}
70*9bb1b549SSpandan Das	return os.ReadFile(p)
71*9bb1b549SSpandan Das}
72*9bb1b549SSpandan Das
73*9bb1b549SSpandan Dastype emptyFile string
74*9bb1b549SSpandan Das
75*9bb1b549SSpandan Dasfunc (f emptyFile) Stat() (fs.FileInfo, error) { return emptyFileInfo(f), nil }
76*9bb1b549SSpandan Dasfunc (f emptyFile) Read([]byte) (int, error)   { return 0, io.EOF }
77*9bb1b549SSpandan Dasfunc (emptyFile) Close() error                 { return nil }
78*9bb1b549SSpandan Das
79*9bb1b549SSpandan Dastype emptyFileInfo string
80*9bb1b549SSpandan Das
81*9bb1b549SSpandan Dasfunc (i emptyFileInfo) Name() string     { return string(i) }
82*9bb1b549SSpandan Dasfunc (emptyFileInfo) Size() int64        { return 0 }
83*9bb1b549SSpandan Dasfunc (emptyFileInfo) Mode() fs.FileMode  { return 0444 }
84*9bb1b549SSpandan Dasfunc (emptyFileInfo) ModTime() time.Time { return time.Time{} }
85*9bb1b549SSpandan Dasfunc (emptyFileInfo) IsDir() bool        { return false }
86*9bb1b549SSpandan Dasfunc (emptyFileInfo) Sys() interface{}   { return nil }
87*9bb1b549SSpandan Das
88*9bb1b549SSpandan Dasfunc pathError(op, name string, err error) error {
89*9bb1b549SSpandan Das	if err == nil {
90*9bb1b549SSpandan Das		return nil
91*9bb1b549SSpandan Das	}
92*9bb1b549SSpandan Das	var rerr Error
93*9bb1b549SSpandan Das	if errors.As(err, &rerr) {
94*9bb1b549SSpandan Das		// Unwrap the error because we don’t need the failing name
95*9bb1b549SSpandan Das		// twice.
96*9bb1b549SSpandan Das		return &fs.PathError{Op: op, Path: rerr.Name, Err: rerr.Err}
97*9bb1b549SSpandan Das	}
98*9bb1b549SSpandan Das	return &fs.PathError{Op: op, Path: name, Err: err}
99*9bb1b549SSpandan Das}
100