Fix comment indentation.
[gpgme.git] / gpgme / data-compat.c
1 /* data-compat.c - Compatibility interfaces for data objects.
2    Copyright (C) 2002 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 <errno.h>
25 #include <sys/stat.h>
26 #include <stdlib.h>
27
28 #include "data.h"
29 #include "util.h"
30
31 \f
32 /* Create a new data buffer filled with LENGTH bytes starting from
33    OFFSET within the file FNAME or stream STREAM (exactly one must be
34    non-zero).  */
35 GpgmeError
36 gpgme_data_new_from_filepart (GpgmeData *dh, const char *fname, FILE *stream,
37                               off_t offset, size_t length)
38 {
39   GpgmeError err;
40   char *buf = NULL;
41
42   if (stream && fname)
43     return GPGME_Invalid_Value;
44
45   if (fname)
46     stream = fopen (fname, "rb");
47   if (!stream)
48     return GPGME_File_Error;
49
50   if (fseek (stream, offset, SEEK_SET))
51     goto ferr;
52
53   buf = malloc (length);
54   if (!buf)
55     goto ferr;
56
57   while (fread (buf, length, 1, stream) < 1
58          && ferror (stream) && errno == EINTR);
59   if (ferror (stream))
60     {
61       if (buf)
62         free (buf);
63       goto ferr;
64     }
65
66   if (fname)
67     fclose (stream);
68
69   err = gpgme_data_new (dh);
70   if (err)
71     {
72       if (buf)
73         free (buf);
74       return err;
75     }
76
77   (*dh)->data.mem.buffer = buf;
78   (*dh)->data.mem.size = length;
79   (*dh)->data.mem.length = length;
80   return 0;
81
82  ferr:
83   {
84     int saved_errno = errno;
85     if (fname)
86       fclose (stream);
87     errno = saved_errno;
88     return GPGME_File_Error;
89   }
90 }
91
92 \f
93 /* Create a new data buffer filled with the content of file FNAME.
94    COPY must be non-zero (delayed reads are not supported yet).  */
95 GpgmeError
96 gpgme_data_new_from_file (GpgmeData *dh, const char *fname, int copy)
97 {
98   struct stat statbuf;
99
100   if (!fname || !copy)
101     return GPGME_Invalid_Value;
102
103   if (stat (fname, &statbuf) < 0)
104     return GPGME_File_Error;
105
106   return gpgme_data_new_from_filepart (dh, fname, NULL, 0, statbuf.st_size);
107 }
108
109 \f
110 static int
111 gpgme_error_to_errno (GpgmeError err)
112 {
113   switch (err)
114     {
115     case GPGME_EOF:
116       return 0;
117     case GPGME_Out_Of_Core:
118       errno = ENOMEM;
119       return -1;
120     case GPGME_Invalid_Value:
121       errno = EINVAL;
122       return -1;
123     case GPGME_Busy:
124       errno = EBUSY;
125       return -1;
126     case GPGME_Not_Implemented:
127       errno = EOPNOTSUPP;
128       return -1;
129     default:
130       /* XXX Yeah, well.  */
131       errno = EINVAL;
132       return -1;
133     }
134 }
135
136 static ssize_t
137 old_user_read (GpgmeData dh, void *buffer, size_t size)
138 {
139   size_t amt;
140   GpgmeError err = (*dh->data.old_user.cb) (dh->data.old_user.handle,
141                                             buffer, size, &amt);
142   if (err)
143     return gpgme_error_to_errno (err);
144   return amt;
145 }
146
147
148 static off_t
149 old_user_seek (GpgmeData dh, off_t offset, int whence)
150 {
151   GpgmeError err;
152   if (whence != SEEK_SET || offset)
153     return EINVAL;
154   err = (*dh->data.old_user.cb) (dh->data.old_user.handle, NULL, 0, NULL);
155   if (err)
156     return gpgme_error_to_errno (err);
157   return 0;
158 }
159
160
161 static struct gpgme_data_cbs old_user_cbs =
162   {
163     old_user_read,
164     NULL,
165     old_user_seek,
166     NULL
167   };
168
169
170 /* Create a new data buffer which retrieves the data from the callback
171    function READ_CB.  */
172 GpgmeError
173 gpgme_data_new_with_read_cb (GpgmeData *dh,
174                              int (*read_cb) (void *, char *, size_t, size_t *),
175                              void *read_cb_value)
176 {
177   GpgmeError err = _gpgme_data_new (dh, &old_user_cbs);
178   if (err)
179     return err;
180
181   (*dh)->data.old_user.cb = read_cb;
182   (*dh)->data.old_user.handle = read_cb_value;
183   return 0;
184 }
185
186 \f
187 GpgmeError
188 gpgme_data_rewind (GpgmeData dh)
189 {
190   return (gpgme_data_seek (dh, 0, SEEK_SET) == -1)
191     ? GPGME_File_Error : 0;
192 }