I was going over the source code of azcopy and I cannot figure out how the “os.Stdin” part of the below code is working. Is anyone kind enough to explain?
func (cca *cookedCopyCmdArgs) processRedirectionUpload(blobResource common.ResourceString, blockSize int64) error {
ctx := context.WithValue(context.TODO(), ste.ServiceAPIVersionOverride, ste.DefaultServiceApiVersion)
// if no block size is set, then use default value
if blockSize == 0 {
blockSize = pipingDefaultBlockSize
}
// step 0: initialize pipeline
p, err := createBlobPipeline(ctx, common.CredentialInfo{CredentialType: common.ECredentialType.Anonymous()})
if err != nil {
return err
}
// step 1: parse destination url
u, err := blobResource.FullURL()
if err != nil {
return fmt.Errorf("fatal: cannot parse destination blob URL due to error: %s", err.Error())
}
// step 2: leverage high-level call in Blob SDK to upload stdin in parallel
blockBlobUrl := azblob.NewBlockBlobURL(*u, p)
_, err = azblob.UploadStreamToBlockBlob(ctx, os.Stdin, blockBlobUrl, azblob.UploadStreamToBlockBlobOptions{
BufferSize: int(blockSize),
MaxBuffers: pipingUploadParallelism,
})
return err
}
@ncw
Nick, thank you for your answer. Seems that my question was too ambiguous. I have used azblob.UploadStreamToBlockBlob function myself, what I do not understand is how are the data bytes from the file sent to the Stdin pipe to be picked up by the function.
Example azcopy copy "C:\somefile.txt" "https://account.blob.core.windows.net/mycontainer
processRedirectionUpload is a wrapper for UploadStreamToBlockBlob. Why do you expect your example to execute processRedirectionUpload? You offer no proof that it does. For your example, is cca.isRedirection()true?
Good point It was the only implementation of azblob.Upload that I could find, but they could use bloburl methods (I am remotely now and cannot check).
But the question remains, how could someone get byte data from a file into the stdin? Or does it need to be piped in the command line?
$ cat stdin.go
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
s := bufio.NewScanner(os.Stdin)
for s.Scan() {
b := s.Bytes()
fmt.Println(string(b))
}
if err := s.Err(); err != nil {
fmt.Println(err)
}
}
$ cat stdin.file
This is data from a file.
.
$ go build stdin.go
$ ./stdin < stdin.file
This is data from a file.
$ cat stdin.file | ./stdin
This is data from a file.