podman
197 строк · 4.9 Кб
1package gpgme2
3// #include <string.h>
4// #include <gpgme.h>
5// #include <errno.h>
6// #include "go_gpgme.h"
7import "C"8
9import (10"io"11"os"12"runtime"13"unsafe"14)
15
16const (17SeekSet = C.SEEK_SET18SeekCur = C.SEEK_CUR19SeekEnd = C.SEEK_END20)
21
22//export gogpgme_readfunc
23func gogpgme_readfunc(handle, buffer unsafe.Pointer, size C.size_t) C.ssize_t {24d := callbackLookup(uintptr(handle)).(*Data)25if len(d.buf) < int(size) {26d.buf = make([]byte, size)27}28n, err := d.r.Read(d.buf[:size])29if err != nil && err != io.EOF {30C.gpgme_err_set_errno(C.EIO)31return -132}33C.memcpy(buffer, unsafe.Pointer(&d.buf[0]), C.size_t(n))34return C.ssize_t(n)35}
36
37//export gogpgme_writefunc
38func gogpgme_writefunc(handle, buffer unsafe.Pointer, size C.size_t) C.ssize_t {39d := callbackLookup(uintptr(handle)).(*Data)40if len(d.buf) < int(size) {41d.buf = make([]byte, size)42}43C.memcpy(unsafe.Pointer(&d.buf[0]), buffer, C.size_t(size))44n, err := d.w.Write(d.buf[:size])45if err != nil && err != io.EOF {46C.gpgme_err_set_errno(C.EIO)47return -148}49return C.ssize_t(n)50}
51
52//export gogpgme_seekfunc
53func gogpgme_seekfunc(handle unsafe.Pointer, offset C.gpgme_off_t, whence C.int) C.gpgme_off_t {54d := callbackLookup(uintptr(handle)).(*Data)55n, err := d.s.Seek(int64(offset), int(whence))56if err != nil {57C.gpgme_err_set_errno(C.EIO)58return -159}60return C.gpgme_off_t(n)61}
62
63// The Data buffer used to communicate with GPGME
64type Data struct {65dh C.gpgme_data_t // WARNING: Call runtime.KeepAlive(d) after ANY passing of d.dh to C66buf []byte67cbs C.struct_gpgme_data_cbs68r io.Reader69w io.Writer70s io.Seeker71cbc uintptr // WARNING: Call runtime.KeepAlive(d) after ANY use of d.cbc in C (typically via d.dh)72}
73
74func newData() *Data {75d := &Data{}76runtime.SetFinalizer(d, (*Data).Close)77return d78}
79
80// NewData returns a new memory based data buffer
81func NewData() (*Data, error) {82d := newData()83return d, handleError(C.gpgme_data_new(&d.dh))84}
85
86// NewDataFile returns a new file based data buffer
87func NewDataFile(f *os.File) (*Data, error) {88d := newData()89return d, handleError(C.gpgme_data_new_from_fd(&d.dh, C.int(f.Fd())))90}
91
92// NewDataBytes returns a new memory based data buffer that contains `b` bytes
93func NewDataBytes(b []byte) (*Data, error) {94d := newData()95var cb *C.char96if len(b) != 0 {97cb = (*C.char)(unsafe.Pointer(&b[0]))98}99return d, handleError(C.gpgme_data_new_from_mem(&d.dh, cb, C.size_t(len(b)), 1))100}
101
102// NewDataReader returns a new callback based data buffer
103func NewDataReader(r io.Reader) (*Data, error) {104d := newData()105d.r = r106d.cbs.read = C.gpgme_data_read_cb_t(C.gogpgme_readfunc)107cbc := callbackAdd(d)108d.cbc = cbc109return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc)))110}
111
112// NewDataWriter returns a new callback based data buffer
113func NewDataWriter(w io.Writer) (*Data, error) {114d := newData()115d.w = w116d.cbs.write = C.gpgme_data_write_cb_t(C.gogpgme_writefunc)117cbc := callbackAdd(d)118d.cbc = cbc119return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc)))120}
121
122// NewDataReadWriter returns a new callback based data buffer
123func NewDataReadWriter(rw io.ReadWriter) (*Data, error) {124d := newData()125d.r = rw126d.w = rw127d.cbs.read = C.gpgme_data_read_cb_t(C.gogpgme_readfunc)128d.cbs.write = C.gpgme_data_write_cb_t(C.gogpgme_writefunc)129cbc := callbackAdd(d)130d.cbc = cbc131return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc)))132}
133
134// NewDataReadWriteSeeker returns a new callback based data buffer
135func NewDataReadWriteSeeker(rw io.ReadWriteSeeker) (*Data, error) {136d := newData()137d.r = rw138d.w = rw139d.s = rw140d.cbs.read = C.gpgme_data_read_cb_t(C.gogpgme_readfunc)141d.cbs.write = C.gpgme_data_write_cb_t(C.gogpgme_writefunc)142d.cbs.seek = C.gpgme_data_seek_cb_t(C.gogpgme_seekfunc)143cbc := callbackAdd(d)144d.cbc = cbc145return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc)))146}
147
148// Close releases any resources associated with the data buffer
149func (d *Data) Close() error {150if d.dh == nil {151return nil152}153if d.cbc > 0 {154callbackDelete(d.cbc)155}156_, err := C.gpgme_data_release(d.dh)157runtime.KeepAlive(d)158d.dh = nil159return err160}
161
162func (d *Data) Write(p []byte) (int, error) {163n, err := C.gpgme_data_write(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))164runtime.KeepAlive(d)165if err != nil {166return 0, err167}168if n == 0 {169return 0, io.EOF170}171return int(n), nil172}
173
174func (d *Data) Read(p []byte) (int, error) {175n, err := C.gpgme_data_read(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))176runtime.KeepAlive(d)177if err != nil {178return 0, err179}180if n == 0 {181return 0, io.EOF182}183return int(n), nil184}
185
186func (d *Data) Seek(offset int64, whence int) (int64, error) {187n, err := C.gogpgme_data_seek(d.dh, C.gpgme_off_t(offset), C.int(whence))188runtime.KeepAlive(d)189return int64(n), err190}
191
192// Name returns the associated filename if any
193func (d *Data) Name() string {194res := C.GoString(C.gpgme_data_get_file_name(d.dh))195runtime.KeepAlive(d)196return res197}
198