1 /* stream.c - The stream implementation
2 * Copyright (C) 2002-2012 Free Software Foundation, Inc.
6 * This file is part of OpenCDK.
8 * The OpenCDK library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
42 /* This is the maximal amount of bytes we map. */
43 #define MAX_MAP_SIZE 16777216
45 static cdk_error_t
stream_flush (cdk_stream_t s
);
46 static cdk_error_t
stream_filter_write (cdk_stream_t s
);
47 static int stream_cache_flush (cdk_stream_t s
, FILE * fp
);
48 struct stream_filter_s
*filter_add (cdk_stream_t s
, filter_fnct_t fnc
,
52 /* FIXME: The read/write/putc/getc function cannot directly
53 return an error code. It is stored in an error variable
54 inside the string. Right now there is no code to
55 return the error code or to reset it. */
59 * @file: The file to open
60 * @ret_s: The new STREAM object
62 * Creates a new stream based on an existing file. The stream is
63 * opened in read-only mode.
66 cdk_stream_open (const char *file
, cdk_stream_t
* ret_s
)
68 return _cdk_stream_open_mode (file
, "rb", ret_s
);
72 /* Helper function to allow to open a stream in different modes. */
74 _cdk_stream_open_mode (const char *file
, const char *mode
,
86 _gnutls_read_log ("open stream `%s'\n", file
);
89 s
= cdk_calloc (1, sizeof *s
);
93 return CDK_Out_Of_Core
;
95 s
->fname
= cdk_strdup (file
);
100 return CDK_Out_Of_Core
;
102 s
->fp
= fopen (file
, mode
);
108 return CDK_File_Error
;
111 _gnutls_read_log ("open stream fd=%d\n", fileno (s
->fp
));
120 * cdk_stream_new_from_cbs:
121 * @cbs: the callback context with all user callback functions
122 * @opa: uint8_t handle which is passed to all callbacks.
123 * @ret_s: the allocated stream
125 * This function creates a stream which uses user callback
126 * for the core operations (open, close, read, write, seek).
129 cdk_stream_new_from_cbs (cdk_stream_cbs_t cbs
, void *opa
,
130 cdk_stream_t
* ret_s
)
134 if (!cbs
|| !opa
|| !ret_s
)
137 return CDK_Inv_Value
;
141 s
= cdk_calloc (1, sizeof *s
);
145 return CDK_Out_Of_Core
;
148 s
->cbs
.read
= cbs
->read
;
149 s
->cbs
.write
= cbs
->write
;
150 s
->cbs
.seek
= cbs
->seek
;
151 s
->cbs
.release
= cbs
->release
;
152 s
->cbs
.open
= cbs
->open
;
156 /* If there is a user callback for open, we need to call it
157 here because read/write expects an open stream. */
159 return s
->cbs
.open (s
->cbs_hd
);
166 * @file: The name of the new file
167 * @ret_s: The new STREAM object
169 * Create a new stream into the given file.
172 cdk_stream_new (const char *file
, cdk_stream_t
* ret_s
)
179 return CDK_Inv_Value
;
183 _gnutls_read_log ("new stream `%s'\n", file
? file
: "[temp]");
186 s
= cdk_calloc (1, sizeof *s
);
190 return CDK_Out_Of_Core
;
197 s
->fname
= cdk_strdup (file
);
202 return CDK_Out_Of_Core
;
205 s
->fp
= _cdk_tmpfile ();
211 return CDK_File_Error
;
214 _gnutls_read_log ("new stream fd=%d\n", fileno (s
->fp
));
222 * @file: the filename
225 * Creates a new stream.
226 * The difference to cdk_stream_new is, that no filtering can be used with
227 * this kind of stream and everything is written directly to the stream.
230 cdk_stream_create (const char *file
, cdk_stream_t
* ret_s
)
237 return CDK_Inv_Value
;
241 _gnutls_read_log ("create stream `%s'\n", file
);
244 s
= cdk_calloc (1, sizeof *s
);
248 return CDK_Out_Of_Core
;
251 s
->flags
.filtrated
= 1;
252 s
->fname
= cdk_strdup (file
);
257 return CDK_Out_Of_Core
;
259 s
->fp
= fopen (file
, "w+b");
265 return CDK_File_Error
;
268 _gnutls_read_log ("stream create fd=%d\n", fileno (s
->fp
));
276 * cdk_stream_tmp_new:
277 * @r_out: the new temp stream.
279 * Allocates a new tempory stream which is not associated with a file.
282 cdk_stream_tmp_new (cdk_stream_t
* r_out
)
284 return cdk_stream_new (NULL
, r_out
);
290 * cdk_stream_tmp_from_mem:
291 * @buf: the buffer which shall be written to the temp stream.
292 * @buflen: how large the buffer is
293 * @r_out: the new stream with the given contents.
295 * Creates a new tempory stream with the given contests.
298 cdk_stream_tmp_from_mem (const void *buf
, size_t buflen
, cdk_stream_t
* r_out
)
305 rc
= cdk_stream_tmp_new (&s
);
312 nwritten
= cdk_stream_write (s
, buf
, buflen
);
315 cdk_stream_close (s
);
319 cdk_stream_seek (s
, 0);
326 _cdk_stream_fpopen (FILE * fp
, unsigned write_mode
, cdk_stream_t
* ret_out
)
331 s
= cdk_calloc (1, sizeof *s
);
335 return CDK_Out_Of_Core
;
339 _gnutls_read_log ("stream ref fd=%d\n", fileno (fp
));
343 s
->flags
.filtrated
= 1;
344 s
->flags
.write
= write_mode
;
352 _cdk_stream_append (const char *file
, cdk_stream_t
* ret_s
)
360 return CDK_Inv_Value
;
364 rc
= _cdk_stream_open_mode (file
, "a+b", &s
);
371 /* In the append mode, we need to write to the flag. */
378 * cdk_stream_is_compressed:
381 * Check whether stream is compressed.
383 * Returns: 0 if the stream is uncompressed, otherwise the compression
387 cdk_stream_is_compressed (cdk_stream_t s
)
391 return s
->flags
.compressed
;
395 _cdk_stream_set_compress_algo (cdk_stream_t s
, int algo
)
399 s
->flags
.compressed
= algo
;
404 cdk_stream_flush (cdk_stream_t s
)
411 return CDK_Inv_Value
;
414 /* The user callback does not support flush */
418 /* For read-only streams, no flush is needed. */
422 if (!s
->flags
.filtrated
)
424 if (!cdk_stream_get_length (s
))
426 rc
= cdk_stream_seek (s
, 0);
428 rc
= stream_flush (s
);
430 rc
= stream_filter_write (s
);
431 s
->flags
.filtrated
= 1;
444 cdk_stream_tmp_set_mode (cdk_stream_t s
, int val
)
446 if (s
&& s
->flags
.temp
)
453 * @s: The STREAM object.
455 * Close a stream and flush all buffers. This function work different
456 * for read or write streams. When the stream is for reading, the
457 * filtering is already done and we can simply close the file and all
458 * buffers. But for the case it's a write stream, we need to apply
459 * all registered filters now. The file is closed in the filter
460 * function and not here.
463 cdk_stream_close (cdk_stream_t s
)
465 struct stream_filter_s
*f
, *f2
;
471 return CDK_Inv_Value
;
475 _gnutls_read_log ("close stream ref=%d `%s'\n",
476 s
->fp_ref
, s
->fname
? s
->fname
: "[temp]");
479 /* In the user callback mode, we call the release cb if possible
480 and just free the stream. */
484 rc
= s
->cbs
.release (s
->cbs_hd
);
494 if (!s
->flags
.filtrated
&& !s
->error
)
495 rc
= cdk_stream_flush (s
);
496 if (!s
->fp_ref
&& (s
->fname
|| s
->flags
.temp
))
501 _gnutls_read_log ("close stream fd=%d\n", fileno (s
->fp
));
503 err
= fclose (s
->fp
);
509 /* Iterate over the filter list and use the cleanup flag to
510 free the allocated internal structures. */
516 f
->fnct (f
->uint8_t, STREAMCTL_FREE
, NULL
, NULL
);
527 cdk_free (s
->cache
.buf
);
528 s
->cache
.alloced
= 0;
541 * @s: The STREAM object.
543 * Return if the associated file handle was set to EOF. This
544 * function will only work with read streams.
547 cdk_stream_eof (cdk_stream_t s
)
549 return s
? s
->flags
.eof
: -1;
554 _cdk_stream_get_fname (cdk_stream_t s
)
560 return s
->fname
? s
->fname
: NULL
;
564 /* Return the underlying FP of the stream.
565 WARNING: This handle should not be closed. */
567 _cdk_stream_get_fp (cdk_stream_t s
)
569 return s
? s
->fp
: NULL
;
574 _cdk_stream_get_errno (cdk_stream_t s
)
576 return s
? s
->error
: CDK_Inv_Value
;
581 * cdk_stream_get_length:
582 * @s: The STREAM object.
584 * Return the length of the associated file handle. This function
585 * should work for both read and write streams. For write streams an
586 * additional flush is used to write possible pending data.
589 cdk_stream_get_length (cdk_stream_t s
)
600 /* The user callback does not support stat. */
604 rc
= stream_flush (s
);
612 if (fstat (fileno (s
->fp
), &statbuf
))
614 s
->error
= CDK_File_Error
;
619 return statbuf
.st_size
;
623 static struct stream_filter_s
*
624 filter_add2 (cdk_stream_t s
)
626 struct stream_filter_s
*f
;
630 f
= cdk_calloc (1, sizeof *f
);
633 f
->next
= s
->filters
;
639 static struct stream_filter_s
*
640 filter_search (cdk_stream_t s
, filter_fnct_t fnc
)
642 struct stream_filter_s
*f
;
646 for (f
= s
->filters
; f
; f
= f
->next
)
656 set_uint8_t (struct stream_filter_s
*f
)
661 f
->uint8_t = &f
->u
.afx
;
664 f
->uint8_t = &f
->u
.cfx
;
667 f
->uint8_t = &f
->u
.pfx
;
670 f
->uint8_t = &f
->u
.zfx
;
673 f
->uint8_t = &f
->u
.mfx
;
676 f
->uint8_t = &f
->u
.tfx
;
684 struct stream_filter_s
*
685 filter_add (cdk_stream_t s
, filter_fnct_t fnc
, int type
)
687 struct stream_filter_s
*f
;
691 s
->flags
.filtrated
= 0;
692 f
= filter_search (s
, fnc
);
699 f
->flags
.enabled
= 1;
709 stream_get_mode (cdk_stream_t s
)
715 return s
->flags
.write
;
720 stream_id_to_filter (int type
)
725 return _cdk_filter_armor
;
727 return _cdk_filter_literal
;
729 return _cdk_filter_text
;
730 /* case fCIPHER : return _cdk_filter_cipher; */
731 /* case fCOMPRESS: return _cdk_filter_compress; */
739 * cdk_stream_filter_disable:
740 * @s: The STREAM object
741 * @type: The numberic filter ID.
743 * Disables the filter with the type 'type'.
746 cdk_stream_filter_disable (cdk_stream_t s
, int type
)
748 struct stream_filter_s
*f
;
754 return CDK_Inv_Value
;
757 fnc
= stream_id_to_filter (type
);
761 return CDK_Inv_Value
;
763 f
= filter_search (s
, fnc
);
765 f
->flags
.enabled
= 0;
770 /* WARNING: tmp should not be closed by the caller. */
772 stream_fp_replace (cdk_stream_t s
, FILE ** tmp
)
779 _gnutls_read_log ("replace stream fd=%d with fd=%d\n",
780 fileno (s
->fp
), fileno (*tmp
));
787 return CDK_File_Error
;
795 /* This function is exactly like filter_read, except the fact that we can't
796 use tmpfile () all the time. That's why we open the real file when there
797 is no last filter. */
799 stream_filter_write (cdk_stream_t s
)
801 struct stream_filter_s
*f
;
806 if (s
->flags
.filtrated
)
809 return CDK_Inv_Value
;
812 for (f
= s
->filters
; f
; f
= f
->next
)
814 if (!f
->flags
.enabled
)
816 /* if there is no next filter, create the final output file */
818 _gnutls_read_log ("filter [write]: last filter=%d fname=%s\n",
819 f
->next
? 1 : 0, s
->fname
);
821 if (!f
->next
&& s
->fname
)
822 f
->tmp
= fopen (s
->fname
, "w+b");
824 f
->tmp
= _cdk_tmpfile ();
830 /* If there is no next filter, flush the cache. We also do this
831 when the next filter is the armor filter because this filter
832 is special and before it starts, all data should be written. */
833 if ((!f
->next
|| f
->next
->type
== fARMOR
) && s
->cache
.size
)
835 rc
= stream_cache_flush (s
, f
->tmp
);
839 rc
= f
->fnct (f
->uint8_t, f
->ctl
, s
->fp
, f
->tmp
);
841 _gnutls_read_log ("filter [write]: type=%d rc=%d\n", f
->type
, rc
);
844 rc
= stream_fp_replace (s
, &f
->tmp
);
846 rc
= cdk_stream_seek (s
, 0);
850 _gnutls_read_log ("filter [close]: fd=%d\n", fileno (f
->tmp
));
861 /* Here all data from the file handle is passed through all filters.
862 The scheme works like this:
863 Create a tempfile and use it for the output of the filter. Then the
864 original file handle will be closed and replace with the temp handle.
865 The file pointer will be set to the begin and the game starts again. */
867 stream_filter_read (cdk_stream_t s
)
869 struct stream_filter_s
*f
;
874 if (s
->flags
.filtrated
)
877 for (f
= s
->filters
; f
; f
= f
->next
)
879 if (!f
->flags
.enabled
)
884 _gnutls_read_log ("filter %s [read]: has the error flag; skipped\n",
885 s
->fname
? s
->fname
: "[temp]");
890 f
->tmp
= _cdk_tmpfile ();
896 rc
= f
->fnct (f
->uint8_t, f
->ctl
, s
->fp
, f
->tmp
);
898 _gnutls_read_log ("filter %s [read]: type=%d rc=%d\n",
899 s
->fname
? s
->fname
: "[temp]", f
->type
, rc
);
908 /* If the filter is read-only, do not replace the FP because
909 the contents were not altered in any way. */
910 if (!f
->flags
.rdonly
)
912 rc
= stream_fp_replace (s
, &f
->tmp
);
921 rc
= cdk_stream_seek (s
, 0);
924 /* Disable the filter after it was successfully used. The idea
925 is the following: let's say the armor filter was pushed and
926 later more filters were added. The second time the filter code
927 will be executed, only the new filter should be started but
928 not the old because we already used it. */
929 f
->flags
.enabled
= 0;
937 _cdk_stream_get_uint8_t (cdk_stream_t s
, int fid
)
939 struct stream_filter_s
*f
;
944 for (f
= s
->filters
; f
; f
= f
->next
)
946 if ((int) f
->type
== fid
)
955 * @s: The STREAM object.
956 * @buf: The buffer to insert the readed bytes.
957 * @count: Request so much bytes.
959 * Tries to read count bytes from the STREAM object.
960 * When this function is called the first time, it can take a while
961 * because all filters need to be processed. Please remember that you
962 * need to add the filters in reserved order.
965 cdk_stream_read (cdk_stream_t s
, void *buf
, size_t buflen
)
979 return s
->cbs
.read (s
->cbs_hd
, buf
, buflen
);
983 if (s
->flags
.write
&& !s
->flags
.temp
)
985 s
->error
= CDK_Inv_Mode
;
987 return EOF
; /* This is a write stream */
990 if (!s
->flags
.no_filter
&& !s
->cache
.on
&& !s
->flags
.filtrated
)
992 rc
= stream_filter_read (s
);
996 if (s
->fp
&& feof (s
->fp
))
1001 s
->flags
.filtrated
= 1;
1004 if (!buf
&& !buflen
)
1007 nread
= fread (buf
, 1, buflen
, s
->fp
);
1021 cdk_stream_getc (cdk_stream_t s
)
1023 unsigned char buf
[2];
1031 nread
= cdk_stream_read (s
, buf
, 1);
1034 s
->error
= CDK_File_Error
;
1044 * @s: The STREAM object
1045 * @buf: The buffer with the values to write.
1046 * @count: The size of the buffer.
1048 * Tries to write count bytes into the stream.
1049 * In this function we simply write the bytes to the stream. We can't
1050 * use the filters here because it would mean they have to support
1054 cdk_stream_write (cdk_stream_t s
, const void *buf
, size_t count
)
1067 return s
->cbs
.write (s
->cbs_hd
, buf
, count
);
1071 if (!s
->flags
.write
)
1073 s
->error
= CDK_Inv_Mode
; /* this is a read stream */
1079 return stream_flush (s
);
1084 _gnutls_read_log ("stream[ref=%u]: written %d bytes\n", s
->fp_ref
, (int) count
);
1087 /* We need to resize the buffer if the additional data wouldn't
1088 fit into it. We allocate more memory to avoid to resize it the
1089 next time the function is used. */
1090 if (s
->cache
.size
+ count
> s
->cache
.alloced
)
1092 byte
*old
= s
->cache
.buf
;
1095 cdk_calloc (1, s
->cache
.alloced
+ count
+ STREAM_BUFSIZE
);
1096 s
->cache
.alloced
+= (count
+ STREAM_BUFSIZE
);
1097 memcpy (s
->cache
.buf
, old
, s
->cache
.size
);
1100 _gnutls_read_log ("stream: enlarge cache to %d octets\n",
1101 (int) s
->cache
.alloced
);
1105 memcpy (s
->cache
.buf
+ s
->cache
.size
, buf
, count
);
1106 s
->cache
.size
+= count
;
1111 _gnutls_read_log ("stream[fd=%u]: written %d bytes\n", fileno (s
->fp
), (int) count
);
1114 nwritten
= fwrite (buf
, 1, count
, s
->fp
);
1122 cdk_stream_putc (cdk_stream_t s
, int c
)
1133 nwritten
= cdk_stream_write (s
, buf
, 1);
1134 if (nwritten
== EOF
)
1141 cdk_stream_tell (cdk_stream_t s
)
1143 return s
? ftell (s
->fp
) : (off_t
) - 1;
1148 cdk_stream_seek (cdk_stream_t s
, off_t offset
)
1155 return CDK_Inv_Value
;
1161 return s
->cbs
.seek (s
->cbs_hd
, offset
);
1165 /* Set or reset the EOF flag. */
1166 len
= cdk_stream_get_length (s
);
1172 if (fseek (s
->fp
, offset
, SEEK_SET
))
1175 return CDK_File_Error
;
1182 stream_flush (cdk_stream_t s
)
1186 /* For some constellations it cannot be assured that the
1187 return value is defined, thus we ignore it for now. */
1188 (void) fflush (s
->fp
);
1194 * cdk_stream_set_armor_flag:
1195 * @s: the stream object
1196 * @type: the type of armor to use
1198 * If the file is in read-mode, no armor type needs to be
1199 * defined (armor_type=0) because the armor filter will be
1200 * used for decoding existing armor data.
1201 * For the write mode, @armor_type can be set to any valid
1202 * armor type (message, key, sig).
1205 cdk_stream_set_armor_flag (cdk_stream_t s
, int armor_type
)
1207 struct stream_filter_s
*f
;
1212 return CDK_Inv_Value
;
1214 f
= filter_add (s
, _cdk_filter_armor
, fARMOR
);
1218 return CDK_Out_Of_Core
;
1220 f
->u
.afx
.idx
= f
->u
.afx
.idx2
= armor_type
;
1221 f
->ctl
= stream_get_mode (s
);
1227 * cdk_stream_set_literal_flag:
1228 * @s: the stream object
1229 * @mode: the mode to use (binary, text, unicode)
1230 * @fname: the file name to store in the packet.
1232 * In read mode it kicks off the literal decoding routine to
1233 * unwrap the data from the packet. The @mode parameter is ignored.
1234 * In write mode the function can be used to wrap the stream data
1235 * into a literal packet with the given mode and file name.
1238 cdk_stream_set_literal_flag (cdk_stream_t s
, cdk_lit_format_t mode
,
1241 struct stream_filter_s
*f
;
1242 const char *orig_fname
;
1245 _gnutls_read_log ("stream: enable literal mode.\n");
1251 return CDK_Inv_Value
;
1254 orig_fname
= _cdk_stream_get_fname (s
);
1255 f
= filter_add (s
, _cdk_filter_literal
, fLITERAL
);
1259 return CDK_Out_Of_Core
;
1261 f
->u
.pfx
.mode
= mode
;
1262 f
->u
.pfx
.filename
= fname
? cdk_strdup (fname
) : NULL
;
1263 f
->u
.pfx
.orig_filename
= orig_fname
? cdk_strdup (orig_fname
) : NULL
;
1264 f
->ctl
= stream_get_mode (s
);
1267 f
->u
.pfx
.blkmode
.on
= 1;
1268 f
->u
.pfx
.blkmode
.size
= s
->blkmode
;
1275 * cdk_stream_set_compress_flag:
1276 * @s: the stream object
1277 * @algo: the compression algo
1278 * @level: level of compression (0..9)
1280 * In read mode it kicks off the decompression filter to retrieve
1281 * the uncompressed data.
1282 * In write mode the stream data will be compressed with the
1283 * given algorithm at the given level.
1286 cdk_stream_set_compress_flag (cdk_stream_t s
, int algo
, int level
)
1290 return CDK_Not_Implemented
;
1295 * cdk_stream_set_text_flag:
1296 * @s: the stream object
1299 * Pushes the text filter to store the stream data in cannoncial format.
1302 cdk_stream_set_text_flag (cdk_stream_t s
, const char *lf
)
1304 struct stream_filter_s
*f
;
1309 return CDK_Inv_Value
;
1311 f
= filter_add (s
, _cdk_filter_text
, fTEXT
);
1315 return CDK_Out_Of_Core
;
1317 f
->ctl
= stream_get_mode (s
);
1324 * cdk_stream_set_hash_flag:
1325 * @s: the stream object
1326 * @digest_algo: the digest algorithm to use
1328 * This is for read-only streams. It pushes a digest filter to
1329 * calculate the digest of the given stream data.
1332 cdk_stream_set_hash_flag (cdk_stream_t s
, int digest_algo
)
1334 struct stream_filter_s
*f
;
1339 return CDK_Inv_Value
;
1341 if (stream_get_mode (s
))
1344 return CDK_Inv_Mode
;
1346 f
= filter_add (s
, _cdk_filter_hash
, fHASH
);
1350 return CDK_Out_Of_Core
;
1352 f
->ctl
= stream_get_mode (s
);
1353 f
->u
.mfx
.digest_algo
= digest_algo
;
1354 f
->flags
.rdonly
= 1;
1360 * cdk_stream_enable_cache:
1361 * @s: the stream object
1364 * Enables or disable the cache section of a stream object.
1367 cdk_stream_enable_cache (cdk_stream_t s
, int val
)
1372 return CDK_Inv_Value
;
1374 if (!s
->flags
.write
)
1377 return CDK_Inv_Mode
;
1382 s
->cache
.buf
= cdk_calloc (1, STREAM_BUFSIZE
);
1383 s
->cache
.alloced
= STREAM_BUFSIZE
;
1385 _gnutls_read_log ("stream: allocate cache of %d octets\n",
1394 stream_cache_flush (cdk_stream_t s
, FILE * fp
)
1400 /* FIXME: We should find a way to use cdk_stream_write here. */
1401 if (s
->cache
.size
> 0)
1403 nwritten
= fwrite (s
->cache
.buf
, 1, s
->cache
.size
, fp
);
1407 return CDK_File_Error
;
1411 memset (s
->cache
.buf
, 0, s
->cache
.alloced
);
1418 * cdk_stream_kick_off:
1419 * @inp: the input stream
1420 * @out: the output stream.
1422 * Passes the entire data from @inp into the output stream @out
1423 * with all the activated filters.
1426 cdk_stream_kick_off (cdk_stream_t inp
, cdk_stream_t out
)
1429 int nread
, nwritten
;
1435 return CDK_Inv_Value
;
1438 while (!cdk_stream_eof (inp
))
1440 nread
= cdk_stream_read (inp
, buf
, DIM (buf
));
1441 if (!nread
|| nread
== EOF
)
1443 nwritten
= cdk_stream_write (out
, buf
, nread
);
1444 if (!nwritten
|| nwritten
== EOF
)
1445 { /* In case of errors, we leave the loop. */
1451 memset (buf
, 0, sizeof (buf
));
1457 * cdk_stream_mmap_part:
1459 * @off: the offset where to start
1460 * @len: how much bytes shall be mapped
1461 * @ret_buf: the buffer to store the content
1462 * @ret_buflen: length of the buffer
1464 * Maps the data of the given stream into a memory section. @ret_count
1465 * contains the length of the buffer.
1468 cdk_stream_mmap_part (cdk_stream_t s
, off_t off
, size_t len
,
1469 byte
** ret_buf
, size_t * ret_buflen
)
1475 if (!ret_buf
|| !ret_buflen
)
1478 return CDK_Inv_Value
;
1486 return CDK_Inv_Value
;
1489 /* Memory mapping is not supported on custom I/O objects. */
1493 _gnutls_read_log ("cdk_stream_mmap_part: not supported on callbacks\n");
1496 return CDK_Inv_Mode
;
1499 oldpos
= cdk_stream_tell (s
);
1500 rc
= cdk_stream_flush (s
);
1506 rc
= cdk_stream_seek (s
, off
);
1513 len
= cdk_stream_get_length (s
);
1516 _gnutls_read_log ("cdk_stream_mmap_part: invalid file size %lu\n", (unsigned long)len
);
1520 if (len
> MAX_MAP_SIZE
)
1523 return CDK_Too_Short
;
1526 *ret_buf
= cdk_calloc (1, len
+ 1);
1528 n
= cdk_stream_read (s
, *ret_buf
, len
);
1531 rc
= cdk_stream_seek (s
, oldpos
);
1539 cdk_stream_mmap (cdk_stream_t inp
, byte
** buf
, size_t * buflen
)
1543 /* We need to make sure all data is flushed before we retrieve the size. */
1544 cdk_stream_flush (inp
);
1545 len
= cdk_stream_get_length (inp
);
1546 return cdk_stream_mmap_part (inp
, 0, len
, buf
, buflen
);
1552 * @inp: the input stream handle
1554 * @count: number of bytes to peek
1556 * The function acts like cdk_stream_read with the difference that
1557 * the file pointer is moved to the old position after the bytes were read.
1560 cdk_stream_peek (cdk_stream_t inp
, byte
* buf
, size_t buflen
)
1570 off
= cdk_stream_tell (inp
);
1571 nbytes
= cdk_stream_read (inp
, buf
, buflen
);
1574 if (cdk_stream_seek (inp
, off
))
1580 /* Try to read a line from the given stream. */
1582 _cdk_stream_gets (cdk_stream_t s
, char *buf
, size_t count
)
1589 while (!cdk_stream_eof (s
) && count
> 0)
1591 c
= cdk_stream_getc (s
);
1592 if (c
== EOF
|| c
== '\r' || c
== '\n')
1604 /* Try to write string into the stream @s. */
1606 _cdk_stream_puts (cdk_stream_t s
, const char *buf
)
1608 return cdk_stream_write (s
, buf
, strlen (buf
));
1612 /* Activate the block mode for the given stream. */
1614 _cdk_stream_set_blockmode (cdk_stream_t s
, size_t nbytes
)
1619 _gnutls_read_log ("stream: activate block mode with blocksize %d\n",
1622 s
->blkmode
= nbytes
;
1627 /* Return the block mode state of the given stream. */
1629 _cdk_stream_get_blockmode (cdk_stream_t s
)
1631 return s
? s
->blkmode
: 0;