(dir, base string, action onConflict)
| 647 | } |
| 648 | |
| 649 | func openFileOrSubstitute(dir, base string, action onConflict) (*os.File, error) { |
| 650 | targetFile := filepath.Join(dir, base) |
| 651 | f, err := os.OpenFile(targetFile, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0644) |
| 652 | if err == nil { |
| 653 | return f, nil |
| 654 | } |
| 655 | // Something went wrong trying to open targetFile as a new file for writing. |
| 656 | switch action { |
| 657 | default: |
| 658 | // This should not happen. |
| 659 | return nil, fmt.Errorf("file issue. how to resolve this conflict? no one knows.") |
| 660 | case skipOnExist: |
| 661 | if _, statErr := os.Stat(targetFile); statErr == nil { |
| 662 | // we can stat a file at that path: so it already exists. |
| 663 | return nil, fmt.Errorf("refusing to overwrite file: %w", err) |
| 664 | } |
| 665 | return nil, fmt.Errorf("failed to write; %w", err) |
| 666 | case overwriteExisting: |
| 667 | // remove the target file and create it anew so we don't fall for an |
| 668 | // attacker who symlinks a known target name to a file he wants changed. |
| 669 | if err = os.Remove(targetFile); err != nil { |
| 670 | return nil, fmt.Errorf("unable to remove target file: %w", err) |
| 671 | } |
| 672 | if f, err = os.OpenFile(targetFile, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0644); err != nil { |
| 673 | return nil, fmt.Errorf("unable to overwrite: %w", err) |
| 674 | } |
| 675 | return f, nil |
| 676 | case createNumberedFiles: |
| 677 | // It's possible the target directory or filesystem isn't writable by us, |
| 678 | // not just that the target file(s) already exists. For now, give up after |
| 679 | // a limited number of attempts. In future, maybe distinguish this case |
| 680 | // and follow in the style of https://tinyurl.com/chromium100 |
| 681 | maxAttempts := 100 |
| 682 | for i := 1; i < maxAttempts; i++ { |
| 683 | if f, err = os.OpenFile(numberedFileName(dir, base, i), os.O_RDWR|os.O_CREATE|os.O_EXCL, 0644); err == nil { |
| 684 | return f, nil |
| 685 | } |
| 686 | } |
| 687 | return nil, fmt.Errorf("unable to find a name for writing %v, final attempt: %w", targetFile, err) |
| 688 | } |
| 689 | } |
| 690 | |
| 691 | func receiveFile(ctx context.Context, wf apitype.WaitingFile, dir string) (targetFile string, size int64, err error) { |
| 692 | rc, size, err := localClient.GetWaitingFile(ctx, wf.Name) |
no test coverage detected
searching dependent graphs…