-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathroot.go
More file actions
148 lines (135 loc) · 4.45 KB
/
root.go
File metadata and controls
148 lines (135 loc) · 4.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package helper
import (
"fmt"
"io"
"os"
"path/filepath"
)
// Package root contains helper functions for file system operations
// that are constrained to the root directory.
// Duplicater copies the contents of the named file to a new named file with the root.
// The function returns an error if the newpath already exists.
func Duplicater(r *os.Root, name, newname string) (int64, error) {
const createNoTruncate = os.O_CREATE | os.O_WRONLY | os.O_EXCL
return duplicater(r, name, newname, createNoTruncate)
}
// DuplicaterOW copies the contents of the named file to a new file with the root.
// The function will truncate and overwrite the newpath if it already exists.
func DuplicaterOW(r *os.Root, name, newname string) (int64, error) {
const createTruncate = os.O_CREATE | os.O_WRONLY | os.O_TRUNC
return duplicater(r, name, newname, createTruncate)
}
func duplicater(r *os.Root, name, newname string, flag int) (int64, error) {
src, err := r.Open(name)
if err != nil {
return 0, fmt.Errorf("r duplicate os.open %w", err)
}
defer src.Close()
dst, err := r.OpenFile(newname, flag, WriteWriteRead)
if err != nil {
return 0, fmt.Errorf("r duplicate os.create %w", err)
}
defer dst.Close()
const size = 4 * 1024
buf := make([]byte, size)
written, err := io.CopyBuffer(dst, src, buf)
if err != nil {
return 0, fmt.Errorf("r duplicate io.copy %w", err)
}
return written, nil
}
// FileMatchR returns true if the two named files are the same.
// It returns false if the files are of different lengths or
// if an error occurs while reading the files.
// The read buffer size is 4096 bytes.
func FileMatchR(r *os.Root, name1, name2 string) (bool, error) {
f1, err := r.Open(name1)
if err != nil {
return false, fmt.Errorf("file match os.open %s: %w", name1, err)
}
defer f1.Close()
f2, err := r.Open(name2)
if err != nil {
return false, fmt.Errorf("file match os.open %s: %w", name2, err)
}
defer f2.Close()
return fileMatch(f1, f2)
}
// RenameRoot renames a file from oldname to newname..
// It returns an error if the oldname does not exist or is a directory,
// newname already exists, or the rename fails.
func RenameRoot(r *os.Root, oldname, newname string) error {
st, err := r.Stat(oldname)
if err != nil {
return fmt.Errorf("rename file r.stat %w", err)
}
if st.IsDir() {
return fmt.Errorf("rename file oldname %w: %s", ErrFilePath, oldname)
}
if _, err = r.Stat(newname); err == nil {
return fmt.Errorf("rename file newname %w: %s", ErrExistPath, newname)
}
oldpath := filepath.Join(r.Name(), oldname)
newpath := filepath.Join(r.Name(), newname)
if err := os.Rename(oldpath, newpath); err != nil {
return fmt.Errorf("rename file os.rename %w", err)
}
return nil
}
// RenameRootOW renames a file from oldname to newname..
// It returns an error if the oldname does not exist or is a directory
// or the rename fails.
func RenameRootOW(r *os.Root, oldname, newname string) error {
st, err := r.Stat(newname)
if err == nil && st.IsDir() {
_ = r.Remove(newname)
}
return RenameRoot(r, oldname, newname)
}
// StrongIntegrityR returns the SHA-386 checksum value of the named file..
func StrongIntegrityR(r *os.Root, name string) (string, error) {
f, err := r.Open(name)
if err != nil {
return "", fmt.Errorf("strong integrity os.open %s: %w", name, err)
}
defer f.Close()
strong, err := Sum386(f)
if err != nil {
return "", fmt.Errorf("strong integrity %w", err)
}
return strong, nil
}
// TouchR creates a new, empty named file..
// If the file already exists, an error is returned.
func TouchR(r *os.Root, name string) error {
f, err := r.OpenFile(name, os.O_CREATE|os.O_EXCL, WriteWriteRead)
if err != nil {
return fmt.Errorf("touch open file %w", err)
}
if err := f.Close(); err != nil {
return fmt.Errorf("touch file close %w", err)
}
return nil
}
// TouchWR creates a new named file with the given data..
// If the file already exists, an error is returned.
func TouchWR(r *os.Root, name string, data ...byte) (int, error) {
file, err := r.OpenFile(name, os.O_CREATE|os.O_EXCL|os.O_WRONLY, WriteWriteRead)
if err != nil {
return 0, fmt.Errorf("touch write open file %w", err)
}
if len(data) == 0 {
if err := file.Close(); err != nil {
return 0, fmt.Errorf("touch write open file close %w", err)
}
return 0, nil
}
i, err := file.Write(data)
if err != nil {
return 0, fmt.Errorf("touch write file write %w", err)
}
if err := file.Close(); err != nil {
return 0, fmt.Errorf("touch write file write close %w", err)
}
return i, nil
}