2003-05-18 Marcus Brinkmann <marcus@g10code.de>
[gpgme.git] / gpgme / data.c
1 /* data.c - An abstraction for data objects.
2    Copyright (C) 2002, 2003 g10 Code GmbH
3
4    This file is part of GPGME.
5  
6    GPGME is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10  
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    General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with GPGME; if not, write to the Free Software Foundation,
18    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA.  */
19
20 #if HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #include <string.h>
28
29 #include "gpgme.h"
30 #include "data.h"
31 #include "util.h"
32 #include "ops.h"
33 #include "io.h"
34
35 \f
36 gpgme_error_t
37 _gpgme_data_new (gpgme_data_t *r_dh, struct _gpgme_data_cbs *cbs)
38 {
39   gpgme_data_t dh;
40
41   if (!r_dh)
42     return GPGME_Invalid_Value;
43
44   *r_dh = NULL;
45   dh = calloc (1, sizeof (*dh));
46   if (!dh)
47     return GPGME_Out_Of_Core;
48
49   dh->cbs = cbs;
50
51   *r_dh = dh;
52   return 0;
53 }
54
55
56 void
57 _gpgme_data_release (gpgme_data_t dh)
58 {
59   if (dh)
60     free (dh);
61 }
62
63 \f
64 /* Read up to SIZE bytes into buffer BUFFER from the data object with
65    the handle DH.  Return the number of characters read, 0 on EOF and
66    -1 on error.  If an error occurs, errno is set.  */
67 ssize_t
68 gpgme_data_read (gpgme_data_t dh, void *buffer, size_t size)
69 {
70   if (!dh)
71     {
72       errno = EINVAL;
73       return -1;
74     }
75   if (!dh->cbs->read)
76     {
77       errno = EOPNOTSUPP;
78       return -1;
79     }
80   return (*dh->cbs->read) (dh, buffer, size);
81 }
82
83
84 /* Write up to SIZE bytes from buffer BUFFER to the data object with
85    the handle DH.  Return the number of characters written, or -1 on
86    error.  If an error occurs, errno is set.  */
87 ssize_t
88 gpgme_data_write (gpgme_data_t dh, const void *buffer, size_t size)
89 {
90   if (!dh)
91     {
92       errno = EINVAL;
93       return -1;
94     }
95   if (!dh->cbs->write)
96     {
97       errno = EOPNOTSUPP;
98       return -1;
99     }
100   return (*dh->cbs->write) (dh, buffer, size);
101 }
102
103
104 /* Set the current position from where the next read or write starts
105    in the data object with the handle DH to OFFSET, relativ to
106    WHENCE.  */
107 off_t
108 gpgme_data_seek (gpgme_data_t dh, off_t offset, int whence)
109 {
110   if (!dh)
111     {
112       errno = EINVAL;
113       return -1;
114     }
115   if (!dh->cbs->read)
116     {
117       errno = EOPNOTSUPP;
118       return -1;
119     }
120   return (*dh->cbs->seek) (dh, offset, whence);
121 }
122
123
124 /* Release the data object with the handle DH.  */
125 void
126 gpgme_data_release (gpgme_data_t dh)
127 {
128   if (!dh)
129     return;
130
131   if (dh->cbs->release)
132     (*dh->cbs->release) (dh);
133   _gpgme_data_release (dh);
134 }
135
136
137 /* Get the current encoding meta information for the data object with
138    handle DH.  */
139 gpgme_data_encoding_t
140 gpgme_data_get_encoding (gpgme_data_t dh)
141 {
142   return dh ? dh->encoding : GPGME_DATA_ENCODING_NONE;
143 }
144
145
146 /* Set the encoding meta information for the data object with handle
147    DH to ENC.  */
148 gpgme_error_t
149 gpgme_data_set_encoding (gpgme_data_t dh, gpgme_data_encoding_t enc)
150 {
151   if (!dh)
152     return GPGME_Invalid_Value;
153   if (enc < 0 || enc > GPGME_DATA_ENCODING_ARMOR)
154     return GPGME_Invalid_Value;
155   dh->encoding = enc;
156   return 0;
157 }
158
159 \f
160 /* Functions to support the wait interface.  */
161
162 gpgme_error_t
163 _gpgme_data_inbound_handler (void *opaque, int fd)
164 {
165   gpgme_data_t dh = (gpgme_data_t) opaque;
166   char buffer[BUFFER_SIZE];
167   char *bufp = buffer;
168   ssize_t buflen;
169
170   buflen = read (fd, buffer, BUFFER_SIZE);
171   if (buflen < 0)
172     return GPGME_File_Error;
173   if (buflen == 0)
174     {
175       _gpgme_io_close (fd);
176       return 0;
177     }
178
179   do
180     {
181       ssize_t amt = gpgme_data_write (dh, bufp, buflen);
182       if (amt == 0 || (amt < 0 && errno != EINTR))
183         return GPGME_File_Error;
184       bufp += amt;
185       buflen -= amt;
186     }
187   while (buflen > 0);
188   return 0;
189 }
190
191
192 gpgme_error_t
193 _gpgme_data_outbound_handler (void *opaque, int fd)
194 {
195   gpgme_data_t dh = (gpgme_data_t) opaque;
196   ssize_t nwritten;
197
198   if (!dh->pending_len)
199     {
200       ssize_t amt = gpgme_data_read (dh, dh->pending, BUFFER_SIZE);
201       if (amt < 0)
202         return GPGME_File_Error;
203       if (amt == 0)
204         {
205           _gpgme_io_close (fd);
206           return 0;
207         }
208       dh->pending_len = amt;
209     }
210
211   nwritten = _gpgme_io_write (fd, dh->pending, dh->pending_len);
212   if (nwritten == -1 && errno == EAGAIN )
213     return 0;
214
215   if (nwritten <= 0)
216     return GPGME_File_Error;
217
218   if (nwritten < dh->pending_len)
219     memmove (dh->pending, dh->pending + nwritten, dh->pending_len - nwritten);
220   dh->pending_len -= nwritten;
221   return 0;
222 }