mirror of
https://github.com/golang/go.git
synced 2025-05-23 00:11:26 +00:00
Also clarify the permissions of created files, and note that CopyFS will not overwrite files. Update a few places in documentation to use 0oXXX for octal consts. For #62484 Change-Id: I208ed2bde250304bc7fac2b93963ba57037e791e Reviewed-on: https://go-review.googlesource.com/c/go/+/600775 Reviewed-by: Ian Lance Taylor <iant@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> (cherry picked from commit 910e6b5fae7cbf84e4a3fcfa6739e20239080bcd) Reviewed-on: https://go-review.googlesource.com/c/go/+/600815 Reviewed-by: Ian Lance Taylor <iant@google.com>
396 lines
8.4 KiB
Go
396 lines
8.4 KiB
Go
// Copyright 2016 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package os_test
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io/fs"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
func ExampleOpenFile() {
|
|
f, err := os.OpenFile("notes.txt", os.O_RDWR|os.O_CREATE, 0644)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if err := f.Close(); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func ExampleOpenFile_append() {
|
|
// If the file doesn't exist, create it, or append to the file
|
|
f, err := os.OpenFile("access.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if _, err := f.Write([]byte("appended some data\n")); err != nil {
|
|
f.Close() // ignore error; Write error takes precedence
|
|
log.Fatal(err)
|
|
}
|
|
if err := f.Close(); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func ExampleChmod() {
|
|
if err := os.Chmod("some-filename", 0644); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func ExampleChtimes() {
|
|
mtime := time.Date(2006, time.February, 1, 3, 4, 5, 0, time.UTC)
|
|
atime := time.Date(2007, time.March, 2, 4, 5, 6, 0, time.UTC)
|
|
if err := os.Chtimes("some-filename", atime, mtime); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func ExampleFileMode() {
|
|
fi, err := os.Lstat("some-filename")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
fmt.Printf("permissions: %#o\n", fi.Mode().Perm()) // 0o400, 0o777, etc.
|
|
switch mode := fi.Mode(); {
|
|
case mode.IsRegular():
|
|
fmt.Println("regular file")
|
|
case mode.IsDir():
|
|
fmt.Println("directory")
|
|
case mode&fs.ModeSymlink != 0:
|
|
fmt.Println("symbolic link")
|
|
case mode&fs.ModeNamedPipe != 0:
|
|
fmt.Println("named pipe")
|
|
}
|
|
}
|
|
|
|
func ExampleErrNotExist() {
|
|
filename := "a-nonexistent-file"
|
|
if _, err := os.Stat(filename); errors.Is(err, fs.ErrNotExist) {
|
|
fmt.Println("file does not exist")
|
|
}
|
|
// Output:
|
|
// file does not exist
|
|
}
|
|
|
|
func ExampleExpand() {
|
|
mapper := func(placeholderName string) string {
|
|
switch placeholderName {
|
|
case "DAY_PART":
|
|
return "morning"
|
|
case "NAME":
|
|
return "Gopher"
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
fmt.Println(os.Expand("Good ${DAY_PART}, $NAME!", mapper))
|
|
|
|
// Output:
|
|
// Good morning, Gopher!
|
|
}
|
|
|
|
func ExampleExpandEnv() {
|
|
os.Setenv("NAME", "gopher")
|
|
os.Setenv("BURROW", "/usr/gopher")
|
|
|
|
fmt.Println(os.ExpandEnv("$NAME lives in ${BURROW}."))
|
|
|
|
// Output:
|
|
// gopher lives in /usr/gopher.
|
|
}
|
|
|
|
func ExampleLookupEnv() {
|
|
show := func(key string) {
|
|
val, ok := os.LookupEnv(key)
|
|
if !ok {
|
|
fmt.Printf("%s not set\n", key)
|
|
} else {
|
|
fmt.Printf("%s=%s\n", key, val)
|
|
}
|
|
}
|
|
|
|
os.Setenv("SOME_KEY", "value")
|
|
os.Setenv("EMPTY_KEY", "")
|
|
|
|
show("SOME_KEY")
|
|
show("EMPTY_KEY")
|
|
show("MISSING_KEY")
|
|
|
|
// Output:
|
|
// SOME_KEY=value
|
|
// EMPTY_KEY=
|
|
// MISSING_KEY not set
|
|
}
|
|
|
|
func ExampleGetenv() {
|
|
os.Setenv("NAME", "gopher")
|
|
os.Setenv("BURROW", "/usr/gopher")
|
|
|
|
fmt.Printf("%s lives in %s.\n", os.Getenv("NAME"), os.Getenv("BURROW"))
|
|
|
|
// Output:
|
|
// gopher lives in /usr/gopher.
|
|
}
|
|
|
|
func ExampleUnsetenv() {
|
|
os.Setenv("TMPDIR", "/my/tmp")
|
|
defer os.Unsetenv("TMPDIR")
|
|
}
|
|
|
|
func ExampleReadDir() {
|
|
files, err := os.ReadDir(".")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
for _, file := range files {
|
|
fmt.Println(file.Name())
|
|
}
|
|
}
|
|
|
|
func ExampleMkdirTemp() {
|
|
dir, err := os.MkdirTemp("", "example")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer os.RemoveAll(dir) // clean up
|
|
|
|
file := filepath.Join(dir, "tmpfile")
|
|
if err := os.WriteFile(file, []byte("content"), 0666); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func ExampleMkdirTemp_suffix() {
|
|
logsDir, err := os.MkdirTemp("", "*-logs")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer os.RemoveAll(logsDir) // clean up
|
|
|
|
// Logs can be cleaned out earlier if needed by searching
|
|
// for all directories whose suffix ends in *-logs.
|
|
globPattern := filepath.Join(os.TempDir(), "*-logs")
|
|
matches, err := filepath.Glob(globPattern)
|
|
if err != nil {
|
|
log.Fatalf("Failed to match %q: %v", globPattern, err)
|
|
}
|
|
|
|
for _, match := range matches {
|
|
if err := os.RemoveAll(match); err != nil {
|
|
log.Printf("Failed to remove %q: %v", match, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func ExampleCreateTemp() {
|
|
f, err := os.CreateTemp("", "example")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer os.Remove(f.Name()) // clean up
|
|
|
|
if _, err := f.Write([]byte("content")); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if err := f.Close(); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func ExampleCreateTemp_suffix() {
|
|
f, err := os.CreateTemp("", "example.*.txt")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer os.Remove(f.Name()) // clean up
|
|
|
|
if _, err := f.Write([]byte("content")); err != nil {
|
|
f.Close()
|
|
log.Fatal(err)
|
|
}
|
|
if err := f.Close(); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func ExampleReadFile() {
|
|
data, err := os.ReadFile("testdata/hello")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
os.Stdout.Write(data)
|
|
|
|
// Output:
|
|
// Hello, Gophers!
|
|
}
|
|
|
|
func ExampleWriteFile() {
|
|
err := os.WriteFile("testdata/hello", []byte("Hello, Gophers!"), 0666)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func ExampleMkdir() {
|
|
err := os.Mkdir("testdir", 0750)
|
|
if err != nil && !os.IsExist(err) {
|
|
log.Fatal(err)
|
|
}
|
|
err = os.WriteFile("testdir/testfile.txt", []byte("Hello, Gophers!"), 0660)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func ExampleMkdirAll() {
|
|
err := os.MkdirAll("test/subdir", 0750)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
err = os.WriteFile("test/subdir/testfile.txt", []byte("Hello, Gophers!"), 0660)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func ExampleReadlink() {
|
|
// First, we create a relative symlink to a file.
|
|
d, err := os.MkdirTemp("", "")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer os.RemoveAll(d)
|
|
targetPath := filepath.Join(d, "hello.txt")
|
|
if err := os.WriteFile(targetPath, []byte("Hello, Gophers!"), 0644); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
linkPath := filepath.Join(d, "hello.link")
|
|
if err := os.Symlink("hello.txt", filepath.Join(d, "hello.link")); err != nil {
|
|
if errors.Is(err, errors.ErrUnsupported) {
|
|
// Allow the example to run on platforms that do not support symbolic links.
|
|
fmt.Printf("%s links to %s\n", filepath.Base(linkPath), "hello.txt")
|
|
return
|
|
}
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Readlink returns the relative path as passed to os.Symlink.
|
|
dst, err := os.Readlink(linkPath)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
fmt.Printf("%s links to %s\n", filepath.Base(linkPath), dst)
|
|
|
|
var dstAbs string
|
|
if filepath.IsAbs(dst) {
|
|
dstAbs = dst
|
|
} else {
|
|
// Symlink targets are relative to the directory containing the link.
|
|
dstAbs = filepath.Join(filepath.Dir(linkPath), dst)
|
|
}
|
|
|
|
// Check that the target is correct by comparing it with os.Stat
|
|
// on the original target path.
|
|
dstInfo, err := os.Stat(dstAbs)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
targetInfo, err := os.Stat(targetPath)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
if !os.SameFile(dstInfo, targetInfo) {
|
|
log.Fatalf("link destination (%s) is not the same file as %s", dstAbs, targetPath)
|
|
}
|
|
|
|
// Output:
|
|
// hello.link links to hello.txt
|
|
}
|
|
|
|
func ExampleUserCacheDir() {
|
|
dir, dirErr := os.UserCacheDir()
|
|
if dirErr == nil {
|
|
dir = filepath.Join(dir, "ExampleUserCacheDir")
|
|
}
|
|
|
|
getCache := func(name string) ([]byte, error) {
|
|
if dirErr != nil {
|
|
return nil, &os.PathError{Op: "getCache", Path: name, Err: os.ErrNotExist}
|
|
}
|
|
return os.ReadFile(filepath.Join(dir, name))
|
|
}
|
|
|
|
var mkdirOnce sync.Once
|
|
putCache := func(name string, b []byte) error {
|
|
if dirErr != nil {
|
|
return &os.PathError{Op: "putCache", Path: name, Err: dirErr}
|
|
}
|
|
mkdirOnce.Do(func() {
|
|
if err := os.MkdirAll(dir, 0700); err != nil {
|
|
log.Printf("can't create user cache dir: %v", err)
|
|
}
|
|
})
|
|
return os.WriteFile(filepath.Join(dir, name), b, 0600)
|
|
}
|
|
|
|
// Read and store cached data.
|
|
// …
|
|
_ = getCache
|
|
_ = putCache
|
|
|
|
// Output:
|
|
}
|
|
|
|
func ExampleUserConfigDir() {
|
|
dir, dirErr := os.UserConfigDir()
|
|
|
|
var (
|
|
configPath string
|
|
origConfig []byte
|
|
)
|
|
if dirErr == nil {
|
|
configPath = filepath.Join(dir, "ExampleUserConfigDir", "example.conf")
|
|
var err error
|
|
origConfig, err = os.ReadFile(configPath)
|
|
if err != nil && !os.IsNotExist(err) {
|
|
// The user has a config file but we couldn't read it.
|
|
// Report the error instead of ignoring their configuration.
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// Use and perhaps make changes to the config.
|
|
config := bytes.Clone(origConfig)
|
|
// …
|
|
|
|
// Save changes.
|
|
if !bytes.Equal(config, origConfig) {
|
|
if configPath == "" {
|
|
log.Printf("not saving config changes: %v", dirErr)
|
|
} else {
|
|
err := os.MkdirAll(filepath.Dir(configPath), 0700)
|
|
if err == nil {
|
|
err = os.WriteFile(configPath, config, 0600)
|
|
}
|
|
if err != nil {
|
|
log.Printf("error saving config changes: %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Output:
|
|
}
|