Skip to content

Commit 1a98869

Browse files
committed
Refactor symlink handling to improve errors/performance
Signed-off-by: Stephen Levine <[email protected]>
1 parent d60f4d0 commit 1a98869

File tree

4 files changed

+25
-34
lines changed

4 files changed

+25
-34
lines changed

node.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,18 @@ func (f *File) sum() ([]byte, error) {
2222
return f.Hash.File(f.Path)
2323
}
2424

25-
func (f *File) stat() (os.FileInfo, error) {
25+
func (f *File) stat(subdir bool) (os.FileInfo, error) {
2626
if f.Stdin {
2727
return os.Stdin.Stat()
2828
}
29-
return os.Lstat(f.Path)
29+
if !f.follow(subdir) {
30+
return os.Lstat(f.Path)
31+
}
32+
return os.Stat(f.Path)
3033
}
3134

32-
func (f *File) xattr() (*Xattr, error) {
33-
hashes, err := getXattr(f.Path, f.Hash)
35+
func (f *File) xattr(subdir bool) (*Xattr, error) {
36+
hashes, err := getXattr(f.Path, f.Hash, f.follow(subdir))
3437
if err != nil {
3538
return nil, err
3639
}
@@ -40,6 +43,11 @@ func (f *File) xattr() (*Xattr, error) {
4043
}, nil
4144
}
4245

46+
func (f *File) follow(subdir bool) bool {
47+
inclusive := f.Mask.Attr&AttrInclusive != 0
48+
return f.Mask.Attr&AttrFollow != 0 || (!inclusive && !subdir)
49+
}
50+
4351
type Node struct {
4452
File
4553
Sum []byte

sum.go

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,10 @@ func (s *Sum) walkFile(file File, subdir bool, sched func()) *Node {
144144
if file.Stdin {
145145
file.Mask.Attr &= ^AttrX
146146
}
147+
inclusive := file.Mask.Attr&AttrInclusive != 0
148+
noData := file.Mask.Attr&AttrNoData != 0 && (inclusive || subdir)
147149

148-
fi, err := file.stat()
150+
fi, err := file.stat(subdir)
149151
if os.IsNotExist(err) {
150152
return newFileErrorNode("", file, subdir, err)
151153
}
@@ -161,17 +163,12 @@ func (s *Sum) walkFile(file File, subdir bool, sched func()) *Node {
161163
}
162164
var xattr *Xattr
163165
if file.Mask.Attr&AttrX != 0 {
164-
xattr, err = file.xattr()
166+
xattr, err = file.xattr(subdir)
165167
if err != nil {
166168
return newFileErrorNode("get xattr", file, subdir, err)
167169
}
168170
}
169171

170-
portable := file.Mask.Attr&AttrNoName != 0
171-
inclusive := file.Mask.Attr&AttrInclusive != 0
172-
follow := file.Mask.Attr&AttrFollow != 0 || (!inclusive && !subdir)
173-
noData := file.Mask.Attr&AttrNoData != 0 && (inclusive || subdir)
174-
175172
var sum []byte
176173
switch {
177174
case fi.IsDir():
@@ -201,7 +198,7 @@ func (s *Sum) walkFile(file File, subdir bool, sched func()) *Node {
201198
return newFileErrorNode("", file, subdir, n.Err)
202199
}
203200
var name string
204-
if !portable {
201+
if file.Mask.Attr&AttrNoName == 0 {
205202
// safe because subdir nodes have generated bases
206203
name = filepath.Base(n.Path)
207204
}
@@ -223,24 +220,6 @@ func (s *Sum) walkFile(file File, subdir bool, sched func()) *Node {
223220
return newFileErrorNode("hash", file, subdir, err)
224221
}
225222

226-
case fi.Mode()&os.ModeSymlink != 0 && follow:
227-
link, err := filepath.EvalSymlinks(file.Path)
228-
if err != nil {
229-
return newFileErrorNode("", file, subdir, err) // closer to, e.g., shasum w/o action
230-
}
231-
232-
rOnce.Do(s.releaseCPU) // will be re-acquired at dest
233-
sOnce.Do(nil) // prevent defer, will be called at dest
234-
235-
path := file.Path
236-
file.Path = link
237-
n := s.walkFile(file, subdir, sched) // FIXME: pass link here instead?
238-
n.Path = path
239-
fErr := &FileError{}
240-
if errors.As(err, &fErr) && !subdir {
241-
fErr.Path = path // FIXME: account for symlink to directory, track real vs. fake path?
242-
}
243-
return n
244223
case fi.Mode()&os.ModeSymlink != 0:
245224
sOnce.Do(sched)
246225
file.Mask.Attr &= ^AttrNoName // not directory

sys_posix.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,18 @@ import (
88
"github.com/sclevine/xsum/encoding"
99
)
1010

11-
func getXattr(path string, hash Hash) ([]encoding.NamedHash, error) {
12-
attrs, err := xattr.LList(path)
11+
func getXattr(path string, hash Hash, follow bool) ([]encoding.NamedHash, error) {
12+
xlist, xget := xattr.List, xattr.Get
13+
if !follow {
14+
xlist, xget = xattr.LList, xattr.LGet
15+
}
16+
attrs, err := xlist(path)
1317
if err != nil {
1418
return nil, err
1519
}
1620
var hashes []encoding.NamedHash
1721
for _, attr := range attrs {
18-
val, err := xattr.LGet(path, attr)
22+
val, err := xget(path, attr)
1923
if err != nil {
2024
return nil, err
2125
}

sys_windows.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func getSys(fi os.FileInfo) (*Sys, error) {
1919
return nil, ErrNoStat
2020
}
2121

22-
func getXattr(_ string, _ Hash) ([]encoding.NamedHash, error) {
22+
func getXattr(_ string, _ Hash, _ bool) ([]encoding.NamedHash, error) {
2323
return nil, ErrNoXattr
2424
}
2525

0 commit comments

Comments
 (0)