1
0
mirror of https://github.com/rclone/rclone.git synced 2026-01-04 17:43:50 +00:00

Compare commits

...

2 Commits

Author SHA1 Message Date
Nick Craig-Wood
4d97a6d2c1 local: when overwriting a symlink with a file delete the link first
If the destination file was a symlink, rclone would update the pointed
to file instead of replacing the symlink with a file.

rsync replaces files with symlinks and symlinks with files silently so
rclone should do the same.

Fixes #3400
2020-09-08 15:35:36 +01:00
Nick Craig-Wood
e4a7686444 accounting: remove new line from end of --stats-one-line display 2020-09-08 15:03:23 +01:00
2 changed files with 16 additions and 5 deletions

View File

@@ -990,7 +990,7 @@ func (o *Object) openTranslatedLink(offset, limit int64) (lrc io.ReadCloser, err
// Read the link and return the destination it as the contents of the object // Read the link and return the destination it as the contents of the object
linkdst, err := os.Readlink(o.path) linkdst, err := os.Readlink(o.path)
if err != nil { if err != nil {
return nil, err return nil, errors.Wrap(err, "read link")
} }
return readers.NewLimitedReadCloser(ioutil.NopCloser(strings.NewReader(linkdst[offset:])), limit), nil return readers.NewLimitedReadCloser(ioutil.NopCloser(strings.NewReader(linkdst[offset:])), limit), nil
} }
@@ -1033,7 +1033,7 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (in io.Read
fd, err := file.Open(o.path) fd, err := file.Open(o.path)
if err != nil { if err != nil {
return return nil, errors.Wrap(err, "Open")
} }
wrappedFd := readers.NewLimitedReadCloser(newFadviseReadCloser(o, fd, offset, limit), limit) wrappedFd := readers.NewLimitedReadCloser(newFadviseReadCloser(o, fd, offset, limit), limit)
if offset != 0 { if offset != 0 {
@@ -1098,6 +1098,15 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
// If it is a translated link, just read in the contents, and // If it is a translated link, just read in the contents, and
// then create a symlink // then create a symlink
if !o.translatedLink { if !o.translatedLink {
fi, err := os.Lstat(o.path)
// if object is currently a symlink remove it
if err == nil && fi.Mode()&os.ModeSymlink != 0 {
fs.Debugf(o, "Deleting as is symlink before updating as file")
err = os.Remove(o.path)
if err != nil {
fs.Debugf(o, "Failed to removing symlink: %v", err)
}
}
f, err := file.OpenFile(o.path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) f, err := file.OpenFile(o.path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)
if err != nil { if err != nil {
if runtime.GOOS == "windows" && os.IsPermission(err) { if runtime.GOOS == "windows" && os.IsPermission(err) {
@@ -1106,10 +1115,10 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op
// See: https://stackoverflow.com/questions/13215716/ioerror-errno-13-permission-denied-when-trying-to-open-hidden-file-in-w-mod // See: https://stackoverflow.com/questions/13215716/ioerror-errno-13-permission-denied-when-trying-to-open-hidden-file-in-w-mod
f, err = file.OpenFile(o.path, os.O_WRONLY|os.O_TRUNC, 0666) f, err = file.OpenFile(o.path, os.O_WRONLY|os.O_TRUNC, 0666)
if err != nil { if err != nil {
return err return errors.Wrap(err, "Update Windows")
} }
} else { } else {
return err return errors.Wrap(err, "Update")
} }
} }
// Pre-allocate the file for performance reasons // Pre-allocate the file for performance reasons

View File

@@ -272,7 +272,7 @@ func (s *StatsInfo) String() string {
} }
} }
_, _ = fmt.Fprintf(buf, "%s%10s / %s, %s, %s, ETA %s%s\n", _, _ = fmt.Fprintf(buf, "%s%10s / %s, %s, %s, ETA %s%s",
dateString, dateString,
fs.SizeSuffix(s.bytes), fs.SizeSuffix(s.bytes),
fs.SizeSuffix(totalSize).Unit("Bytes"), fs.SizeSuffix(totalSize).Unit("Bytes"),
@@ -283,6 +283,7 @@ func (s *StatsInfo) String() string {
) )
if !fs.Config.StatsOneLine { if !fs.Config.StatsOneLine {
_, _ = buf.WriteRune('\n')
errorDetails := "" errorDetails := ""
switch { switch {
case s.fatalError: case s.fatalError:
@@ -291,6 +292,7 @@ func (s *StatsInfo) String() string {
errorDetails = " (retrying may help)" errorDetails = " (retrying may help)"
case s.errors != 0: case s.errors != 0:
errorDetails = " (no need to retry)" errorDetails = " (no need to retry)"
} }
// Add only non zero stats // Add only non zero stats