Skip to content

Commit

Permalink
fix: failure on broken symlink deletion
Browse files Browse the repository at this point in the history
  • Loading branch information
o1egl committed Jul 26, 2021
1 parent 34d7d2c commit 8650d2f
Showing 1 changed file with 63 additions and 13 deletions.
76 changes: 63 additions & 13 deletions files/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type FileInfo struct {
ModTime time.Time `json:"modified"`
Mode os.FileMode `json:"mode"`
IsDir bool `json:"isDir"`
IsSymlink bool `json:"isSymlink"`
Type string `json:"type"`
Subtitles []string `json:"subtitles,omitempty"`
Content string `json:"content,omitempty"`
Expand Down Expand Up @@ -61,23 +62,11 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) {
return nil, os.ErrPermission
}

info, err := opts.Fs.Stat(opts.Path)
file, err := stat(opts)
if err != nil {
return nil, err
}

file := &FileInfo{
Fs: opts.Fs,
Path: opts.Path,
Name: info.Name(),
ModTime: info.ModTime(),
Mode: info.Mode(),
IsDir: info.IsDir(),
Size: info.Size(),
Extension: filepath.Ext(info.Name()),
Token: opts.Token,
}

if opts.Expand {
if file.IsDir {
if err := file.readListing(opts.Checker, opts.ReadHeader); err != nil { //nolint:govet
Expand All @@ -95,6 +84,64 @@ func NewFileInfo(opts FileOptions) (*FileInfo, error) {
return file, err
}

func stat(opts FileOptions) (*FileInfo, error) {
var file *FileInfo

if lstaterFs, ok := opts.Fs.(afero.Lstater); ok {
info, _, err := lstaterFs.LstatIfPossible(opts.Path)
if err != nil {
return nil, err
}
file = &FileInfo{
Fs: opts.Fs,
Path: opts.Path,
Name: info.Name(),
ModTime: info.ModTime(),
Mode: info.Mode(),
IsDir: info.IsDir(),
IsSymlink: IsSymlink(info.Mode()),
Size: info.Size(),
Extension: filepath.Ext(info.Name()),
Token: opts.Token,
}
}

// regular file
if file != nil && !file.IsSymlink {
return file, nil
}

// fs doesn't support afero.Lstater interface or the file is a symlink
info, err := opts.Fs.Stat(opts.Path)
if err != nil {
// can't follow symlink
if file != nil && file.IsSymlink {
return file, nil
}
return nil, err
}

// set correct file size in case of symlink
if file != nil && file.IsSymlink {
file.Size = info.Size()
return file, nil
}

file = &FileInfo{
Fs: opts.Fs,
Path: opts.Path,
Name: info.Name(),
ModTime: info.ModTime(),
Mode: info.Mode(),
IsDir: info.IsDir(),
Size: info.Size(),
Extension: filepath.Ext(info.Name()),
Token: opts.Token,
}

return file, nil
}

// Checksum checksums a given File for a given User, using a specific
// algorithm. The checksums data is saved on File object.
func (i *FileInfo) Checksum(algo string) error {
Expand Down Expand Up @@ -252,7 +299,9 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error {
continue
}

isSymlink := false
if IsSymlink(f.Mode()) {
isSymlink = true
// It's a symbolic link. We try to follow it. If it doesn't work,
// we stay with the link information instead of the target's.
info, err := i.Fs.Stat(fPath)
Expand All @@ -268,6 +317,7 @@ func (i *FileInfo) readListing(checker rules.Checker, readHeader bool) error {
ModTime: f.ModTime(),
Mode: f.Mode(),
IsDir: f.IsDir(),
IsSymlink: isSymlink,
Extension: filepath.Ext(name),
Path: fPath,
}
Expand Down

0 comments on commit 8650d2f

Please sign in to comment.