spf13 / afero

A FileSystem Abstraction System for Go
Apache License 2.0
5.79k stars 498 forks source link

GcsFs: incorrect handling of OpenFile of flags #423

Open meandnano opened 2 months ago

meandnano commented 2 months ago

First, thanks for the great product!

Second, a bug report: In the occasion of "overwriting file" with GCS FS using afero.WriteFile (or fs.OpenFile), the way in which flags are processed seems to be incorrect.

afero.WriteFile calls fs.OpenFile with flags being os.O_WRONLY|os.O_CREATE|os.O_TRUNC which works like a charm for creating new files or truncating existing ones with local FS. However, with GCS FS, when the file does not exist, such call fails with storage: object doesn't exist.

Example code:

package main

import (
    "context"
    "fmt"
    "github.com/spf13/afero"
    "github.com/spf13/afero/gcsfs"
    "os"
)

func main() {
    filename := "mybucket/myfile.txt" // bucket exists, but not the file
    fs, err := gcsfs.NewGcsFS(context.Background())
    if err != nil {
        panic(err)
    }

    if err := afero.WriteFile(fs, filename, []byte("Hello"), os.ModePerm); err != nil {
        fmt.Printf("%s\n", err) // will print "storage: object doesn't exist"
    }
}

Looking at the gcsfs/fs.go it's clear that os.O_TRUNC tries to delete non-existent file without checking for os.O_CREATE flag to be present.

I'm capable of providing a PR with the solution to the issue, but just wanted to make sure this is not something already being addressed or was considered an expected behaviour.