MCPcopy
hub / github.com/syncthing/syncthing / handleSymlink

Method handleSymlink

lib/model/folder_sendrecv.go:715–773  ·  view source on GitHub ↗

handleSymlink creates or updates the given symlink

(file protocol.FileInfo, dbUpdateChan chan<- dbUpdateJob, scanChan chan<- string)

Source from the content-addressed store, hash-verified

713
714// handleSymlink creates or updates the given symlink
715func (f *sendReceiveFolder) handleSymlink(file protocol.FileInfo, dbUpdateChan chan<- dbUpdateJob, scanChan chan<- string) {
716 // Used in the defer closure below, updated by the function body. Take
717 // care not declare another err.
718 var err error
719
720 f.evLogger.Log(events.ItemStarted, map[string]string{
721 "folder": f.folderID,
722 "item": file.Name,
723 "type": "symlink",
724 "action": "update",
725 })
726
727 defer func() {
728 if err != nil {
729 slog.Warn("Failed to handle symlink", f.LogAttr(), file.LogAttr(), slogutil.Error(err))
730 } else {
731 slog.Info("Created or updated symlink", f.LogAttr(), file.LogAttr())
732 }
733 f.evLogger.Log(events.ItemFinished, map[string]interface{}{
734 "folder": f.folderID,
735 "item": file.Name,
736 "error": events.Error(err),
737 "type": "symlink",
738 "action": "update",
739 })
740 }()
741
742 f.sl.Debug("Need symlink", slogutil.FilePath(file.Name), slog.Any("cur", slogutil.Expensive(func() any {
743 curFile, _, _ := f.model.sdb.GetDeviceFile(f.folderID, protocol.LocalDeviceID, file.Name)
744 return curFile
745 })))
746
747 if len(file.SymlinkTarget) == 0 {
748 // Index entry from a Syncthing predating the support for including
749 // the link target in the index entry. We log this as an error.
750 f.newPullError(file.Name, errIncompatibleSymlink)
751 return
752 }
753
754 if err = f.handleSymlinkCheckExisting(file, scanChan); err != nil {
755 f.newPullError(file.Name, fmt.Errorf("handling symlink: %w", err))
756 return
757 }
758
759 // We declare a function that acts on only the path name, so
760 // we can pass it to InWritableDir.
761 createLink := func(path string) error {
762 if err := f.mtimefs.CreateSymlink(string(file.SymlinkTarget), path); err != nil {
763 return err
764 }
765 return f.setPlatformData(&file, path)
766 }
767
768 if err = f.inWritableDir(createLink, file.Name); err == nil {
769 dbUpdateChan <- dbUpdateJob{file, dbUpdateHandleSymlink}
770 } else {
771 f.newPullError(file.Name, fmt.Errorf("symlink create: %w", err))
772 }

Callers 4

processNeededMethod · 0.95
TestCopyOwnerFunction · 0.80

Calls 12

newPullErrorMethod · 0.95
setPlatformDataMethod · 0.95
inWritableDirMethod · 0.95
ErrorFunction · 0.92
ErrorFunction · 0.92
FilePathFunction · 0.92
ExpensiveFunction · 0.92
LogMethod · 0.65
GetDeviceFileMethod · 0.65
CreateSymlinkMethod · 0.65
LogAttrMethod · 0.45

Tested by 3

TestCopyOwnerFunction · 0.64