func()

in internal/fs/fs.go [2039:2101]


func (fs *fileSystem) Rename(
	ctx context.Context,
	op *fuseops.RenameOp) (err error) {
	if fs.newConfig.FileSystem.IgnoreInterrupts {
		// When ignore interrupts config is set, we are creating a new context not
		// cancellable by parent context.
		var cancel context.CancelFunc
		ctx, cancel = util.IsolateContextFromParentContext(ctx)
		defer cancel()
	}
	// Find the old and new parents.
	fs.mu.Lock()
	oldParent := fs.dirInodeOrDie(op.OldParent)
	newParent := fs.dirInodeOrDie(op.NewParent)
	fs.mu.Unlock()

	if oldInode, ok := oldParent.(inode.BucketOwnedInode); !ok {
		// The old parent is not owned by any bucket, which means it's the base
		// directory that holds all the buckets' root directories. So, this op
		// is to rename a bucket, which is not supported.
		return fmt.Errorf("rename a bucket: %w", syscall.ENOTSUP)
	} else {
		// The target path must exist in the same bucket.
		oldBucket := oldInode.Bucket().Name()
		if newInode, ok := newParent.(inode.BucketOwnedInode); !ok || oldBucket != newInode.Bucket().Name() {
			return fmt.Errorf("move out of bucket %q: %w", oldBucket, syscall.ENOTSUP)
		}
	}

	child, err := fs.lookUpOrCreateChildInode(ctx, oldParent, op.OldName)
	if err != nil {
		return err
	}
	if child == nil {
		return fuse.ENOENT
	}
	child.DecrementLookupCount(1)
	child.Unlock()

	childBktOwned, ok := child.(inode.BucketOwnedInode)
	if !ok { // Won't happen in ideal case.
		return fmt.Errorf("child inode (id %v) is not owned by any bucket", child.ID())
	}

	if child.Name().IsDir() {
		// If 'enable-hns' flag is false, the bucket type is set to 'NonHierarchical' even for HNS buckets because the control client is nil.
		// Therefore, an additional 'enable hns' check is not required here.
		if childBktOwned.Bucket().BucketType().Hierarchical {
			return fs.renameHierarchicalDir(ctx, oldParent, op.OldName, newParent, op.NewName)
		}
		return fs.renameNonHierarchicalDir(ctx, oldParent, op.OldName, newParent, op.NewName)
	}
	childFileInode, ok := child.(*inode.FileInode)
	if !ok {
		return fmt.Errorf("child inode (id %v) is neither file nor directory inode", child.ID())
	}
	// TODO(b/402335988): Fix rename flow for local files when streaming writes is disabled.
	// If object to be renamed is a local file inode and streaming writes are disabled, rename operation is not supported.
	if childFileInode.IsLocal() && !fs.newConfig.Write.EnableStreamingWrites {
		return fmt.Errorf("cannot rename open file %q: %w", op.OldName, syscall.ENOTSUP)
	}
	return fs.renameFile(ctx, op, childFileInode, oldParent, newParent)
}