Repository: rclone/rclone
File: fs/operations/copy.go (Go)

Code before:
		return truncated
	}
	for len(truncated) > 0 {
		if utf8.ValidString(truncated) {
			return truncated
		}
		// Remove 1 byte until valid
		truncated = truncated[:len(truncated)-1]
	}
	return truncated
}

// Check to see if we should be using a partial name and return the name for the copy and the inplace flag
func (c *copy) checkPartial() (remoteForCopy string, inplace bool, err error) {
	remoteForCopy = c.remote
	if c.ci.Inplace || c.dstFeatures.Move == nil || !c.dstFeatures.PartialUploads || strings.HasSuffix(c.remote, ".rclonelink") {
		return remoteForCopy, true, nil
	}
	if len(c.ci.PartialSuffix) > 16 {
		return remoteForCopy, true, fmt.Errorf("expecting length of --partial-suffix to be not greater than %d but got %d", 16, len(c.ci.PartialSuffix))
	}
	// Avoid making the leaf name longer if it's already lengthy to avoid
	// trouble with file name length limits.

	// generate a stable random suffix: use the significant bytes of the hashed remote
	hashBytes := sha256.Sum256([]byte(c.remote))
	hashString := hex.EncodeToString(hashBytes[0:4])

	suffix := "." + hashString + c.ci.PartialSuffix
	base := path.Base(remoteForCopy)
	if len(base) > 100 {
		remoteForCopy = TruncateString(remoteForCopy, len(remoteForCopy)-len(suffix)) + suffix
	} else {
		remoteForCopy += suffix
	}
	return remoteForCopy, false, nil
}

// Check to see if we have hit max transfer limits
func (c *copy) checkLimits(ctx context.Context) (err error) {
	if c.ci.MaxTransfer < 0 {
		return nil
	}
	var bytesSoFar int64
	if c.ci.CutoffMode == fs.CutoffModeCautious {
		bytesSoFar = accounting.Stats(ctx).GetBytesWithPending() + c.src.Size()
	} else {
		bytesSoFar = accounting.Stats(ctx).GetBytes()
	}
	if bytesSoFar >= int64(c.ci.MaxTransfer) {
		if c.ci.CutoffMode == fs.CutoffModeHard {

Review comment (suggestion):
Making the suffix depend on the remote name will make it identical for all users. This means that if A and B are uploading at the same time then the resultant file won't be either A or B but a corrupted mix of both.

You could use `fs.Fingerprint(ctx, c.src, true)` to create a string which depends on the source in a reasonably robust fashion. I'm not sure this will solve your problem though.

Code after:
	}
	for len(truncated) > 0 {
		if utf8.ValidString(truncated) {
			return truncated
		}
		// Remove 1 byte until valid
		truncated = truncated[:len(truncated)-1]
	}
	return truncated
}

// Check to see if we should be using a partial name and return the name for the copy and the inplace flag
func (c *copy) checkPartial() (remoteForCopy string, inplace bool, err error) {
	remoteForCopy = c.remote
	if c.ci.Inplace || c.dstFeatures.Move == nil || !c.dstFeatures.PartialUploads || strings.HasSuffix(c.remote, ".rclonelink") {
		return remoteForCopy, true, nil
	}
	if len(c.ci.PartialSuffix) > 16 {
		return remoteForCopy, true, fmt.Errorf("expecting length of --partial-suffix to be not greater than %d but got %d", 16, len(c.ci.PartialSuffix))
	}
	// Avoid making the leaf name longer if it's already lengthy to avoid
	// trouble with file name length limits.
	suffix := "." + random.String(8) + c.ci.PartialSuffix
	base := path.Base(remoteForCopy)
	if len(base) > 100 {
		remoteForCopy = TruncateString(remoteForCopy, len(remoteForCopy)-len(suffix)) + suffix
	} else {
		remoteForCopy += suffix
	}
	return remoteForCopy, false, nil
}

// Check to see if we have hit max transfer limits
func (c *copy) checkLimits(ctx context.Context) (err error) {
	if c.ci.MaxTransfer < 0 {
		return nil
	}
	var bytesSoFar int64
	if c.ci.CutoffMode == fs.CutoffModeCautious {
		bytesSoFar = accounting.Stats(ctx).GetBytesWithPending() + c.src.Size()
	} else {
		bytesSoFar = accounting.Stats(ctx).GetBytes()
	}
	if bytesSoFar >= int64(c.ci.MaxTransfer) {
		if c.ci.CutoffMode == fs.CutoffModeHard {
			return accounting.ErrorMaxTransferLimitReachedFatal
		}
		return accounting.ErrorMaxTransferLimitReachedGraceful
	}
	return nil
}