// Copyright 2025 The BoringSSL Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //go:build gcs package main import ( "context" "flag" "io" "log" neturl "net/url" "time" "cloud.google.com/go/storage" "google.golang.org/api/iterator" ) var uploadGCSDirectory = flag.String("gcs", "", "GCS path to folder where result files to be uploaded are") // Uploads results directory from GCS. // Similar to uploadResultsDirectory(). func uploadResultsFromGCS(gcsBucket string, config *Config, sessionTokensCacheDir string) { u, err := neturl.Parse(gcsBucket) if err != nil { log.Fatal(err) } bucket := u.Host folder := trimLeadingSlash(addTrailingSlash(u.Path)) sessionID, err := getLastDigitDir(folder) if err != nil { log.Fatal(err) } ctx := context.Background() client, err := storage.NewClient(ctx) if err != nil { log.Fatalf("Failed to create client: %v", err) } defer client.Close() ctx, cancel := context.WithTimeout(ctx, time.Second*10) defer cancel() // Access bucket and identify all objects. // Objects include the folder. it := client.Bucket(bucket).Objects(ctx, &storage.Query{ Prefix: folder, Delimiter: "/", }) var results []nistUploadResult // Go through each object (noting GCS stores objects, not files) for { attrs, err := it.Next() if err == iterator.Done { break } else if err != nil { log.Fatalf("Unable to read bucket: %s", err) } rc, err := client.Bucket(bucket).Object(attrs.Name).NewReader(ctx) if err != nil { log.Fatalf("unable to open object from bucket %q, object %q: %v", bucket, attrs.Name, err) return } defer rc.Close() content, err := io.ReadAll(rc) if err != nil { log.Fatalf("unable to read contents of object %q: %v", attrs.Name, err) } if len(content) == 0 { log.Printf("object (gs://%s/%s) is a \"folder\" or empty.", bucket, attrs.Name) continue } results = processResultContent(results, content, sessionID, attrs.Name) } uploadResults(results, sessionID, config, sessionTokensCacheDir) } func handleGCSFlag(config *Config, sessionTokensCacheDir string) bool { if len(*uploadGCSDirectory) > 0 { uploadResultsFromGCS(*uploadGCSDirectory, config, sessionTokensCacheDir) return true } return false }