mirror of
https://github.com/strongdm/comply
synced 2024-11-05 07:25:26 +00:00
80 lines
1.9 KiB
Go
80 lines
1.9 KiB
Go
package github
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
)
|
|
|
|
func GetFileSize(f *os.File) (int64, error) {
|
|
/* first try stat */
|
|
off, err := fsizeStat(f)
|
|
if err != nil {
|
|
/* if that fails, try seek */
|
|
return fsizeSeek(f)
|
|
}
|
|
|
|
return off, nil
|
|
}
|
|
|
|
func fsizeStat(f *os.File) (int64, error) {
|
|
fi, err := f.Stat()
|
|
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return fi.Size(), nil
|
|
}
|
|
|
|
func fsizeSeek(f *os.File) (int64, error) {
|
|
off, err := f.Seek(0, 2)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("seeking did not work, stdin is not" +
|
|
"supported yet because github doesn't support chunking" +
|
|
"requests (and I haven't implemented detecting stdin and" +
|
|
"buffering yet")
|
|
}
|
|
|
|
_, err = f.Seek(0, 0)
|
|
if err != nil {
|
|
return 0, fmt.Errorf("could not seek back in the file")
|
|
}
|
|
return off, nil
|
|
}
|
|
|
|
// materializeFile takes a physical file or stream (named pipe, user input,
|
|
// ...) and returns an io.Reader and the number of bytes that can be read
|
|
// from it.
|
|
func materializeFile(f *os.File) (io.Reader, int64, error) {
|
|
fi, err := f.Stat()
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
// If the file is actually a char device (like user typed input)
|
|
// or a named pipe (like a streamed in file), buffer it up.
|
|
//
|
|
// When uploading a file, you need to either explicitly set the
|
|
// Content-Length header or send a chunked request. Since the
|
|
// github upload server doesn't accept chunked encoding, we have
|
|
// to set the size of the file manually. Since a stream doesn't have a
|
|
// predefined length, it's read entirely into a byte buffer.
|
|
if fi.Mode()&(os.ModeCharDevice|os.ModeNamedPipe) == 1 {
|
|
vprintln("input was a stream, buffering up")
|
|
|
|
var buf bytes.Buffer
|
|
n, err := buf.ReadFrom(f)
|
|
if err != nil {
|
|
return nil, 0, errors.New("req: could not buffer up input stream: " + err.Error())
|
|
}
|
|
return &buf, n, err
|
|
}
|
|
|
|
// We know the os.File is most likely an actual file now.
|
|
n, err := GetFileSize(f)
|
|
return f, n, err
|
|
}
|