-
Notifications
You must be signed in to change notification settings - Fork 1
/
fileinfo.go
158 lines (131 loc) · 3.16 KB
/
fileinfo.go
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
149
150
151
152
153
154
155
156
157
158
/*
* Rufs - Remote Union File System
*
* Copyright 2017 Matthias Ladkau. All rights reserved.
*
* This Source Code Form is subject to the terms of the MIT
* License, If a copy of the MIT License was not distributed with this
* file, You can obtain one at https://opensource.org/licenses/MIT.
*/
package rufs
import (
"fmt"
"os"
"path/filepath"
"time"
)
/*
Special unit test flag - use a common mode to gloss over OS specific
defaults
*/
var unitTestModes = false
/*
FileInfo implements os.FileInfo in an platform-agnostic way
*/
type FileInfo struct {
FiName string // Base name
FiSize int64 // Size in bytes
FiMode os.FileMode // File mode bits
FiModTime time.Time // Modification time
FiChecksum string // Checksum of files
// Private fields which will not be transferred via RPC
isSymLink bool // Flag if this is a symlink (unix)
symLinkTarget string // Target file/directory of the symlink
}
/*
WrapFileInfo wraps a single os.FileInfo object in a serializable FileInfo.
*/
func WrapFileInfo(path string, i os.FileInfo) os.FileInfo {
var realPath string
// Check if we have a symlink
mode := i.Mode()
size := i.Size()
isSymlink := i.Mode()&os.ModeSymlink != 0
if isSymlink {
var err error
if realPath, err = filepath.EvalSymlinks(filepath.Join(path, i.Name())); err == nil {
var ri os.FileInfo
if ri, err = os.Stat(realPath); err == nil {
// Write in the size of the target and file mode
mode = ri.Mode()
size = ri.Size()
}
}
}
// Unit test fixed file modes
if unitTestModes {
mode = mode & os.ModeDir
if mode.IsDir() {
mode = mode | 0777
size = 4096
} else {
mode = mode | 0666
}
}
return &FileInfo{i.Name(), size, mode, i.ModTime(), "",
isSymlink, realPath}
}
/*
WrapFileInfos wraps a list of os.FileInfo objects into a list of
serializable FileInfo objects. This function will modify the given
list.
*/
func WrapFileInfos(path string, is []os.FileInfo) []os.FileInfo {
for i, info := range is {
is[i] = WrapFileInfo(path, info)
}
return is
}
/*
Name returns the base name.
*/
func (rfi *FileInfo) Name() string {
return rfi.FiName
}
/*
Size returns the length in bytes.
*/
func (rfi *FileInfo) Size() int64 {
return rfi.FiSize
}
/*
Mode returns the file mode bits.
*/
func (rfi *FileInfo) Mode() os.FileMode {
return rfi.FiMode
}
/*
ModTime returns the modification time.
*/
func (rfi *FileInfo) ModTime() time.Time {
return rfi.FiModTime
}
/*
Checksum returns the checksum of this file. May be an empty string if it was
not calculated.
*/
func (rfi *FileInfo) Checksum() string {
return rfi.FiChecksum
}
/*
IsDir returns if this is a directory.
*/
func (rfi *FileInfo) IsDir() bool {
return rfi.FiMode.IsDir()
}
/*
Sys should return the underlying data source but will always return nil
for FileInfo nodes.
*/
func (rfi *FileInfo) Sys() interface{} {
return nil
}
func (rfi *FileInfo) String() string {
sum := rfi.Checksum()
if sum != "" {
return fmt.Sprintf("%v %s [%v] %v (%v) - %v", rfi.Name(), sum, rfi.Size(),
rfi.Mode(), rfi.ModTime(), rfi.Sys())
}
return fmt.Sprintf("%v [%v] %v (%v) - %v", rfi.Name(), rfi.Size(),
rfi.Mode(), rfi.ModTime(), rfi.Sys())
}