Kannel: Open Source WAP and SMS gateway  svn-r5335
wsstream_file.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  *
59  * wsstream_file.c
60  *
61  * Author: Markku Rossi <mtr@iki.fi>
62  *
63  * Copyright (c) 1999-2000 WAPIT OY LTD.
64  * All rights reserved.
65  *
66  * Implementation of the file stream.
67  *
68  */
69 
70 #include "wsint.h"
71 
72 /********************* Types and definitions ****************************/
73 
75 {
76  FILE *fp;
77 
78  /* Should the `fp' be closed when the stream is closed. */
80 
81  /* A temporary buffer for the raw file data. */
82  unsigned char buf[WS_STREAM_BUFFER_SIZE];
83 
84  /* For file output streams, this variable holds the number of data
85  in `buf'. */
86  size_t data_in_buf;
87 
88  /* Other fields (like character set conversion information) might be
89  defined later. */
90 };
91 
93 
94 /********************* Static method functions **************************/
95 
96 static size_t file_input(void *context, WsUInt32 *buf, size_t buflen)
97 {
99  size_t read = 0;
100 
101  while (buflen > 0) {
102  size_t toread = buflen < sizeof(ctx->buf) ? buflen : sizeof(ctx->buf);
103  size_t got, i;
104 
105  got = fread(ctx->buf, 1, toread, ctx->fp);
106 
107  /* Convert the data to the stream's IO buffer. */
108  for (i = 0; i < got; i++)
109  buf[i] = ctx->buf[i];
110 
111  buflen -= got;
112  buf += got;
113  read += got;
114 
115  if (got < toread)
116  /* EOF seen. */
117  break;
118  }
119 
120  return read;
121 }
122 
123 
124 static size_t file_output(void *context, WsUInt32 *buf, size_t buflen)
125 {
127  size_t wrote = 0;
128  unsigned char ch;
129 
130  while (buflen) {
131  /* Do we have any space in the stream's internal IO buffer? */
132  if (ctx->data_in_buf >= WS_STREAM_BUFFER_SIZE) {
133  size_t w;
134 
135  /* No, flush something to our file stream. */
136  w = fwrite(ctx->buf, 1, ctx->data_in_buf, ctx->fp);
137  if (w < ctx->data_in_buf) {
138  /* Write failed. As a result code we return the number
139  of characters written from our current write
140  request. */
141  ctx->data_in_buf = 0;
142  return wrote;
143  }
144 
145  ctx->data_in_buf = 0;
146  }
147  /* Now we have space in the internal buffer. */
148 
149  /* Here we could perform some sort of conversions from ISO 10646
150  to the output character set. Currently we just support
151  ISO-8859/1 and all unknown characters are replaced with
152  '?'. */
153 
154  if (*buf > 0xff)
155  ch = '?';
156  else
157  ch = (unsigned char) * buf;
158 
159  ctx->buf[ctx->data_in_buf++] = ch;
160 
161  /* Move forward. */
162  buf++;
163  buflen--;
164  wrote++;
165  }
166 
167  return wrote;
168 }
169 
170 
171 static WsBool file_flush(void *context)
172 {
174 
175  /* If the internal buffer has any data, then this stream must be an
176  output stream. The variable `data_in_buf' is not updated on
177  input streams. */
178  if (ctx->data_in_buf) {
179  if (fwrite(ctx->buf, 1, ctx->data_in_buf, ctx->fp) != ctx->data_in_buf) {
180  /* The write failed. */
181  ctx->data_in_buf = 0;
182  return WS_FALSE;
183  }
184 
185  /* The temporary buffer is not empty. */
186  ctx->data_in_buf = 0;
187  }
188 
189  /* Flush the underlying file stream. */
190  return fflush(ctx->fp) == 0;
191 }
192 
193 
194 static void file_close(void *context)
195 {
197 
198  if (ctx->close_fp)
199  fclose(ctx->fp);
200 
201  ws_free(ctx);
202 }
203 
204 /********************* Global functions *********************************/
205 
207 {
208  WsStreamFileCtx *ctx = ws_calloc(1, sizeof(*ctx));
209  WsStream *stream;
210 
211  if (ctx == NULL)
212  return NULL;
213 
214  ctx->fp = fp;
215  ctx->close_fp = close;
216 
217  if (output)
219  else
221 
222  if (stream == NULL)
223  /* The stream creation failed. Close the stream context. */
224  file_close(ctx);
225 
226  return stream;
227 }
void * ws_calloc(size_t num, size_t size)
Definition: wsalloc.c:83
Definition: parse.c:65
unsigned long WsUInt32
Definition: wsint.h:122
#define WS_STREAM_BUFFER_SIZE
Definition: wsstream.h:78
void ws_free(void *ptr)
Definition: wsalloc.c:139
static size_t file_input(void *context, WsUInt32 *buf, size_t buflen)
Definition: wsstream_file.c:96
WsStream * ws_stream_new(void *context, WsStreamIOProc io, WsStreamFlushProc flush, WsStreamCloseProc close)
Definition: wsstream.c:126
static size_t file_output(void *context, WsUInt32 *buf, size_t buflen)
WsBool
Definition: wsint.h:128
static void file_close(void *context)
WsStream * ws_stream_new_file(FILE *fp, WsBool output, WsBool close)
unsigned char buf[WS_STREAM_BUFFER_SIZE]
Definition: wsstream_file.c:82
static WsBool file_flush(void *context)
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.