1 /* data.c - An abstraction for data objects.
2 Copyright (C) 2002, 2003, 2004, 2005, 2007 g10 Code GmbH
4 This file is part of GPGME.
6 GPGME is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of
9 the License, or (at your option) any later version.
11 GPGME is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
39 _gpgme_data_new (gpgme_data_t *r_dh, struct _gpgme_data_cbs *cbs)
44 return gpg_error (GPG_ERR_INV_VALUE);
47 dh = calloc (1, sizeof (*dh));
49 return gpg_error_from_syserror ();
59 _gpgme_data_release (gpgme_data_t dh)
70 /* Read up to SIZE bytes into buffer BUFFER from the data object with
71 the handle DH. Return the number of characters read, 0 on EOF and
72 -1 on error. If an error occurs, errno is set. */
74 gpgme_data_read (gpgme_data_t dh, void *buffer, size_t size)
77 TRACE_BEG2 (DEBUG_DATA, "gpgme_data_read", dh,
78 "buffer=%p, size=%u", buffer, size);
82 gpg_err_set_errno (EINVAL);
83 return TRACE_SYSRES (-1);
87 gpg_err_set_errno (ENOSYS);
88 return TRACE_SYSRES (-1);
91 res = (*dh->cbs->read) (dh, buffer, size);
92 while (res < 0 && errno == EINTR);
94 return TRACE_SYSRES (res);
98 /* Write up to SIZE bytes from buffer BUFFER to the data object with
99 the handle DH. Return the number of characters written, or -1 on
100 error. If an error occurs, errno is set. */
102 gpgme_data_write (gpgme_data_t dh, const void *buffer, size_t size)
105 TRACE_BEG2 (DEBUG_DATA, "gpgme_data_write", dh,
106 "buffer=%p, size=%u", buffer, size);
110 gpg_err_set_errno (EINVAL);
111 return TRACE_SYSRES (-1);
115 gpg_err_set_errno (ENOSYS);
116 return TRACE_SYSRES (-1);
119 res = (*dh->cbs->write) (dh, buffer, size);
120 while (res < 0 && errno == EINTR);
122 return TRACE_SYSRES (res);
126 /* Set the current position from where the next read or write starts
127 in the data object with the handle DH to OFFSET, relativ to
130 gpgme_data_seek (gpgme_data_t dh, off_t offset, int whence)
132 TRACE_BEG2 (DEBUG_DATA, "gpgme_data_seek", dh,
133 "offset=%lli, whence=%i", offset, whence);
137 gpg_err_set_errno (EINVAL);
138 return TRACE_SYSRES (-1);
142 gpg_err_set_errno (ENOSYS);
143 return TRACE_SYSRES (-1);
146 /* For relative movement, we must take into account the actual
147 position of the read counter. */
148 if (whence == SEEK_CUR)
149 offset -= dh->pending_len;
151 offset = (*dh->cbs->seek) (dh, offset, whence);
155 return TRACE_SYSRES (offset);
159 /* Release the data object with the handle DH. */
161 gpgme_data_release (gpgme_data_t dh)
163 TRACE (DEBUG_DATA, "gpgme_data_release", dh);
168 if (dh->cbs->release)
169 (*dh->cbs->release) (dh);
170 _gpgme_data_release (dh);
174 /* Get the current encoding meta information for the data object with
176 gpgme_data_encoding_t
177 gpgme_data_get_encoding (gpgme_data_t dh)
179 TRACE1 (DEBUG_DATA, "gpgme_data_get_encoding", dh,
180 "dh->encoding=%i", dh ? dh->encoding : GPGME_DATA_ENCODING_NONE);
181 return dh ? dh->encoding : GPGME_DATA_ENCODING_NONE;
185 /* Set the encoding meta information for the data object with handle
188 gpgme_data_set_encoding (gpgme_data_t dh, gpgme_data_encoding_t enc)
190 TRACE_BEG1 (DEBUG_DATA, "gpgme_data_set_encoding", dh,
193 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
194 if (enc < 0 || enc > GPGME_DATA_ENCODING_URL0)
195 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
197 return TRACE_ERR (0);
201 /* Set the file name associated with the data object with handle DH to
204 gpgme_data_set_file_name (gpgme_data_t dh, const char *file_name)
206 TRACE_BEG1 (DEBUG_DATA, "gpgme_data_set_file_name", dh,
207 "file_name=%s", file_name);
210 return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
213 free (dh->file_name);
217 dh->file_name = strdup (file_name);
219 return TRACE_ERR (gpg_error_from_syserror ());
224 return TRACE_ERR (0);
228 /* Get the file name associated with the data object with handle DH,
229 or NULL if there is none. */
231 gpgme_data_get_file_name (gpgme_data_t dh)
235 TRACE (DEBUG_DATA, "gpgme_data_get_file_name", dh);
239 TRACE1 (DEBUG_DATA, "gpgme_data_get_file_name", dh,
240 "dh->file_name=%s", dh->file_name);
241 return dh->file_name;
245 /* Functions to support the wait interface. */
248 _gpgme_data_inbound_handler (void *opaque, int fd)
250 struct io_cb_data *data = (struct io_cb_data *) opaque;
251 gpgme_data_t dh = (gpgme_data_t) data->handler_value;
252 char buffer[BUFFER_SIZE];
255 TRACE_BEG1 (DEBUG_CTX, "_gpgme_data_inbound_handler", dh,
258 buflen = _gpgme_io_read (fd, buffer, BUFFER_SIZE);
260 return gpg_error_from_syserror ();
263 _gpgme_io_close (fd);
264 return TRACE_ERR (0);
269 ssize_t amt = gpgme_data_write (dh, bufp, buflen);
270 if (amt == 0 || (amt < 0 && errno != EINTR))
271 return TRACE_ERR (gpg_error_from_syserror ());
276 return TRACE_ERR (0);
281 _gpgme_data_outbound_handler (void *opaque, int fd)
283 struct io_cb_data *data = (struct io_cb_data *) opaque;
284 gpgme_data_t dh = (gpgme_data_t) data->handler_value;
286 TRACE_BEG1 (DEBUG_CTX, "_gpgme_data_outbound_handler", dh,
289 if (!dh->pending_len)
291 ssize_t amt = gpgme_data_read (dh, dh->pending, BUFFER_SIZE);
293 return TRACE_ERR (gpg_error_from_syserror ());
296 _gpgme_io_close (fd);
297 return TRACE_ERR (0);
299 dh->pending_len = amt;
302 nwritten = _gpgme_io_write (fd, dh->pending, dh->pending_len);
303 if (nwritten == -1 && errno == EAGAIN)
304 return TRACE_ERR (0);
306 if (nwritten == -1 && errno == EPIPE)
308 /* Not much we can do. The other end closed the pipe, but we
309 still have data. This should only ever happen if the other
310 end is going to tell us what happened on some other channel.
311 Silently close our end. */
312 _gpgme_io_close (fd);
313 return TRACE_ERR (0);
317 return TRACE_ERR (gpg_error_from_syserror ());
319 if (nwritten < dh->pending_len)
320 memmove (dh->pending, dh->pending + nwritten, dh->pending_len - nwritten);
321 dh->pending_len -= nwritten;
322 return TRACE_ERR (0);
326 /* Get the file descriptor associated with DH, if possible. Otherwise
329 _gpgme_data_get_fd (gpgme_data_t dh)
331 if (!dh || !dh->cbs->get_fd)
333 return (*dh->cbs->get_fd) (dh);