File Coverage

bson/bson-reader.c
Criterion Covered Total %
statement 0 176 0.0
branch 0 88 0.0
condition n/a
subroutine n/a
pod n/a
total 0 264 0.0


line stmt bran cond sub pod time code
1             /*
2             * Copyright 2013 MongoDB, Inc.
3             *
4             * Licensed under the Apache License, Version 2.0 (the "License");
5             * you may not use this file except in compliance with the License.
6             * You may obtain a copy of the License at
7             *
8             * http://www.apache.org/licenses/LICENSE-2.0
9             *
10             * Unless required by applicable law or agreed to in writing, software
11             * distributed under the License is distributed on an "AS IS" BASIS,
12             * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13             * See the License for the specific language governing permissions and
14             * limitations under the License.
15             */
16              
17             #include "bson.h"
18              
19             #include
20             #include
21             #ifdef BSON_OS_WIN32
22             # include
23             # include
24             #endif
25             #include
26             #include
27             #include
28             #include
29              
30             #include "bson-reader.h"
31             #include "bson-memory.h"
32              
33              
34             typedef enum
35             {
36             BSON_READER_HANDLE = 1,
37             BSON_READER_DATA = 2,
38             } bson_reader_type_t;
39              
40              
41             typedef struct
42             {
43             bson_reader_type_t type;
44             void *handle;
45             bool done : 1;
46             bool failed : 1;
47             size_t end;
48             size_t len;
49             size_t offset;
50             size_t bytes_read;
51             bson_t inline_bson;
52             uint8_t *data;
53             bson_reader_read_func_t read_func;
54             bson_reader_destroy_func_t destroy_func;
55             } bson_reader_handle_t;
56              
57              
58             typedef struct
59             {
60             int fd;
61             bool do_close;
62             } bson_reader_handle_fd_t;
63              
64              
65             typedef struct
66             {
67             bson_reader_type_t type;
68             const uint8_t *data;
69             size_t length;
70             size_t offset;
71             bson_t inline_bson;
72             } bson_reader_data_t;
73              
74              
75             /*
76             *--------------------------------------------------------------------------
77             *
78             * _bson_reader_handle_fill_buffer --
79             *
80             * Attempt to read as much as possible until the underlying buffer
81             * in @reader is filled or we have reached end-of-stream or
82             * read failure.
83             *
84             * Returns:
85             * None.
86             *
87             * Side effects:
88             * None.
89             *
90             *--------------------------------------------------------------------------
91             */
92              
93             static void
94 0           _bson_reader_handle_fill_buffer (bson_reader_handle_t *reader) /* IN */
95             {
96             ssize_t ret;
97              
98             /*
99             * Handle first read specially.
100             */
101 0 0         if ((!reader->done) && (!reader->offset) && (!reader->end)) {
    0          
    0          
102 0           ret = reader->read_func (reader->handle, &reader->data[0], reader->len);
103              
104 0 0         if (ret <= 0) {
105 0           reader->done = true;
106 0           return;
107             }
108 0           reader->bytes_read += ret;
109              
110 0           reader->end = ret;
111 0           return;
112             }
113              
114             /*
115             * Move valid data to head.
116             */
117 0           memmove (&reader->data[0],
118 0           &reader->data[reader->offset],
119 0           reader->end - reader->offset);
120 0           reader->end = reader->end - reader->offset;
121 0           reader->offset = 0;
122              
123             /*
124             * Read in data to fill the buffer.
125             */
126 0           ret = reader->read_func (reader->handle,
127 0           &reader->data[reader->end],
128 0           reader->len - reader->end);
129              
130 0 0         if (ret <= 0) {
131 0           reader->done = true;
132 0           reader->failed = (ret < 0);
133             } else {
134 0           reader->bytes_read += ret;
135 0           reader->end += ret;
136             }
137              
138 0 0         BSON_ASSERT (reader->offset == 0);
139 0 0         BSON_ASSERT (reader->end <= reader->len);
140             }
141              
142              
143             /*
144             *--------------------------------------------------------------------------
145             *
146             * bson_reader_new_from_handle --
147             *
148             * Allocates and initializes a new bson_reader_t using the opaque
149             * handle provided.
150             *
151             * Parameters:
152             * @handle: an opaque handle to use to read data.
153             * @rf: a function to perform reads on @handle.
154             * @df: a function to release @handle, or NULL.
155             *
156             * Returns:
157             * A newly allocated bson_reader_t if successful, otherwise NULL.
158             * Free the successful result with bson_reader_destroy().
159             *
160             * Side effects:
161             * None.
162             *
163             *--------------------------------------------------------------------------
164             */
165              
166             bson_reader_t *
167 0           bson_reader_new_from_handle (void *handle,
168             bson_reader_read_func_t rf,
169             bson_reader_destroy_func_t df)
170             {
171             bson_reader_handle_t *real;
172              
173 0 0         BSON_ASSERT (handle);
174 0 0         BSON_ASSERT (rf);
175              
176 0           real = bson_malloc0 (sizeof *real);
177 0           real->type = BSON_READER_HANDLE;
178 0           real->data = bson_malloc0 (1024);
179 0           real->handle = handle;
180 0           real->len = 1024;
181 0           real->offset = 0;
182              
183 0           bson_reader_set_read_func ((bson_reader_t *)real, rf);
184              
185 0 0         if (df) {
186 0           bson_reader_set_destroy_func ((bson_reader_t *)real, df);
187             }
188              
189 0           _bson_reader_handle_fill_buffer (real);
190              
191 0           return (bson_reader_t *)real;
192             }
193              
194              
195             /*
196             *--------------------------------------------------------------------------
197             *
198             * _bson_reader_handle_fd_destroy --
199             *
200             * Cleanup allocations associated with state created in
201             * bson_reader_new_from_fd().
202             *
203             * Returns:
204             * None.
205             *
206             * Side effects:
207             * None.
208             *
209             *--------------------------------------------------------------------------
210             */
211              
212             static void
213 0           _bson_reader_handle_fd_destroy (void *handle) /* IN */
214             {
215 0           bson_reader_handle_fd_t *fd = handle;
216              
217 0 0         if (fd) {
218 0 0         if ((fd->fd != -1) && fd->do_close) {
    0          
219             #ifdef _WIN32
220             _close (fd->fd);
221             #else
222 0           close (fd->fd);
223             #endif
224             }
225 0           bson_free (fd);
226             }
227 0           }
228              
229              
230             /*
231             *--------------------------------------------------------------------------
232             *
233             * _bson_reader_handle_fd_read --
234             *
235             * Perform read on opaque handle created in
236             * bson_reader_new_from_fd().
237             *
238             * The underlying file descriptor is read from the current position
239             * using the bson_reader_handle_fd_t allocated.
240             *
241             * Returns:
242             * -1 on failure.
243             * 0 on end of stream.
244             * Greater than zero on success.
245             *
246             * Side effects:
247             * None.
248             *
249             *--------------------------------------------------------------------------
250             */
251              
252             static ssize_t
253 0           _bson_reader_handle_fd_read (void *handle, /* IN */
254             void *buf, /* IN */
255             size_t len) /* IN */
256             {
257 0           bson_reader_handle_fd_t *fd = handle;
258 0           ssize_t ret = -1;
259              
260 0 0         if (fd && (fd->fd != -1)) {
    0          
261             again:
262             #ifdef BSON_OS_WIN32
263             ret = _read (fd->fd, buf, (unsigned int)len);
264             #else
265 0           ret = read (fd->fd, buf, len);
266             #endif
267 0 0         if ((ret == -1) && (errno == EAGAIN)) {
    0          
268 0           goto again;
269             }
270             }
271              
272 0           return ret;
273             }
274              
275              
276             /*
277             *--------------------------------------------------------------------------
278             *
279             * bson_reader_new_from_fd --
280             *
281             * Create a new bson_reader_t using the file-descriptor provided.
282             *
283             * Parameters:
284             * @fd: a libc style file-descriptor.
285             * @close_on_destroy: if close() should be called on @fd when
286             * bson_reader_destroy() is called.
287             *
288             * Returns:
289             * A newly allocated bson_reader_t on success; otherwise NULL.
290             *
291             * Side effects:
292             * None.
293             *
294             *--------------------------------------------------------------------------
295             */
296              
297             bson_reader_t *
298 0           bson_reader_new_from_fd (int fd, /* IN */
299             bool close_on_destroy) /* IN */
300             {
301             bson_reader_handle_fd_t *handle;
302              
303 0 0         BSON_ASSERT (fd != -1);
304              
305 0           handle = bson_malloc0 (sizeof *handle);
306 0           handle->fd = fd;
307 0           handle->do_close = close_on_destroy;
308              
309 0           return bson_reader_new_from_handle (handle,
310             _bson_reader_handle_fd_read,
311             _bson_reader_handle_fd_destroy);
312             }
313              
314              
315             /**
316             * bson_reader_set_read_func:
317             * @reader: A bson_reader_t.
318             *
319             * Note that @reader must be initialized by bson_reader_init_from_handle(), or data
320             * will be destroyed.
321             */
322             /*
323             *--------------------------------------------------------------------------
324             *
325             * bson_reader_set_read_func --
326             *
327             * Set the read func to be provided for @reader.
328             *
329             * You probably want to use bson_reader_new_from_handle() or
330             * bson_reader_new_from_fd() instead.
331             *
332             * Returns:
333             * None.
334             *
335             * Side effects:
336             * None.
337             *
338             *--------------------------------------------------------------------------
339             */
340              
341             void
342 0           bson_reader_set_read_func (bson_reader_t *reader, /* IN */
343             bson_reader_read_func_t func) /* IN */
344             {
345 0           bson_reader_handle_t *real = (bson_reader_handle_t *)reader;
346              
347 0 0         BSON_ASSERT (reader->type == BSON_READER_HANDLE);
348              
349 0           real->read_func = func;
350 0           }
351              
352              
353             /*
354             *--------------------------------------------------------------------------
355             *
356             * bson_reader_set_destroy_func --
357             *
358             * Set the function to cleanup state when @reader is destroyed.
359             *
360             * You probably want bson_reader_new_from_fd() or
361             * bson_reader_new_from_handle() instead.
362             *
363             * Returns:
364             * None.
365             *
366             * Side effects:
367             * None.
368             *
369             *--------------------------------------------------------------------------
370             */
371              
372             void
373 0           bson_reader_set_destroy_func (bson_reader_t *reader, /* IN */
374             bson_reader_destroy_func_t func) /* IN */
375             {
376 0           bson_reader_handle_t *real = (bson_reader_handle_t *)reader;
377              
378 0 0         BSON_ASSERT (reader->type == BSON_READER_HANDLE);
379              
380 0           real->destroy_func = func;
381 0           }
382              
383              
384             /*
385             *--------------------------------------------------------------------------
386             *
387             * _bson_reader_handle_grow_buffer --
388             *
389             * Grow the buffer to the next power of two.
390             *
391             * Returns:
392             * None.
393             *
394             * Side effects:
395             * None.
396             *
397             *--------------------------------------------------------------------------
398             */
399              
400             static void
401 0           _bson_reader_handle_grow_buffer (bson_reader_handle_t *reader) /* IN */
402             {
403             size_t size;
404              
405 0           size = reader->len * 2;
406 0           reader->data = bson_realloc (reader->data, size);
407 0           reader->len = size;
408 0           }
409              
410              
411             /*
412             *--------------------------------------------------------------------------
413             *
414             * _bson_reader_handle_tell --
415             *
416             * Tell the current position within the underlying file-descriptor.
417             *
418             * Returns:
419             * An off_t containing the current offset.
420             *
421             * Side effects:
422             * None.
423             *
424             *--------------------------------------------------------------------------
425             */
426              
427             static off_t
428 0           _bson_reader_handle_tell (bson_reader_handle_t *reader) /* IN */
429             {
430             off_t off;
431              
432 0           off = (off_t)reader->bytes_read;
433 0           off -= (off_t)reader->end;
434 0           off += (off_t)reader->offset;
435              
436 0           return off;
437             }
438              
439              
440             /*
441             *--------------------------------------------------------------------------
442             *
443             * _bson_reader_handle_read --
444             *
445             * Read the next chunk of data from the underlying file descriptor
446             * and return a bson_t which should not be modified.
447             *
448             * There was a failure if NULL is returned and @reached_eof is
449             * not set to true.
450             *
451             * Returns:
452             * NULL on failure or end of stream.
453             *
454             * Side effects:
455             * @reached_eof is set if non-NULL.
456             *
457             *--------------------------------------------------------------------------
458             */
459              
460             static const bson_t *
461 0           _bson_reader_handle_read (bson_reader_handle_t *reader, /* IN */
462             bool *reached_eof) /* IN */
463             {
464             int32_t blen;
465              
466 0 0         if (reached_eof) {
467 0           *reached_eof = false;
468             }
469              
470 0 0         while (!reader->done) {
471 0 0         if ((reader->end - reader->offset) < 4) {
472 0           _bson_reader_handle_fill_buffer (reader);
473 0           continue;
474             }
475              
476 0           memcpy (&blen, &reader->data[reader->offset], sizeof blen);
477 0           blen = BSON_UINT32_FROM_LE (blen);
478              
479 0 0         if (blen < 5) {
480 0           return NULL;
481             }
482              
483 0 0         if (blen > (int32_t)(reader->end - reader->offset)) {
484 0 0         if (blen > (int32_t)reader->len) {
485 0           _bson_reader_handle_grow_buffer (reader);
486             }
487              
488 0           _bson_reader_handle_fill_buffer (reader);
489 0           continue;
490             }
491              
492 0 0         if (!bson_init_static (&reader->inline_bson,
493 0           &reader->data[reader->offset],
494 0           (uint32_t)blen)) {
495 0           return NULL;
496             }
497              
498 0           reader->offset += blen;
499              
500 0           return &reader->inline_bson;
501             }
502              
503 0 0         if (reached_eof) {
504 0 0         *reached_eof = reader->done && !reader->failed;
    0          
505             }
506              
507 0           return NULL;
508             }
509              
510              
511             /*
512             *--------------------------------------------------------------------------
513             *
514             * bson_reader_new_from_data --
515             *
516             * Allocates and initializes a new bson_reader_t that reads the memory
517             * provided as a stream of BSON documents.
518             *
519             * Parameters:
520             * @data: A buffer to read BSON documents from.
521             * @length: The length of @data.
522             *
523             * Returns:
524             * A newly allocated bson_reader_t that should be freed with
525             * bson_reader_destroy().
526             *
527             * Side effects:
528             * None.
529             *
530             *--------------------------------------------------------------------------
531             */
532              
533             bson_reader_t *
534 0           bson_reader_new_from_data (const uint8_t *data, /* IN */
535             size_t length) /* IN */
536             {
537             bson_reader_data_t *real;
538              
539 0 0         BSON_ASSERT (data);
540              
541 0           real = (bson_reader_data_t*)bson_malloc0 (sizeof *real);
542 0           real->type = BSON_READER_DATA;
543 0           real->data = data;
544 0           real->length = length;
545 0           real->offset = 0;
546              
547 0           return (bson_reader_t *)real;
548             }
549              
550              
551             /*
552             *--------------------------------------------------------------------------
553             *
554             * _bson_reader_data_read --
555             *
556             * Read the next document from the underlying buffer.
557             *
558             * Returns:
559             * NULL on failure or end of stream.
560             * a bson_t which should not be modified.
561             *
562             * Side effects:
563             * None.
564             *
565             *--------------------------------------------------------------------------
566             */
567              
568             static const bson_t *
569 0           _bson_reader_data_read (bson_reader_data_t *reader, /* IN */
570             bool *reached_eof) /* IN */
571             {
572             int32_t blen;
573              
574 0 0         if (reached_eof) {
575 0           *reached_eof = false;
576             }
577              
578 0 0         if ((reader->offset + 4) < reader->length) {
579 0           memcpy (&blen, &reader->data[reader->offset], sizeof blen);
580 0           blen = BSON_UINT32_FROM_LE (blen);
581              
582 0 0         if (blen < 5) {
583 0           return NULL;
584             }
585              
586 0 0         if (blen > (int32_t)(reader->length - reader->offset)) {
587 0           return NULL;
588             }
589              
590 0 0         if (!bson_init_static (&reader->inline_bson,
591 0           &reader->data[reader->offset], (uint32_t)blen)) {
592 0           return NULL;
593             }
594              
595 0           reader->offset += blen;
596              
597 0           return &reader->inline_bson;
598             }
599              
600 0 0         if (reached_eof) {
601 0           *reached_eof = (reader->offset == reader->length);
602             }
603              
604 0           return NULL;
605             }
606              
607              
608             /*
609             *--------------------------------------------------------------------------
610             *
611             * _bson_reader_data_tell --
612             *
613             * Tell the current position in the underlying buffer.
614             *
615             * Returns:
616             * An off_t of the current offset.
617             *
618             * Side effects:
619             * None.
620             *
621             *--------------------------------------------------------------------------
622             */
623              
624             static off_t
625 0           _bson_reader_data_tell (bson_reader_data_t *reader) /* IN */
626             {
627 0           return (off_t)reader->offset;
628             }
629              
630              
631             /*
632             *--------------------------------------------------------------------------
633             *
634             * bson_reader_destroy --
635             *
636             * Release a bson_reader_t created with bson_reader_new_from_data(),
637             * bson_reader_new_from_fd(), or bson_reader_new_from_handle().
638             *
639             * Returns:
640             * None.
641             *
642             * Side effects:
643             * None.
644             *
645             *--------------------------------------------------------------------------
646             */
647              
648             void
649 0           bson_reader_destroy (bson_reader_t *reader) /* IN */
650             {
651 0 0         BSON_ASSERT (reader);
652              
653 0           switch (reader->type) {
654             case 0:
655 0           break;
656             case BSON_READER_HANDLE:
657             {
658 0           bson_reader_handle_t *handle = (bson_reader_handle_t *)reader;
659              
660 0 0         if (handle->destroy_func) {
661              
662 0           handle->destroy_func(handle->handle);
663             }
664              
665 0           bson_free (handle->data);
666             }
667 0           break;
668             case BSON_READER_DATA:
669 0           break;
670             default:
671 0           fprintf (stderr, "No such reader type: %02x\n", reader->type);
672 0           break;
673             }
674              
675 0           reader->type = 0;
676              
677 0           bson_free (reader);
678 0           }
679              
680              
681             /*
682             *--------------------------------------------------------------------------
683             *
684             * bson_reader_read --
685             *
686             * Reads the next bson_t in the underlying memory or storage. The
687             * resulting bson_t should not be modified or freed. You may copy it
688             * and iterate over it. Functions that take a const bson_t* are safe
689             * to use.
690             *
691             * This structure does not survive calls to bson_reader_read() or
692             * bson_reader_destroy() as it uses memory allocated by the reader or
693             * underlying storage/memory.
694             *
695             * If NULL is returned then @reached_eof will be set to true if the
696             * end of the file or buffer was reached. This indicates if there was
697             * an error parsing the document stream.
698             *
699             * Returns:
700             * A const bson_t that should not be modified or freed.
701             * NULL on failure or end of stream.
702             *
703             * Side effects:
704             * @reached_eof is set if non-NULL.
705             *
706             *--------------------------------------------------------------------------
707             */
708              
709             const bson_t *
710 0           bson_reader_read (bson_reader_t *reader, /* IN */
711             bool *reached_eof) /* OUT */
712             {
713 0 0         BSON_ASSERT (reader);
714              
715 0           switch (reader->type) {
716             case BSON_READER_HANDLE:
717 0           return _bson_reader_handle_read ((bson_reader_handle_t *)reader, reached_eof);
718              
719             case BSON_READER_DATA:
720 0           return _bson_reader_data_read ((bson_reader_data_t *)reader, reached_eof);
721              
722             default:
723 0           fprintf (stderr, "No such reader type: %02x\n", reader->type);
724 0           break;
725             }
726              
727 0           return NULL;
728             }
729              
730              
731             /*
732             *--------------------------------------------------------------------------
733             *
734             * bson_reader_tell --
735             *
736             * Return the current position in the underlying reader. This will
737             * always be at the beginning of a bson document or end of file.
738             *
739             * Returns:
740             * An off_t containing the current offset.
741             *
742             * Side effects:
743             * None.
744             *
745             *--------------------------------------------------------------------------
746             */
747              
748             off_t
749 0           bson_reader_tell (bson_reader_t *reader) /* IN */
750             {
751 0 0         BSON_ASSERT (reader);
752              
753 0           switch (reader->type) {
754             case BSON_READER_HANDLE:
755 0           return _bson_reader_handle_tell ((bson_reader_handle_t *)reader);
756              
757             case BSON_READER_DATA:
758 0           return _bson_reader_data_tell ((bson_reader_data_t *)reader);
759              
760             default:
761 0           fprintf (stderr, "No such reader type: %02x\n", reader->type);
762 0           return -1;
763             }
764             }
765              
766              
767             /*
768             *--------------------------------------------------------------------------
769             *
770             * bson_reader_new_from_file --
771             *
772             * A convenience function to open a file containing sequential
773             * bson documents and read them using bson_reader_t.
774             *
775             * Returns:
776             * A new bson_reader_t if successful, otherwise NULL and
777             * @error is set. Free the non-NULL result with
778             * bson_reader_destroy().
779             *
780             * Side effects:
781             * @error may be set.
782             *
783             *--------------------------------------------------------------------------
784             */
785              
786             bson_reader_t *
787 0           bson_reader_new_from_file (const char *path, /* IN */
788             bson_error_t *error) /* OUT */
789             {
790             char errmsg_buf[BSON_ERROR_BUFFER_SIZE];
791             char *errmsg;
792             int fd;
793              
794 0 0         BSON_ASSERT (path);
795              
796             #ifdef BSON_OS_WIN32
797             if (_sopen_s (&fd, path, (_O_RDONLY | _O_BINARY), _SH_DENYNO, 0) != 0) {
798             fd = -1;
799             }
800             #else
801 0           fd = open (path, O_RDONLY);
802             #endif
803              
804 0 0         if (fd == -1) {
805 0           errmsg = bson_strerror_r (errno, errmsg_buf, sizeof errmsg_buf);
806 0           bson_set_error (error,
807             BSON_ERROR_READER,
808             BSON_ERROR_READER_BADFD,
809             "%s", errmsg);
810 0           return NULL;
811             }
812              
813 0           return bson_reader_new_from_fd (fd, true);
814             }
815              
816              
817             /*
818             *--------------------------------------------------------------------------
819             *
820             * bson_reader_reset --
821             *
822             * Restore the reader to its initial state. Valid only for readers
823             * created with bson_reader_new_from_data.
824             *
825             *--------------------------------------------------------------------------
826             */
827              
828             void
829 0           bson_reader_reset (bson_reader_t *reader)
830             {
831 0           bson_reader_data_t *real = (bson_reader_data_t *) reader;
832              
833 0 0         if (real->type != BSON_READER_DATA) {
834 0           fprintf (stderr, "Reader type cannot be reset\n");
835 0           return;
836             }
837              
838 0           real->offset = 0;
839             }