1 /***************************************************************************
2  begin       : Tue Apr 27 2010
3  copyright   : (C) 2010 by Martin Preuss
4  email       : martin@libchipcard.de
5 
6  ***************************************************************************
7  *                                                                         *
8  *   This library is free software; you can redistribute it and/or         *
9  *   modify it under the terms of the GNU Lesser General Public            *
10  *   License as published by the Free Software Foundation; either          *
11  *   version 2.1 of the License, or (at your option) any later version.    *
12  *                                                                         *
13  *   This library is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
16  *   Lesser General Public License for more details.                       *
17  *                                                                         *
18  *   You should have received a copy of the GNU Lesser General Public      *
19  *   License along with this library; if not, write to the Free Software   *
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
21  *   MA  02111-1307  USA                                                   *
22  *                                                                         *
23  ***************************************************************************/
24 
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #define DISABLE_DEBUGLOG
30 
31 
32 #include "syncio_p.h"
33 #include "syncio_file.h"
34 #include "syncio_buffered.h"
35 
36 #include <gwenhywfar/misc.h>
37 #include <gwenhywfar/debug.h>
38 
39 #include <assert.h>
40 #include <stdlib.h>
41 #include <string.h>
42 
43 
44 
45 GWEN_INHERIT_FUNCTIONS(GWEN_SYNCIO)
GWEN_LIST_FUNCTIONS(GWEN_SYNCIO,GWEN_SyncIo)46 GWEN_LIST_FUNCTIONS(GWEN_SYNCIO, GWEN_SyncIo)
47 
48 
49 
50 
51 GWEN_SYNCIO *GWEN_SyncIo_new(const char *typeName, GWEN_SYNCIO *baseIo)
52 {
53   GWEN_SYNCIO *sio;
54 
55   assert(typeName);
56   GWEN_NEW_OBJECT(GWEN_SYNCIO, sio);
57   sio->refCount=1;
58   GWEN_INHERIT_INIT(GWEN_SYNCIO, sio);
59   GWEN_LIST_INIT(GWEN_SYNCIO, sio);
60 
61   sio->typeName=strdup(typeName);
62   sio->baseIo=baseIo;
63 
64   return sio;
65 }
66 
67 
68 
GWEN_SyncIo_Attach(GWEN_SYNCIO * sio)69 void GWEN_SyncIo_Attach(GWEN_SYNCIO *sio)
70 {
71   assert(sio);
72   assert(sio->refCount);
73   sio->refCount++;
74 }
75 
76 
77 
GWEN_SyncIo_free(GWEN_SYNCIO * sio)78 void GWEN_SyncIo_free(GWEN_SYNCIO *sio)
79 {
80   if (sio) {
81     assert(sio->refCount);
82     if (sio->refCount==1) {
83       GWEN_LIST_FINI(GWEN_SYNCIO, sio);
84       GWEN_INHERIT_FINI(GWEN_SYNCIO, sio);
85       GWEN_SyncIo_free(sio->baseIo);
86       free(sio->typeName);
87       sio->refCount=0;
88       GWEN_FREE_OBJECT(sio);
89     }
90     else
91       sio->refCount--;
92   }
93 }
94 
95 
96 
GWEN_SyncIo_Connect(GWEN_SYNCIO * sio)97 int GWEN_SyncIo_Connect(GWEN_SYNCIO *sio)
98 {
99   assert(sio);
100   assert(sio->refCount);
101   if (sio->connectFn)
102     return sio->connectFn(sio);
103   else
104     return 0;
105 }
106 
107 
108 
GWEN_SyncIo_Disconnect(GWEN_SYNCIO * sio)109 int GWEN_SyncIo_Disconnect(GWEN_SYNCIO *sio)
110 {
111   assert(sio);
112   assert(sio->refCount);
113   if (sio->disconnectFn)
114     return sio->disconnectFn(sio);
115   else
116     return 0;
117 }
118 
119 
120 
GWEN_SyncIo_Flush(GWEN_SYNCIO * sio)121 int GWEN_SyncIo_Flush(GWEN_SYNCIO *sio)
122 {
123   assert(sio);
124   assert(sio->refCount);
125   if (sio->flushFn)
126     return sio->flushFn(sio);
127   else
128     return 0;
129 }
130 
131 
132 
GWEN_SyncIo_Read(GWEN_SYNCIO * sio,uint8_t * buffer,uint32_t size)133 int GWEN_SyncIo_Read(GWEN_SYNCIO *sio,
134                      uint8_t *buffer,
135                      uint32_t size)
136 {
137   assert(sio);
138   assert(sio->refCount);
139   if (sio->readFn)
140     return sio->readFn(sio, buffer, size);
141   else
142     return GWEN_ERROR_EOF;
143 }
144 
145 
146 
GWEN_SyncIo_Write(GWEN_SYNCIO * sio,const uint8_t * buffer,uint32_t size)147 int GWEN_SyncIo_Write(GWEN_SYNCIO *sio,
148                       const uint8_t *buffer,
149                       uint32_t size)
150 {
151   assert(sio);
152   assert(sio->refCount);
153   if (sio->writeFn)
154     return sio->writeFn(sio, buffer, size);
155   else
156     return GWEN_ERROR_BROKEN_PIPE;
157 }
158 
159 
160 
GWEN_SyncIo_GetFlags(const GWEN_SYNCIO * sio)161 uint32_t GWEN_SyncIo_GetFlags(const GWEN_SYNCIO *sio)
162 {
163   assert(sio);
164   assert(sio->refCount);
165   return sio->flags;
166 }
167 
168 
169 
GWEN_SyncIo_SetFlags(GWEN_SYNCIO * sio,uint32_t fl)170 void GWEN_SyncIo_SetFlags(GWEN_SYNCIO *sio, uint32_t fl)
171 {
172   assert(sio);
173   assert(sio->refCount);
174   sio->flags=fl;
175 }
176 
177 
178 
GWEN_SyncIo_AddFlags(GWEN_SYNCIO * sio,uint32_t fl)179 void GWEN_SyncIo_AddFlags(GWEN_SYNCIO *sio, uint32_t fl)
180 {
181   assert(sio);
182   assert(sio->refCount);
183   sio->flags|=fl;
184 }
185 
186 
187 
GWEN_SyncIo_SubFlags(GWEN_SYNCIO * sio,uint32_t fl)188 void GWEN_SyncIo_SubFlags(GWEN_SYNCIO *sio, uint32_t fl)
189 {
190   assert(sio);
191   assert(sio->refCount);
192   sio->flags&=~fl;
193 }
194 
195 
196 
GWEN_SyncIo_GetStatus(const GWEN_SYNCIO * sio)197 GWEN_SYNCIO_STATUS GWEN_SyncIo_GetStatus(const GWEN_SYNCIO *sio)
198 {
199   assert(sio);
200   assert(sio->refCount);
201   return sio->status;
202 }
203 
204 
205 
GWEN_SyncIo_SetStatus(GWEN_SYNCIO * sio,GWEN_SYNCIO_STATUS st)206 void GWEN_SyncIo_SetStatus(GWEN_SYNCIO *sio, GWEN_SYNCIO_STATUS st)
207 {
208   assert(sio);
209   assert(sio->refCount);
210   sio->status=st;
211 }
212 
213 
214 
GWEN_SyncIo_GetTypeName(const GWEN_SYNCIO * sio)215 const char *GWEN_SyncIo_GetTypeName(const GWEN_SYNCIO *sio)
216 {
217   assert(sio);
218   assert(sio->refCount);
219   return sio->typeName;
220 }
221 
222 
223 
GWEN_SyncIo_GetBaseIo(const GWEN_SYNCIO * sio)224 GWEN_SYNCIO *GWEN_SyncIo_GetBaseIo(const GWEN_SYNCIO *sio)
225 {
226   assert(sio);
227   assert(sio->refCount);
228   return sio->baseIo;
229 }
230 
231 
232 
GWEN_SyncIo_GetBaseIoByTypeName(const GWEN_SYNCIO * sio,const char * typeName)233 GWEN_SYNCIO *GWEN_SyncIo_GetBaseIoByTypeName(const GWEN_SYNCIO *sio, const char *typeName)
234 {
235   GWEN_SYNCIO *baseIo;
236 
237   assert(sio);
238   assert(sio->refCount);
239 
240   baseIo=sio->baseIo;
241   while (baseIo) {
242     if (baseIo->typeName && strcasecmp(baseIo->typeName, typeName)==0)
243       return baseIo;
244     baseIo=baseIo->baseIo;
245   }
246 
247   return NULL;
248 }
249 
250 
251 
GWEN_SyncIo_SetConnectFn(GWEN_SYNCIO * sio,GWEN_SYNCIO_CONNECT_FN fn)252 GWEN_SYNCIO_CONNECT_FN GWEN_SyncIo_SetConnectFn(GWEN_SYNCIO *sio, GWEN_SYNCIO_CONNECT_FN fn)
253 {
254   GWEN_SYNCIO_CONNECT_FN of;
255 
256   assert(sio);
257   assert(sio->refCount);
258   of=sio->connectFn;
259   sio->connectFn=fn;
260   return of;
261 }
262 
263 
264 
GWEN_SyncIo_SetDisconnectFn(GWEN_SYNCIO * sio,GWEN_SYNCIO_DISCONNECT_FN fn)265 GWEN_SYNCIO_DISCONNECT_FN GWEN_SyncIo_SetDisconnectFn(GWEN_SYNCIO *sio, GWEN_SYNCIO_DISCONNECT_FN fn)
266 {
267   GWEN_SYNCIO_DISCONNECT_FN of;
268 
269   assert(sio);
270   assert(sio->refCount);
271   of=sio->disconnectFn;
272   sio->disconnectFn=fn;
273   return of;
274 }
275 
276 
277 
GWEN_SyncIo_SetFlushFn(GWEN_SYNCIO * sio,GWEN_SYNCIO_FLUSH_FN fn)278 GWEN_SYNCIO_FLUSH_FN GWEN_SyncIo_SetFlushFn(GWEN_SYNCIO *sio, GWEN_SYNCIO_FLUSH_FN fn)
279 {
280   GWEN_SYNCIO_FLUSH_FN of;
281 
282   assert(sio);
283   assert(sio->refCount);
284   of=sio->flushFn;
285   sio->flushFn=fn;
286   return of;
287 }
288 
289 
290 
GWEN_SyncIo_SetReadFn(GWEN_SYNCIO * sio,GWEN_SYNCIO_READ_FN fn)291 GWEN_SYNCIO_READ_FN GWEN_SyncIo_SetReadFn(GWEN_SYNCIO *sio, GWEN_SYNCIO_READ_FN fn)
292 {
293   GWEN_SYNCIO_READ_FN of;
294 
295   assert(sio);
296   assert(sio->refCount);
297   of=sio->readFn;
298   sio->readFn=fn;
299   return of;
300 }
301 
302 
303 
GWEN_SyncIo_SetWriteFn(GWEN_SYNCIO * sio,GWEN_SYNCIO_WRITE_FN fn)304 GWEN_SYNCIO_WRITE_FN GWEN_SyncIo_SetWriteFn(GWEN_SYNCIO *sio, GWEN_SYNCIO_WRITE_FN fn)
305 {
306   GWEN_SYNCIO_WRITE_FN of;
307 
308   assert(sio);
309   assert(sio->refCount);
310   of=sio->writeFn;
311   sio->writeFn=fn;
312   return of;
313 }
314 
315 
316 
GWEN_SyncIo_WriteForced(GWEN_SYNCIO * sio,const uint8_t * buffer,uint32_t size)317 int GWEN_SyncIo_WriteForced(GWEN_SYNCIO *sio,
318                             const uint8_t *buffer,
319                             uint32_t size)
320 {
321   if (size==0) {
322     int rv;
323 
324     do {
325       rv=GWEN_SyncIo_Write(sio, buffer, size);
326     }
327     while (rv==GWEN_ERROR_INTERRUPTED);
328     if (rv<0) {
329       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
330       return rv;
331     }
332     return 0;
333   }
334   else {
335     uint32_t todo;
336 
337     todo=size;
338     while (todo) {
339       int rv;
340 
341       do {
342         rv=GWEN_SyncIo_Write(sio, buffer, todo);
343       }
344       while (rv==GWEN_ERROR_INTERRUPTED);
345 
346       if (rv<0) {
347         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
348         return rv;
349       }
350       todo-=rv;
351       buffer+=rv;
352     }
353 
354     return size;
355   }
356 }
357 
358 
359 
GWEN_SyncIo_ReadForced(GWEN_SYNCIO * sio,uint8_t * buffer,uint32_t size)360 int GWEN_SyncIo_ReadForced(GWEN_SYNCIO *sio,
361                            uint8_t *buffer,
362                            uint32_t size)
363 {
364   uint32_t todo;
365 
366   todo=size;
367   while (todo) {
368     int rv;
369 
370     do {
371       rv=GWEN_SyncIo_Read(sio, buffer, todo);
372     }
373     while (rv==GWEN_ERROR_INTERRUPTED);
374 
375     if (rv<0) {
376       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
377       return rv;
378     }
379     else if (rv==0) {
380       DBG_ERROR(GWEN_LOGDOMAIN, "EOF met");
381       return GWEN_ERROR_EOF;
382     }
383     todo-=rv;
384     buffer+=rv;
385   }
386 
387   return size;
388 }
389 
390 
391 
GWEN_SyncIo_WriteString(GWEN_SYNCIO * sio,const char * s)392 int GWEN_SyncIo_WriteString(GWEN_SYNCIO *sio, const char *s)
393 {
394   int rv;
395 
396   rv=GWEN_SyncIo_WriteForced(sio, (const uint8_t *) s, s?strlen(s):0);
397   if (rv<0) {
398     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
399     return rv;
400   }
401 
402   return 0;
403 }
404 
405 
406 
GWEN_SyncIo_WriteLine(GWEN_SYNCIO * sio,const char * s)407 int GWEN_SyncIo_WriteLine(GWEN_SYNCIO *sio, const char *s)
408 {
409   int rv;
410 
411   rv=GWEN_SyncIo_WriteString(sio, s);
412   if (rv<0) {
413     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
414     return rv;
415   }
416 
417   if (GWEN_SyncIo_GetFlags(sio) & GWEN_SYNCIO_FLAGS_DOSMODE)
418     rv=GWEN_SyncIo_WriteForced(sio, (const uint8_t *) "\r\n", 2);
419   else
420     rv=GWEN_SyncIo_WriteForced(sio, (const uint8_t *) "\n", 1);
421   if (rv<0) {
422     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
423     return rv;
424   }
425 
426   return 0;
427 }
428 
429 
430 
GWEN_SyncIo_WriteChar(GWEN_SYNCIO * sio,char s)431 int GWEN_SyncIo_WriteChar(GWEN_SYNCIO *sio, char s)
432 {
433   return GWEN_SyncIo_WriteForced(sio, (const uint8_t *) &s, 1);
434 }
435 
436 
437 
GWEN_SyncIo_Helper_ReadFileToStringList(const char * fname,int maxLines,GWEN_STRINGLIST * sl)438 int GWEN_SyncIo_Helper_ReadFileToStringList(const char *fname,
439                                             int maxLines,
440                                             GWEN_STRINGLIST *sl)
441 {
442   GWEN_SYNCIO *sio;
443   GWEN_SYNCIO *baseSio;
444   int rv;
445 
446   /* open checksums from file */
447   baseSio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_OpenExisting);
448   GWEN_SyncIo_SetFlags(baseSio, GWEN_SYNCIO_FILE_FLAGS_READ);
449   sio=GWEN_SyncIo_Buffered_new(baseSio);
450 
451   rv=GWEN_SyncIo_Connect(sio);
452   if (rv<0) {
453     DBG_INFO(GWEN_LOGDOMAIN, "Could not open file [%s]", fname?fname:"<no filename>");
454     GWEN_SyncIo_free(sio);
455     return rv;
456   }
457 
458   /* read up to maxlines lines from file */
459   rv=GWEN_SyncIo_Buffered_ReadLinesToStringList(sio, maxLines, sl);
460   if (rv<0) {
461     DBG_INFO(GWEN_LOGDOMAIN, "Could not open file [%s]", fname?fname:"<no filename>");
462     GWEN_SyncIo_Disconnect(sio);
463     GWEN_SyncIo_free(sio);
464     return rv;
465   }
466 
467   /* close file */
468   GWEN_SyncIo_Disconnect(sio);
469   GWEN_SyncIo_free(sio);
470   return 0;
471 }
472 
473 
474 
475 
GWEN_SyncIo_Helper_PartiallyReadFile(const char * fName,uint8_t * buffer,uint32_t size)476 int GWEN_SyncIo_Helper_PartiallyReadFile(const char *fName, uint8_t *buffer, uint32_t size)
477 {
478   GWEN_SYNCIO *sio;
479   uint32_t todo;
480   int rv;
481 
482   /* open file */
483   sio=GWEN_SyncIo_File_new(fName, GWEN_SyncIo_File_CreationMode_OpenExisting);
484   GWEN_SyncIo_SetFlags(sio, GWEN_SYNCIO_FILE_FLAGS_READ);
485 
486   rv=GWEN_SyncIo_Connect(sio);
487   if (rv<0) {
488     DBG_INFO(GWEN_LOGDOMAIN, "Could not open file [%s]", fName?fName:"<no filename>");
489     GWEN_SyncIo_free(sio);
490     return rv;
491   }
492 
493   /* read file */
494   todo=size;
495   while (todo) {
496     do {
497       rv=GWEN_SyncIo_Read(sio, buffer, todo);
498     }
499     while (rv==GWEN_ERROR_INTERRUPTED);
500 
501     if (rv<0) {
502       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
503       GWEN_SyncIo_Disconnect(sio);
504       GWEN_SyncIo_free(sio);
505       return rv;
506     }
507     else if (rv==0) {
508       DBG_INFO(GWEN_LOGDOMAIN, "EOF met");
509       break;
510     }
511     todo-=rv;
512     buffer+=rv;
513   }
514 
515   /* close file */
516   GWEN_SyncIo_Disconnect(sio);
517   GWEN_SyncIo_free(sio);
518 
519   return size-todo;
520 }
521 
522 
523 
GWEN_SyncIo_Helper_ReadFile(const char * fName,GWEN_BUFFER * dbuf)524 int GWEN_SyncIo_Helper_ReadFile(const char *fName, GWEN_BUFFER *dbuf)
525 {
526   GWEN_SYNCIO *sio;
527   int rv;
528   int bytesRead=0;
529   int64_t fileSize=0;
530 
531   /* open file */
532   sio=GWEN_SyncIo_File_new(fName, GWEN_SyncIo_File_CreationMode_OpenExisting);
533   GWEN_SyncIo_SetFlags(sio, GWEN_SYNCIO_FILE_FLAGS_READ);
534 
535   rv=GWEN_SyncIo_Connect(sio);
536   if (rv<0) {
537     DBG_INFO(GWEN_LOGDOMAIN, "Could not open file [%s]", fName?fName:"<no filename>");
538     GWEN_SyncIo_free(sio);
539     return rv;
540   }
541 
542   fileSize=GWEN_SyncIo_File_Seek(sio, 0, GWEN_SyncIo_File_Whence_End);
543   GWEN_SyncIo_File_Seek(sio, 0, GWEN_SyncIo_File_Whence_Set);
544   if (fileSize>GWEN_Buffer_GetMaxUnsegmentedWrite(dbuf))
545     GWEN_Buffer_AllocRoom(dbuf, (uint32_t) fileSize);
546 
547   /* read file */
548   while (1) {
549     uint32_t l;
550     uint8_t *p;
551 
552     GWEN_Buffer_AllocRoom(dbuf, 4096);
553     l=GWEN_Buffer_GetMaxUnsegmentedWrite(dbuf);
554     p=(uint8_t *) GWEN_Buffer_GetPosPointer(dbuf);
555 
556     do {
557       rv=GWEN_SyncIo_Read(sio, p, l);
558     }
559     while (rv==GWEN_ERROR_INTERRUPTED);
560 
561     if (rv<0) {
562       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
563       GWEN_SyncIo_Disconnect(sio);
564       GWEN_SyncIo_free(sio);
565       return rv;
566     }
567     else if (rv==0) {
568       DBG_INFO(GWEN_LOGDOMAIN, "EOF met");
569       break;
570     }
571     bytesRead+=rv;
572 
573     GWEN_Buffer_IncrementPos(dbuf, rv);
574     GWEN_Buffer_AdjustUsedBytes(dbuf);
575   }
576 
577   /* close file */
578   GWEN_SyncIo_Disconnect(sio);
579   GWEN_SyncIo_free(sio);
580 
581   return bytesRead;
582 }
583 
584 
585 
GWEN_SyncIo_Helper_WriteFile(const char * fName,const uint8_t * ptrSource,uint64_t lenSource)586 int GWEN_SyncIo_Helper_WriteFile(const char *fName, const uint8_t *ptrSource, uint64_t lenSource)
587 {
588   GWEN_SYNCIO *sio;
589   int rv;
590   int64_t bytesWritten=0;
591   int64_t bytesLeft;
592 
593   /* open file */
594   sio=GWEN_SyncIo_File_new(fName, GWEN_SyncIo_File_CreationMode_CreateNew);
595   GWEN_SyncIo_SetFlags(sio,
596                        GWEN_SYNCIO_FILE_FLAGS_WRITE | GWEN_SYNCIO_FILE_FLAGS_READ |
597                        GWEN_SYNCIO_FILE_FLAGS_UREAD | GWEN_SYNCIO_FILE_FLAGS_UWRITE);
598 
599   rv=GWEN_SyncIo_Connect(sio);
600   if (rv<0) {
601     DBG_INFO(GWEN_LOGDOMAIN, "Could not open file [%s]", fName?fName:"<no filename>");
602     GWEN_SyncIo_free(sio);
603     return rv;
604   }
605 
606   /* write file */
607   bytesLeft=lenSource;
608   while (bytesLeft>0) {
609     do {
610       rv=GWEN_SyncIo_Write(sio, ptrSource, bytesLeft);
611     }
612     while (rv==GWEN_ERROR_INTERRUPTED);
613 
614     if (rv<0) {
615       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
616       GWEN_SyncIo_Disconnect(sio);
617       GWEN_SyncIo_free(sio);
618       return rv;
619     }
620     else if (rv==0) {
621       DBG_INFO(GWEN_LOGDOMAIN, "Nothing written");
622       GWEN_SyncIo_Disconnect(sio);
623       GWEN_SyncIo_free(sio);
624       return GWEN_ERROR_IO;
625     }
626     ptrSource+=rv;
627     bytesWritten+=rv;
628     bytesLeft-=rv;
629   }
630 
631   /* close file */
632   GWEN_SyncIo_Disconnect(sio);
633   GWEN_SyncIo_free(sio);
634 
635   return bytesWritten;
636 }
637 
638 
639 
640 
641