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