1 /************************************************************************/
2 /* */
3 /* Simple io streams using raw file IO. */
4 /* */
5 /************************************************************************/
6
7 # include "appUtilConfig.h"
8
9 # include "sioFileio.h"
10 # include "sioFd.h"
11 # include "sioStdin.h"
12 # include "sioStdout.h"
13
14 # include <appDebugon.h>
15 # include <unistd.h>
16 # include <errno.h>
17 # include <string.h>
18 # include <stdlib.h>
19 # include <fcntl.h>
20
21 typedef struct FileIo
22 {
23 int fiFd;
24 int fiOwnFd;
25 } FileIo;
26
sioFileioClose(void * vfi)27 static int sioFileioClose( void * vfi )
28 {
29 FileIo * fi= (FileIo *)vfi;
30 int rval= 0;
31
32 if ( fi->fiOwnFd )
33 {
34 rval= close( fi->fiFd );
35 if ( rval != 0 )
36 { LLSDEB(fi->fiFd,errno,strerror(errno)); }
37 }
38
39 free( vfi );
40
41 return rval;
42 }
43
sioFdCloseFile(int fd)44 int sioFdCloseFile( int fd )
45 {
46 int rval= close( fd );
47 if ( rval != 0 )
48 { LLSDEB(fd,errno,strerror(errno)); }
49
50 return rval;
51 }
52
sioInFileioReadBytes(void * vfi,unsigned char * buffer,unsigned int count)53 static int sioInFileioReadBytes( void * vfi,
54 unsigned char * buffer,
55 unsigned int count )
56 {
57 FileIo * fi= (FileIo *)vfi;
58 int rval= read( fi->fiFd, buffer, count );
59
60 if ( rval < 0 )
61 { LLSDEB(fi->fiFd,errno,strerror(errno)); }
62
63 return rval;
64 }
65
sioFdOpenFileS(const char * filename,int read,int write,int append,int create,int exclusive)66 static int sioFdOpenFileS( const char * filename,
67 int read,
68 int write,
69 int append,
70 int create,
71 int exclusive )
72 {
73 int fd= -1;
74 int flags= 0;
75
76 if ( write )
77 {
78 if ( read )
79 {
80 flags= O_RDWR;
81
82 if ( append )
83 { flags |= O_APPEND; }
84 }
85 else{
86 flags= O_WRONLY;
87 if ( append )
88 { flags |= O_APPEND; }
89 else{ flags |= O_TRUNC; }
90 }
91
92 if ( create )
93 {
94 flags |= O_CREAT;
95
96 if ( exclusive )
97 { flags |= O_EXCL; }
98 }
99 else{
100 if ( exclusive )
101 { LLDEB(create,exclusive); return -1; }
102 }
103 }
104 else{
105 if ( create )
106 { LLDEB(write,create); return -1; }
107 if ( exclusive )
108 { LLDEB(write,exclusive); return -1; }
109
110 flags= O_RDONLY;
111 }
112
113 # ifdef O_BINARY
114 flags |= O_BINARY;
115 # endif
116
117 fd= open( filename, flags, 0666 );
118 if ( fd < 0 )
119 {
120 switch( errno )
121 {
122 case EPERM:
123 return FDerrPERM;
124 case ENOENT:
125 return FDerrNOENT;
126 case EEXIST:
127 return FDerrEXIST;
128 case EACCES:
129 return FDerrACCES;
130 case EISDIR:
131 return FDerrISDIR;
132 default:
133 SLSDEB(filename,errno,strerror(errno));
134 return FDerrOTHER;
135 }
136 }
137
138 return fd;
139 }
140
sioFdOpenFile(const MemoryBuffer * filename,int read,int write,int append,int create,int exclusive)141 int sioFdOpenFile( const MemoryBuffer * filename,
142 int read,
143 int write,
144 int append,
145 int create,
146 int exclusive )
147 {
148 if ( ! filename || filename->mbSize <= 0 )
149 { XDEB(filename); return FDerrOTHER; }
150
151 return sioFdOpenFileS( utilMemoryBufferGetString( filename ),
152 read, write, append, create, exclusive );
153 }
154
sioInFileioOpenS(const char * filename)155 SimpleInputStream * sioInFileioOpenS( const char * filename )
156 {
157 SimpleInputStream * sis= (SimpleInputStream *)0;
158 FileIo * fi= malloc( sizeof(FileIo) );
159
160 const int read= 1;
161 const int write= 0;
162 const int create= 0;
163 const int append= 0;
164 const int exclusive= 0;
165
166 if ( ! fi )
167 { XDEB(fi); goto ready; }
168
169 fi->fiOwnFd= 0;
170 fi->fiFd= sioFdOpenFileS( filename,
171 read, write, append, create, exclusive );
172 if ( fi->fiFd < 0 )
173 { SLDEB(filename,fi->fiFd); goto ready; }
174 fi->fiOwnFd= 1;
175
176 sis= sioInOpen( (void *)fi, sioInFileioReadBytes, sioFileioClose );
177 if ( ! sis )
178 { XDEB(sis); goto ready; }
179
180 fi= (FileIo *)0; /* steal */
181
182 ready:
183
184 if ( fi )
185 { sioFileioClose( fi ); }
186
187 return sis;
188 }
189
sioInFileioOpen(const MemoryBuffer * filename)190 SimpleInputStream * sioInFileioOpen( const MemoryBuffer * filename )
191 {
192 return sioInFileioOpenS( utilMemoryBufferGetString( filename ) );
193 }
194
sioOutFileioWriteBytes(void * vfi,const unsigned char * buffer,int count)195 static int sioOutFileioWriteBytes( void * vfi,
196 const unsigned char * buffer,
197 int count )
198 {
199 FileIo * fi= (FileIo *)vfi;
200 int rval= write( fi->fiFd, buffer, count );
201
202 if ( rval < 0 )
203 { LLSDEB(fi->fiFd,errno,strerror(errno)); }
204
205 return rval;
206 }
207
sioOutFileioOpenSAt(const char * filename,int append,long offset)208 static SimpleOutputStream * sioOutFileioOpenSAt( const char * filename,
209 int append,
210 long offset )
211 {
212 SimpleOutputStream * sos= (SimpleOutputStream *)0;
213 FileIo * fi= malloc( sizeof(FileIo) );
214 int flags= O_CREAT|O_WRONLY;
215 const int mode= 0666;
216
217 # ifdef O_BINARY
218 flags |= O_BINARY;
219 # endif
220
221 if ( ! fi )
222 { XDEB(fi); goto ready; }
223
224 if ( append )
225 { flags |= O_APPEND; }
226 else{
227 if ( offset == 0 )
228 { flags |= O_TRUNC; }
229 }
230
231 fi->fiOwnFd= 0;
232 fi->fiFd= open( filename, flags, mode );
233 if ( fi->fiFd < 0 )
234 { SLSDEB(filename,errno,strerror(errno)); goto ready; }
235 fi->fiOwnFd= 1;
236
237 if ( ! append && offset > 0 )
238 {
239 if ( ftruncate( fi->fiFd, offset ) )
240 { SLSDEB(filename,errno,strerror(errno)); goto ready; }
241
242 if ( lseek( fi->fiFd, offset, SEEK_SET ) != offset )
243 { SLSDEB(filename,errno,strerror(errno)); goto ready; }
244 }
245
246 sos= sioOutOpen( (void *)fi, sioOutFileioWriteBytes, sioFileioClose );
247 if ( ! sos )
248 { XDEB(sos); goto ready; }
249
250 fi= (FileIo *)0; /* steal */
251
252 ready:
253
254 if ( fi )
255 { sioFileioClose( fi ); }
256
257 return sos;
258 }
259
sioOutFileioOpenS(const char * filename)260 SimpleOutputStream * sioOutFileioOpenS( const char * filename )
261 {
262 const int append= 0;
263 const long offset= 0L;
264
265 return sioOutFileioOpenSAt( filename, append, offset );
266 }
267
sioOutFileioOpen(const MemoryBuffer * filename)268 SimpleOutputStream * sioOutFileioOpen( const MemoryBuffer * filename )
269 {
270 const int append= 0;
271 const long offset= 0L;
272
273 return sioOutFileioOpenSAt( utilMemoryBufferGetString( filename ),
274 append, offset );
275 }
276
sioOutFileioOpenForAppend(const MemoryBuffer * filename)277 SimpleOutputStream * sioOutFileioOpenForAppend(
278 const MemoryBuffer * filename )
279 {
280 const int append= 1;
281 const long offset= 0L;
282
283 return sioOutFileioOpenSAt( utilMemoryBufferGetString( filename ),
284 append, offset );
285 }
286
287 /************************************************************************/
288 /* */
289 /* Simple output stream to a particular file descriptor. */
290 /* */
291 /************************************************************************/
292
sioOutFdOpenAtX(int fd,int seek,long offset)293 static SimpleOutputStream * sioOutFdOpenAtX(
294 int fd,
295 int seek,
296 long offset )
297 {
298 SimpleOutputStream * sos= (SimpleOutputStream *)0;
299 FileIo * fi= malloc( sizeof(FileIo) );
300
301 if ( ! fi )
302 { XDEB(fi); goto ready; }
303
304 fi->fiOwnFd= 0;
305 fi->fiFd= fd;
306
307 if ( seek )
308 {
309 if ( lseek( fi->fiFd, offset, SEEK_SET ) != offset )
310 { LLLSDEB(fi->fiFd,offset,errno,strerror(errno)); goto ready; }
311
312 if ( ftruncate( fi->fiFd, offset ) )
313 { LLSDEB(offset,errno,strerror(errno)); goto ready; }
314 }
315
316 sos= sioOutOpen( (void *)fi, sioOutFileioWriteBytes, sioFileioClose );
317 if ( ! sos )
318 { XDEB(sos); goto ready; }
319
320 fi= (FileIo *)0; /* steal */
321
322 ready:
323
324 if ( fi )
325 { sioFileioClose( fi ); }
326
327 return sos;
328 }
329
sioOutFdOpenAt(int fd,long offset)330 SimpleOutputStream * sioOutFdOpenAt( int fd,
331 long offset )
332 {
333 int seek= 1;
334
335 return sioOutFdOpenAtX( fd, seek, offset );
336 }
337
sioOutFdOpen(int fd)338 SimpleOutputStream * sioOutFdOpen( int fd )
339 {
340 int seek= 0;
341 long offset= 0;
342
343 return sioOutFdOpenAtX( fd, seek, offset );
344 }
345
346 /************************************************************************/
347 /* */
348 /* Simple input stream from a particular file descriptor. */
349 /* */
350 /************************************************************************/
351
sioInFdOpenAt(int fd,long offset)352 SimpleInputStream * sioInFdOpenAt( int fd,
353 long offset )
354 {
355 SimpleInputStream * sis= (SimpleInputStream *)0;
356 FileIo * fi= malloc( sizeof(FileIo) );
357
358 if ( ! fi )
359 { XDEB(fi); goto ready; }
360
361 fi->fiOwnFd= 0;
362 fi->fiFd= fd;
363
364 if ( lseek( fi->fiFd, offset, SEEK_SET ) != offset )
365 { LLSDEB(offset,errno,strerror(errno)); goto ready; }
366
367 sis= sioInOpen( (void *)fi, sioInFileioReadBytes, sioFileioClose );
368 if ( ! sis )
369 { XDEB(sis); goto ready; }
370
371 fi= (FileIo *)0; /* steal */
372
373 ready:
374
375 if ( fi )
376 { sioFileioClose( fi ); }
377
378 return sis;
379 }
380
sioInFdOpen(int fd)381 SimpleInputStream * sioInFdOpen( int fd )
382 {
383 const long offset= 0;
384
385 return sioInFdOpenAt( fd, offset );
386 }
387
388 /************************************************************************/
389 /* */
390 /* Make a temporary file and return an output stream for it. */
391 /* */
392 /************************************************************************/
393
sioOutFileioOpenTempFile(MemoryBuffer * filename,const char * template)394 SimpleOutputStream * sioOutFileioOpenTempFile(
395 MemoryBuffer * filename,
396 const char * template )
397 {
398 int fd;
399 SimpleOutputStream * sos= (SimpleOutputStream *)0;
400
401 if ( utilMemoryBufferSetString( filename, template ) )
402 { SDEB(template); return (SimpleOutputStream *)0; }
403
404 /* This is known and intended to scribble */
405 fd= mkstemp( (char *)utilMemoryBufferGetString( filename ) );
406 if ( fd < 0 )
407 { LDEB(fd); return (SimpleOutputStream *)0; }
408
409 sos= sioOutFdOpen( fd );
410 if ( ! sos )
411 {
412 if ( close( fd ) )
413 { LLDEB(fd,errno); }
414
415 if ( unlink( utilMemoryBufferGetString( filename ) ) )
416 { LLDEB(fd,errno); }
417 }
418
419 return sos;
420 }
421
422 /************************************************************************/
423 /* */
424 /* Simple input stream from 'stdin' */
425 /* */
426 /************************************************************************/
427
sioInStdinOpen(void)428 SimpleInputStream * sioInStdinOpen( void )
429 {
430 return sioInFdOpen( 0 );
431 }
432
433 /************************************************************************/
434 /* */
435 /* Simple output stream to 'stdout' */
436 /* */
437 /************************************************************************/
438
sioOutStdoutOpen(void)439 SimpleOutputStream * sioOutStdoutOpen( void )
440 {
441 int seek= 0;
442 long offset= 0;
443
444 return sioOutFdOpenAtX( 1, seek, offset );
445 }
446