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