github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/syz-cluster/pkg/blob/gcs.go (about)

     1  // Copyright 2025 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  package blob
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"io"
    10  	"path"
    11  	"regexp"
    12  
    13  	"github.com/google/syzkaller/pkg/gcs"
    14  )
    15  
    16  type gcsDriver struct {
    17  	bucket string
    18  	client gcs.Client
    19  }
    20  
    21  func NewGCSClient(ctx context.Context, bucket string) (Storage, error) {
    22  	client, err := gcs.NewClient(ctx)
    23  	if err != nil {
    24  		return nil, err
    25  	}
    26  	return &gcsDriver{
    27  		bucket: bucket,
    28  		client: client,
    29  	}, nil
    30  }
    31  
    32  func (gcs *gcsDriver) Write(source io.Reader, parts ...string) (string, error) {
    33  	if len(parts) == 0 {
    34  		return "", fmt.Errorf("no identifiers for the object were passed to Write")
    35  	}
    36  	object := path.Join(gcs.bucket, path.Join(parts...))
    37  	w, err := gcs.client.FileWriter(object, "", "")
    38  	if err != nil {
    39  		return "", err
    40  	}
    41  	defer w.Close()
    42  	_, err = io.Copy(w, source)
    43  	if err != nil {
    44  		return "", err
    45  	}
    46  	return "gcs://" + object, nil
    47  }
    48  
    49  func (gcs *gcsDriver) Read(uri string) (io.ReadCloser, error) {
    50  	bucket, object, err := gcs.parseURI(uri)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  	return gcs.client.FileReader(path.Join(bucket, object))
    55  }
    56  
    57  var gcsObjectRe = regexp.MustCompile(`^gcs://([\w-]+)/(.+)$`)
    58  
    59  func (gcs *gcsDriver) parseURI(uri string) (string, string, error) {
    60  	match := gcsObjectRe.FindStringSubmatch(uri)
    61  	if len(match) == 0 {
    62  		return "", "", fmt.Errorf("invalid GCS URI")
    63  	} else if match[1] != gcs.bucket {
    64  		return "", "", fmt.Errorf("unexpected GCS bucket")
    65  	}
    66  	return gcs.bucket, match[2], nil
    67  }