podman

Форк
0
197 строк · 4.9 Кб
1
package gpgme
2

3
// #include <string.h>
4
// #include <gpgme.h>
5
// #include <errno.h>
6
// #include "go_gpgme.h"
7
import "C"
8

9
import (
10
	"io"
11
	"os"
12
	"runtime"
13
	"unsafe"
14
)
15

16
const (
17
	SeekSet = C.SEEK_SET
18
	SeekCur = C.SEEK_CUR
19
	SeekEnd = C.SEEK_END
20
)
21

22
//export gogpgme_readfunc
23
func gogpgme_readfunc(handle, buffer unsafe.Pointer, size C.size_t) C.ssize_t {
24
	d := callbackLookup(uintptr(handle)).(*Data)
25
	if len(d.buf) < int(size) {
26
		d.buf = make([]byte, size)
27
	}
28
	n, err := d.r.Read(d.buf[:size])
29
	if err != nil && err != io.EOF {
30
		C.gpgme_err_set_errno(C.EIO)
31
		return -1
32
	}
33
	C.memcpy(buffer, unsafe.Pointer(&d.buf[0]), C.size_t(n))
34
	return C.ssize_t(n)
35
}
36

37
//export gogpgme_writefunc
38
func gogpgme_writefunc(handle, buffer unsafe.Pointer, size C.size_t) C.ssize_t {
39
	d := callbackLookup(uintptr(handle)).(*Data)
40
	if len(d.buf) < int(size) {
41
		d.buf = make([]byte, size)
42
	}
43
	C.memcpy(unsafe.Pointer(&d.buf[0]), buffer, C.size_t(size))
44
	n, err := d.w.Write(d.buf[:size])
45
	if err != nil && err != io.EOF {
46
		C.gpgme_err_set_errno(C.EIO)
47
		return -1
48
	}
49
	return C.ssize_t(n)
50
}
51

52
//export gogpgme_seekfunc
53
func gogpgme_seekfunc(handle unsafe.Pointer, offset C.gpgme_off_t, whence C.int) C.gpgme_off_t {
54
	d := callbackLookup(uintptr(handle)).(*Data)
55
	n, err := d.s.Seek(int64(offset), int(whence))
56
	if err != nil {
57
		C.gpgme_err_set_errno(C.EIO)
58
		return -1
59
	}
60
	return C.gpgme_off_t(n)
61
}
62

63
// The Data buffer used to communicate with GPGME
64
type Data struct {
65
	dh  C.gpgme_data_t // WARNING: Call runtime.KeepAlive(d) after ANY passing of d.dh to C
66
	buf []byte
67
	cbs C.struct_gpgme_data_cbs
68
	r   io.Reader
69
	w   io.Writer
70
	s   io.Seeker
71
	cbc uintptr // WARNING: Call runtime.KeepAlive(d) after ANY use of d.cbc in C (typically via d.dh)
72
}
73

74
func newData() *Data {
75
	d := &Data{}
76
	runtime.SetFinalizer(d, (*Data).Close)
77
	return d
78
}
79

80
// NewData returns a new memory based data buffer
81
func NewData() (*Data, error) {
82
	d := newData()
83
	return d, handleError(C.gpgme_data_new(&d.dh))
84
}
85

86
// NewDataFile returns a new file based data buffer
87
func NewDataFile(f *os.File) (*Data, error) {
88
	d := newData()
89
	return 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
93
func NewDataBytes(b []byte) (*Data, error) {
94
	d := newData()
95
	var cb *C.char
96
	if len(b) != 0 {
97
		cb = (*C.char)(unsafe.Pointer(&b[0]))
98
	}
99
	return 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
103
func NewDataReader(r io.Reader) (*Data, error) {
104
	d := newData()
105
	d.r = r
106
	d.cbs.read = C.gpgme_data_read_cb_t(C.gogpgme_readfunc)
107
	cbc := callbackAdd(d)
108
	d.cbc = cbc
109
	return 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
113
func NewDataWriter(w io.Writer) (*Data, error) {
114
	d := newData()
115
	d.w = w
116
	d.cbs.write = C.gpgme_data_write_cb_t(C.gogpgme_writefunc)
117
	cbc := callbackAdd(d)
118
	d.cbc = cbc
119
	return 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
123
func NewDataReadWriter(rw io.ReadWriter) (*Data, error) {
124
	d := newData()
125
	d.r = rw
126
	d.w = rw
127
	d.cbs.read = C.gpgme_data_read_cb_t(C.gogpgme_readfunc)
128
	d.cbs.write = C.gpgme_data_write_cb_t(C.gogpgme_writefunc)
129
	cbc := callbackAdd(d)
130
	d.cbc = cbc
131
	return 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
135
func NewDataReadWriteSeeker(rw io.ReadWriteSeeker) (*Data, error) {
136
	d := newData()
137
	d.r = rw
138
	d.w = rw
139
	d.s = rw
140
	d.cbs.read = C.gpgme_data_read_cb_t(C.gogpgme_readfunc)
141
	d.cbs.write = C.gpgme_data_write_cb_t(C.gogpgme_writefunc)
142
	d.cbs.seek = C.gpgme_data_seek_cb_t(C.gogpgme_seekfunc)
143
	cbc := callbackAdd(d)
144
	d.cbc = cbc
145
	return 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
149
func (d *Data) Close() error {
150
	if d.dh == nil {
151
		return nil
152
	}
153
	if d.cbc > 0 {
154
		callbackDelete(d.cbc)
155
	}
156
	_, err := C.gpgme_data_release(d.dh)
157
	runtime.KeepAlive(d)
158
	d.dh = nil
159
	return err
160
}
161

162
func (d *Data) Write(p []byte) (int, error) {
163
	n, err := C.gpgme_data_write(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))
164
	runtime.KeepAlive(d)
165
	if err != nil {
166
		return 0, err
167
	}
168
	if n == 0 {
169
		return 0, io.EOF
170
	}
171
	return int(n), nil
172
}
173

174
func (d *Data) Read(p []byte) (int, error) {
175
	n, err := C.gpgme_data_read(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))
176
	runtime.KeepAlive(d)
177
	if err != nil {
178
		return 0, err
179
	}
180
	if n == 0 {
181
		return 0, io.EOF
182
	}
183
	return int(n), nil
184
}
185

186
func (d *Data) Seek(offset int64, whence int) (int64, error) {
187
	n, err := C.gogpgme_data_seek(d.dh, C.gpgme_off_t(offset), C.int(whence))
188
	runtime.KeepAlive(d)
189
	return int64(n), err
190
}
191

192
// Name returns the associated filename if any
193
func (d *Data) Name() string {
194
	res := C.GoString(C.gpgme_data_get_file_name(d.dh))
195
	runtime.KeepAlive(d)
196
	return res
197
}
198

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.