1 /* -*- c++ -*- */
2 /*
3 * Copyright 2004,2005,2013 Free Software Foundation, Inc.
4 *
5 * This file is part of GNU Radio
6 *
7 * GNU Radio is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
10 * any later version.
11 *
12 * GNU Radio is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Radio; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include "file_descriptor_source_impl.h"
28 #include <gnuradio/io_signature.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #include <cstdio>
36 #include <stdexcept>
37
38 #ifdef HAVE_IO_H
39 #include <io.h>
40 #endif
41
42 namespace gr {
43 namespace blocks {
44
45 file_descriptor_source::sptr
make(size_t itemsize,int fd,bool repeat)46 file_descriptor_source::make(size_t itemsize, int fd, bool repeat)
47 {
48 return gnuradio::get_initial_sptr(
49 new file_descriptor_source_impl(itemsize, fd, repeat));
50 }
51
file_descriptor_source_impl(size_t itemsize,int fd,bool repeat)52 file_descriptor_source_impl::file_descriptor_source_impl(size_t itemsize,
53 int fd,
54 bool repeat)
55 : sync_block("file_descriptor_source",
56 io_signature::make(0, 0, 0),
57 io_signature::make(1, 1, itemsize)),
58 d_itemsize(itemsize),
59 d_fd(fd),
60 d_repeat(repeat),
61 d_residue(new unsigned char[itemsize]),
62 d_residue_len(0)
63 {
64 }
65
~file_descriptor_source_impl()66 file_descriptor_source_impl::~file_descriptor_source_impl()
67 {
68 close(d_fd);
69 delete[] d_residue;
70 }
71
read_items(char * buf,int nitems)72 int file_descriptor_source_impl::read_items(char* buf, int nitems)
73 {
74 assert(nitems > 0);
75 assert(d_residue_len < d_itemsize);
76
77 int nbytes_read = 0;
78
79 if (d_residue_len > 0) {
80 memcpy(buf, d_residue, d_residue_len);
81 nbytes_read = d_residue_len;
82 d_residue_len = 0;
83 }
84
85 int r = read(d_fd, buf + nbytes_read, nitems * d_itemsize - nbytes_read);
86 if (r <= 0) {
87 handle_residue(buf, nbytes_read);
88 return r;
89 }
90
91 r = handle_residue(buf, r + nbytes_read);
92
93 if (r == 0) // block until we get something
94 return read_items(buf, nitems);
95
96 return r;
97 }
98
handle_residue(char * buf,int nbytes_read)99 int file_descriptor_source_impl::handle_residue(char* buf, int nbytes_read)
100 {
101 assert(nbytes_read >= 0);
102 int nitems_read = nbytes_read / d_itemsize;
103 d_residue_len = nbytes_read % d_itemsize;
104 if (d_residue_len > 0) {
105 // fprintf (stderr, "handle_residue: %d\n", d_residue_len);
106 memcpy(d_residue, buf + nbytes_read - d_residue_len, d_residue_len);
107 }
108 return nitems_read;
109 }
110
work(int noutput_items,gr_vector_const_void_star & input_items,gr_vector_void_star & output_items)111 int file_descriptor_source_impl::work(int noutput_items,
112 gr_vector_const_void_star& input_items,
113 gr_vector_void_star& output_items)
114 {
115 assert(noutput_items > 0);
116
117 char* o = (char*)output_items[0];
118 int nread = 0;
119
120 while (1) {
121 int r = read_items(o, noutput_items - nread);
122 if (r == -1) {
123 if (errno == EINTR)
124 continue;
125 else {
126 perror("file_descriptor_source[read]");
127 return -1;
128 }
129 } else if (r == 0) { // end of file
130 if (!d_repeat)
131 break;
132 else {
133 flush_residue();
134 if (lseek(d_fd, 0, SEEK_SET) == -1) {
135 perror("file_descriptor_source[lseek]");
136 return -1;
137 }
138 }
139 } else {
140 o += r * d_itemsize;
141 nread += r;
142 break;
143 }
144 }
145
146 if (nread == 0) // EOF
147 return -1;
148
149 return nread;
150 }
151
152 } /* namespace blocks */
153 } /* namespace gr */
154