Imported Upstream version 3.0
[debian/gnuradio] / gnuradio-core / src / lib / io / gr_file_sink.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2004,2006 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 2, 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 <gr_file_sink.h>
28 #include <gr_io_signature.h>
29 #include <cstdio>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 #include <stdexcept>
34
35 // win32 (mingw/msvc) specific
36 #ifdef HAVE_IO_H
37 #include <io.h>
38 #endif
39 #ifdef O_BINARY
40 #define OUR_O_BINARY O_BINARY
41 #else
42 #define OUR_O_BINARY 0
43 #endif
44
45 // should be handled via configure
46 #ifdef O_LARGEFILE
47 #define OUR_O_LARGEFILE O_LARGEFILE
48 #else
49 #define OUR_O_LARGEFILE 0
50 #endif
51
52 gr_file_sink::gr_file_sink(size_t itemsize, const char *filename)
53   : gr_sync_block ("file_sink",
54                    gr_make_io_signature(1, 1, itemsize),
55                    gr_make_io_signature(0, 0, 0)),
56     d_itemsize(itemsize), d_fp(0), d_new_fp(0), d_updated(false)
57 {
58   if (!open(filename))
59     throw std::runtime_error ("can't open file");
60 }
61
62 gr_file_sink_sptr
63 gr_make_file_sink (size_t itemsize, const char *filename)
64 {
65   return gr_file_sink_sptr (new gr_file_sink (itemsize, filename));
66 }
67
68 gr_file_sink::~gr_file_sink ()
69 {
70   close();
71   if (d_fp){
72     fclose((FILE *) d_fp);
73     d_fp = 0;
74   }
75 }
76
77 bool
78 gr_file_sink::open(const char *filename)
79 {
80   omni_mutex_lock       l(d_mutex);     // hold mutex for duration of this function
81
82   // we use the open system call to get access to the O_LARGEFILE flag.
83   int fd;
84   if ((fd = ::open (filename,
85                     O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY, 0664)) < 0){
86     perror (filename);
87     return false;
88   }
89
90   if (d_new_fp){                // if we've already got a new one open, close it
91     fclose((FILE *) d_new_fp);
92     d_new_fp = 0;
93   }
94
95   if ((d_new_fp = fdopen (fd, "wb")) == NULL){
96     perror (filename);
97     ::close(fd);                // don't leak file descriptor if fdopen fails.
98   }
99
100   d_updated = true;
101   return d_new_fp != 0;
102 }
103
104 void
105 gr_file_sink::close()
106 {
107   omni_mutex_lock       l(d_mutex);     // hold mutex for duration of this function
108
109   if (d_new_fp){
110     fclose((FILE *) d_new_fp);
111     d_new_fp = 0;
112   }
113   d_updated = true;
114 }
115
116 int 
117 gr_file_sink::work (int noutput_items,
118                     gr_vector_const_void_star &input_items,
119                     gr_vector_void_star &output_items)
120 {
121   char *inbuf = (char *) input_items[0];
122   int  nwritten = 0;
123
124   if (d_updated){
125     omni_mutex_lock     l(d_mutex);     // hold mutex for duration of this block
126     if (d_fp)
127       fclose((FILE *)d_fp);
128     d_fp = d_new_fp;                    // install new file pointer
129     d_new_fp = 0;
130     d_updated = false;
131   }
132   
133   if (!d_fp)
134     return noutput_items;               // drop output on the floor
135
136   while (nwritten < noutput_items){
137     int count = fwrite (inbuf, d_itemsize, noutput_items - nwritten, (FILE *) d_fp);
138     if (count == 0)     // FIXME add error handling
139       break;
140     nwritten += count;
141     inbuf += count * d_itemsize;
142   }
143   return nwritten;
144 }