00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028
00029
00030 #include "sar_p.h"
00031 #include "gwen_sar_fileheader_l.h"
00032 #include "i18n_l.h"
00033
00034 #include <gwenhywfar/misc.h>
00035 #include <gwenhywfar/debug.h>
00036 #include <gwenhywfar/tlv.h>
00037 #include <gwenhywfar/gui.h>
00038 #include <gwenhywfar/text.h>
00039 #include <gwenhywfar/cryptmgrkeys.h>
00040
00041 #include <sys/types.h>
00042 #include <sys/stat.h>
00043 #include <unistd.h>
00044
00045 #include <errno.h>
00046 #include <string.h>
00047
00048
00049
00050 GWEN_SAR *GWEN_Sar_new(void) {
00051 GWEN_SAR *sr;
00052
00053 GWEN_NEW_OBJECT(GWEN_SAR, sr);
00054 sr->refCount=1;
00055
00056 sr->headers=GWEN_SarFileHeader_List_new();
00057
00058 return sr;
00059 }
00060
00061
00062
00063 void GWEN_Sar_Attach(GWEN_SAR *sr) {
00064 assert(sr);
00065 assert(sr->refCount);
00066 sr->refCount++;
00067 }
00068
00069
00070
00071 void GWEN_Sar_free(GWEN_SAR *sr) {
00072 if (sr) {
00073 assert(sr->refCount);
00074 if (sr->refCount==1) {
00075 free(sr->archiveName);
00076 GWEN_SarFileHeader_List_free(sr->headers);
00077 GWEN_SyncIo_free(sr->archiveSio);
00078 sr->refCount=0;
00079 GWEN_FREE_OBJECT(sr);
00080 }
00081 else {
00082 sr->refCount--;
00083 }
00084 }
00085 }
00086
00087
00088
00089 int GWEN_Sar_CreateArchive(GWEN_SAR *sr, const char *aname) {
00090 GWEN_SYNCIO *sio;
00091 int rv;
00092
00093 assert(sr);
00094 assert(sr->refCount);
00095
00096 assert(aname);
00097 if (sr->openMode!=GWEN_Sar_OpenMode_Closed) {
00098 DBG_ERROR(GWEN_LOGDOMAIN, "Archive already open");
00099 return GWEN_ERROR_OPEN;
00100 }
00101
00102 free(sr->archiveName);
00103 sr->archiveName=strdup(aname);
00104 sio=GWEN_SyncIo_File_new(aname, GWEN_SyncIo_File_CreationMode_CreateAlways);
00105 GWEN_SyncIo_AddFlags(sio,
00106 GWEN_SYNCIO_FILE_FLAGS_READ |
00107 GWEN_SYNCIO_FILE_FLAGS_WRITE |
00108 GWEN_SYNCIO_FILE_FLAGS_UREAD |
00109 GWEN_SYNCIO_FILE_FLAGS_UWRITE |
00110 GWEN_SYNCIO_FILE_FLAGS_GREAD |
00111 GWEN_SYNCIO_FILE_FLAGS_GWRITE);
00112 rv=GWEN_SyncIo_Connect(sio);
00113 if (rv<0) {
00114 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00115 GWEN_SyncIo_free(sio);
00116 return rv;
00117 }
00118
00119 sr->archiveSio=sio;
00120 sr->openMode=GWEN_Sar_OpenMode_Created;
00121
00122 sr->signaturePos=0;
00123 sr->signatureSize=0;
00124
00125 return 0;
00126 }
00127
00128
00129
00130 int GWEN_Sar_OpenArchive(GWEN_SAR *sr, const char *aname,
00131 GWEN_SYNCIO_FILE_CREATIONMODE cm,
00132 uint32_t acc) {
00133 GWEN_SYNCIO *sio;
00134 int rv;
00135
00136 assert(sr);
00137 assert(sr->refCount);
00138
00139 assert(aname);
00140 if (sr->openMode!=GWEN_Sar_OpenMode_Closed) {
00141 DBG_ERROR(GWEN_LOGDOMAIN, "Archive already open");
00142 return GWEN_ERROR_OPEN;
00143 }
00144
00145 free(sr->archiveName);
00146 sr->archiveName=strdup(aname);
00147 sio=GWEN_SyncIo_File_new(aname, cm);
00148 GWEN_SyncIo_AddFlags(sio, acc);
00149 rv=GWEN_SyncIo_Connect(sio);
00150 if (rv<0) {
00151 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00152 GWEN_SyncIo_free(sio);
00153 return rv;
00154 }
00155
00156 sr->archiveSio=sio;
00157 sr->openMode=GWEN_Sar_OpenMode_Opened;
00158
00159 sr->signaturePos=0;
00160 sr->signatureSize=0;
00161
00162 rv=GWEN_Sar_ScanFile(sr);
00163 if (rv<0) {
00164 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00165 sr->archiveSio=NULL;
00166 sr->openMode=GWEN_Sar_OpenMode_Closed;
00167 GWEN_SyncIo_free(sio);
00168 return rv;
00169 }
00170
00171 return 0;
00172 }
00173
00174
00175
00176 int GWEN_Sar_CloseArchive(GWEN_SAR *sr, int abandon) {
00177 int rv;
00178
00179 assert(sr);
00180 assert(sr->refCount);
00181
00182 if (sr->openMode!=GWEN_Sar_OpenMode_Opened &&
00183 sr->openMode!=GWEN_Sar_OpenMode_Created) {
00184 DBG_ERROR(GWEN_LOGDOMAIN, "Archive not open");
00185 return GWEN_ERROR_NOT_OPEN;
00186 }
00187
00188 if (!abandon) {
00189
00190 rv=GWEN_SyncIo_Flush(sr->archiveSio);
00191 if (rv<0) {
00192 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00193 GWEN_SyncIo_Disconnect(sr->archiveSio);
00194 GWEN_SyncIo_free(sr->archiveSio);
00195 sr->archiveSio=NULL;
00196 free(sr->archiveName);
00197 sr->archiveName=NULL;
00198 sr->openMode=GWEN_Sar_OpenMode_Closed;
00199 return rv;
00200 }
00201 }
00202
00203
00204 rv=GWEN_SyncIo_Disconnect(sr->archiveSio);
00205 if (rv<0) {
00206 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00207 GWEN_SyncIo_free(sr->archiveSio);
00208 sr->archiveSio=NULL;
00209 free(sr->archiveName);
00210 sr->archiveName=NULL;
00211 sr->openMode=GWEN_Sar_OpenMode_Closed;
00212 return rv;
00213 }
00214
00215 GWEN_SyncIo_free(sr->archiveSio);
00216 sr->archiveSio=NULL;
00217 free(sr->archiveName);
00218 sr->archiveName=NULL;
00219 sr->openMode=GWEN_Sar_OpenMode_Closed;
00220 return 0;
00221 }
00222
00223
00224
00225 int GWEN_Sar_FileHeaderToTlv(const GWEN_SAR_FILEHEADER *fh, GWEN_BUFFER *tbuf) {
00226 const char *s;
00227 uint16_t v8;
00228 uint32_t v32;
00229 uint64_t v64;
00230 uint8_t hbuf[8];
00231 const GWEN_TIME *ti;
00232 int rv;
00233
00234
00235 v32=GWEN_SAR_HEADER_VERSION;
00236 hbuf[0]=(v32>>24) & 0xff;
00237 hbuf[1]=(v32>>16) & 0xff;
00238 hbuf[2]=(v32>>8) & 0xff;
00239 hbuf[3]=v32 & 0xff;
00240 GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_VERSION, 0x00, hbuf, 4, 1, tbuf);
00241
00242
00243 v8=GWEN_SarFileHeader_GetStatus(fh) & 0xff;
00244 hbuf[0]=v8;
00245 GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_STATUS, 0x00, hbuf, 1, 1, tbuf);
00246
00247
00248 v32=GWEN_SarFileHeader_GetFlags(fh);
00249 hbuf[0]=(v32>>24) & 0xff;
00250 hbuf[1]=(v32>>16) & 0xff;
00251 hbuf[2]=(v32>>8) & 0xff;
00252 hbuf[3]=v32 & 0xff;
00253 GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_FLAGS, 0x00, hbuf, 4, 1, tbuf);
00254
00255
00256 s=GWEN_SarFileHeader_GetPath(fh);
00257 if (s && *s)
00258 GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_PATH, 0x00, s, strlen(s)+1, 1, tbuf);
00259
00260
00261 v8=GWEN_SarFileHeader_GetFileType(fh) & 0xff;
00262 hbuf[0]=v8;
00263 GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_TYPE, 0x00, hbuf, 1, 1, tbuf);
00264
00265
00266 v32=GWEN_SarFileHeader_GetPermissions(fh);
00267 hbuf[0]=(v32>>24) & 0xff;
00268 hbuf[1]=(v32>>16) & 0xff;
00269 hbuf[2]=(v32>>8) & 0xff;
00270 hbuf[3]=v32 & 0xff;
00271 GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_PERM, 0x00, hbuf, 4, 1, tbuf);
00272
00273
00274 ti=GWEN_SarFileHeader_GetAtime(fh);
00275 if (ti) {
00276 GWEN_BUFFER *xbuf;
00277
00278 xbuf=GWEN_Buffer_new(0, 32, 0, 1);
00279 rv=GWEN_Time_toUtcString(ti, "YYYYMMDDhhmmss", xbuf);
00280 if (rv>=0)
00281 GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_ATIME, 0x00,
00282 GWEN_Buffer_GetStart(xbuf),
00283 GWEN_Buffer_GetUsedBytes(xbuf),
00284 1,
00285 tbuf);
00286 GWEN_Buffer_free(xbuf);
00287 }
00288
00289
00290 ti=GWEN_SarFileHeader_GetMtime(fh);
00291 if (ti) {
00292 GWEN_BUFFER *xbuf;
00293
00294 xbuf=GWEN_Buffer_new(0, 32, 0, 1);
00295 rv=GWEN_Time_toUtcString(ti, "YYYYMMDDhhmmss", xbuf);
00296 if (rv>=0)
00297 GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_MTIME, 0x00,
00298 GWEN_Buffer_GetStart(xbuf),
00299 GWEN_Buffer_GetUsedBytes(xbuf),
00300 1,
00301 tbuf);
00302 GWEN_Buffer_free(xbuf);
00303 }
00304
00305
00306 ti=GWEN_SarFileHeader_GetCtime(fh);
00307 if (ti) {
00308 GWEN_BUFFER *xbuf;
00309
00310 xbuf=GWEN_Buffer_new(0, 32, 0, 1);
00311 rv=GWEN_Time_toUtcString(ti, "YYYYMMDDhhmmss", xbuf);
00312 if (rv>=0)
00313 GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_CTIME, 0x00,
00314 GWEN_Buffer_GetStart(xbuf),
00315 GWEN_Buffer_GetUsedBytes(xbuf),
00316 1,
00317 tbuf);
00318 GWEN_Buffer_free(xbuf);
00319 }
00320
00321
00322 v64=GWEN_SarFileHeader_GetFileSize(fh);
00323 hbuf[0]=(v64>>56) & 0xff;
00324 hbuf[1]=(v64>>48) & 0xff;
00325 hbuf[2]=(v64>>40) & 0xff;
00326 hbuf[3]=(v64>>32) & 0xff;
00327 hbuf[4]=(v64>>24) & 0xff;
00328 hbuf[5]=(v64>>16) & 0xff;
00329 hbuf[6]=(v64>>8) & 0xff;
00330 hbuf[7]=v64 & 0xff;
00331 GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HEADER_SIZE, 0x00, hbuf, 8, 1, tbuf);
00332
00333 return 0;
00334 }
00335
00336
00337
00338 uint64_t GWEN_Sar_ReadUint64(const uint8_t *p, uint32_t bs) {
00339 uint64_t v=0;
00340
00341 switch(bs) {
00342 case 8:
00343 v=(((uint64_t)(p[0]))<<56)+
00344 (((uint64_t)(p[1]))<<48)+
00345 (((uint64_t)(p[2]))<<40)+
00346 (((uint64_t)(p[3]))<<32)+
00347 (((uint64_t)(p[4]))<<24)+
00348 (((uint64_t)(p[5]))<<16)+
00349 (((uint64_t)(p[6]))<<8)+
00350 ((uint64_t)(p[7]));
00351 break;
00352 case 7:
00353 v=(((uint64_t)(p[0]))<<48)+
00354 (((uint64_t)(p[1]))<<40)+
00355 (((uint64_t)(p[2]))<<32)+
00356 (((uint64_t)(p[3]))<<24)+
00357 (((uint64_t)(p[4]))<<16)+
00358 (((uint64_t)(p[5]))<<8)+
00359 ((uint64_t)(p[6]));
00360 break;
00361 case 6:
00362 v=(((uint64_t)(p[0]))<<40)+
00363 (((uint64_t)(p[1]))<<32)+
00364 (((uint64_t)(p[2]))<<24)+
00365 (((uint64_t)(p[3]))<<16)+
00366 (((uint64_t)(p[4]))<<8)+
00367 ((uint64_t)(p[5]));
00368 break;
00369 case 5:
00370 v=(((uint64_t)(p[0]))<<32)+
00371 (((uint64_t)(p[1]))<<24)+
00372 (((uint64_t)(p[2]))<<16)+
00373 (((uint64_t)(p[3]))<<8)+
00374 ((uint64_t)(p[4]));
00375 break;
00376 case 4:
00377 v=(((uint64_t)(p[0]))<<24)+
00378 (((uint64_t)(p[1]))<<16)+
00379 (((uint64_t)(p[2]))<<8)+
00380 ((uint64_t)(p[3]));
00381 break;
00382 case 3:
00383 v=(((uint64_t)(p[0]))<<16)+
00384 (((uint64_t)(p[1]))<<8)+
00385 ((uint64_t)(p[2]));
00386 break;
00387 case 2:
00388 v=(((uint64_t)(p[0]))<<8)+
00389 ((uint64_t)(p[1]));
00390 break;
00391 case 1:
00392 v=((uint64_t)(p[0]));
00393 break;
00394
00395 default:
00396 DBG_ERROR(GWEN_LOGDOMAIN, "Unsupported size of %d for uint32", bs);
00397 break;
00398 }
00399
00400 return v;
00401 }
00402
00403
00404
00405 int GWEN_Sar_TlvToFileHeader(GWEN_BUFFER *mbuf, GWEN_SAR_FILEHEADER *fh) {
00406 while(GWEN_Buffer_GetBytesLeft(mbuf)) {
00407 GWEN_TLV *tlv;
00408
00409 tlv=GWEN_TLV_fromBuffer(mbuf, 1);
00410 if (tlv) {
00411 const uint8_t *p;
00412 uint32_t bs;
00413 uint64_t v;
00414 GWEN_TIME *ti;
00415
00416 p=GWEN_TLV_GetTagData(tlv);
00417 bs=GWEN_TLV_GetTagLength(tlv);
00418 switch(GWEN_TLV_GetTagType(tlv)) {
00419 case GWEN_SAR_TAG_HEADER_VERSION:
00420 v=GWEN_Sar_ReadUint64(p, bs);
00421 DBG_DEBUG(GWEN_LOGDOMAIN, "File Header Version: %08x", (unsigned int) (v & 0xffffffff));
00422 break;
00423
00424 case GWEN_SAR_TAG_HEADER_STATUS:
00425 v=GWEN_Sar_ReadUint64(p, bs);
00426 GWEN_SarFileHeader_SetStatus(fh, v & 0xffffffff);
00427 break;
00428
00429 case GWEN_SAR_TAG_HEADER_FLAGS:
00430 v=GWEN_Sar_ReadUint64(p, bs);
00431 GWEN_SarFileHeader_SetFlags(fh, v & 0xffffffff);
00432 break;
00433
00434 case GWEN_SAR_TAG_HEADER_PATH:
00435 GWEN_SarFileHeader_SetPath(fh, (const char*)p);
00436 break;
00437
00438 case GWEN_SAR_TAG_HEADER_TYPE:
00439 v=GWEN_Sar_ReadUint64(p, bs);
00440 GWEN_SarFileHeader_SetFileType(fh, v & 0xffffffff);
00441 break;
00442
00443 case GWEN_SAR_TAG_HEADER_PERM:
00444 v=GWEN_Sar_ReadUint64(p, bs);
00445 GWEN_SarFileHeader_SetPermissions(fh, v & 0xffffffff);
00446 break;
00447
00448 case GWEN_SAR_TAG_HEADER_ATIME:
00449 ti=GWEN_Time_fromUtcString((const char*) p, "YYYYMMDDhhmmss");
00450 GWEN_SarFileHeader_SetAtime(fh, ti);
00451 break;
00452
00453 case GWEN_SAR_TAG_HEADER_MTIME:
00454 ti=GWEN_Time_fromUtcString((const char*) p, "YYYYMMDDhhmmss");
00455 GWEN_SarFileHeader_SetMtime(fh, ti);
00456 break;
00457
00458 case GWEN_SAR_TAG_HEADER_CTIME:
00459 ti=GWEN_Time_fromUtcString((const char*) p, "YYYYMMDDhhmmss");
00460 GWEN_SarFileHeader_SetCtime(fh, ti);
00461 break;
00462
00463 case GWEN_SAR_TAG_HEADER_SIZE:
00464 v=GWEN_Sar_ReadUint64(p, bs);
00465 GWEN_SarFileHeader_SetFileSize(fh, v);
00466 break;
00467 default:
00468 DBG_WARN(GWEN_LOGDOMAIN, "Ignoring unknown tag %d", GWEN_TLV_GetTagType(tlv));
00469 break;
00470 }
00471
00472 }
00473 else {
00474 DBG_ERROR(GWEN_LOGDOMAIN, "No TLV in buffer");
00475 return GWEN_ERROR_BAD_DATA;
00476 }
00477 }
00478 return 0;
00479 }
00480
00481
00482
00483 int GWEN_Sar_AddAndDigestFileReg(GWEN_SAR *sr, const GWEN_SAR_FILEHEADER *fh, GWEN_MDIGEST *md) {
00484 int rv;
00485 const char *fname;
00486 uint64_t fsize;
00487 uint64_t bytesDone;
00488 GWEN_BUFFER *hbuf;
00489
00490 assert(sr);
00491 assert(sr->refCount);
00492
00493 fname=GWEN_SarFileHeader_GetPath(fh);
00494 assert(fname);
00495 fsize=GWEN_SarFileHeader_GetFileSize(fh);
00496
00497
00498 hbuf=GWEN_Buffer_new(0, 32, 0, 1);
00499 rv=GWEN_TLV_WriteHeader(GWEN_SAR_TAG_FILE, 0x00, fsize, 1, hbuf);
00500 if (rv<0) {
00501 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00502 GWEN_Buffer_free(hbuf);
00503 return rv;
00504 }
00505
00506
00507 rv=GWEN_SyncIo_WriteForced(sr->archiveSio,
00508 (const uint8_t*) GWEN_Buffer_GetStart(hbuf),
00509 GWEN_Buffer_GetUsedBytes(hbuf));
00510 if (rv<0) {
00511 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00512 GWEN_Buffer_free(hbuf);
00513 return rv;
00514 }
00515
00516 GWEN_Buffer_free(hbuf);
00517
00518
00519 if (fsize>0) {
00520 GWEN_SYNCIO *sio;
00521 uint32_t pid;
00522
00523
00524 sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_OpenExisting);
00525 GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_READ);
00526 rv=GWEN_SyncIo_Connect(sio);
00527 if (rv<0) {
00528 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00529 GWEN_SyncIo_free(sio);
00530 return rv;
00531 }
00532
00533 pid=GWEN_Gui_ProgressStart(GWEN_GUI_PROGRESS_DELAY |
00534 GWEN_GUI_PROGRESS_SHOW_ABORT |
00535 GWEN_GUI_PROGRESS_ALLOW_EMBED |
00536 GWEN_GUI_PROGRESS_SHOW_PROGRESS,
00537 I18N("File Operation"),
00538 I18N("Copying file into archive"),
00539 fsize,
00540 0);
00541 bytesDone=0;
00542 while(fsize) {
00543 uint8_t fbuf[10240];
00544 uint64_t bs;
00545
00546 bs=fsize;
00547 if (bs>sizeof(fbuf))
00548 bs=sizeof(fbuf);
00549
00550
00551 rv=GWEN_SyncIo_Read(sio, fbuf, bs);
00552 if (rv<0) {
00553 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00554 GWEN_Gui_ProgressEnd(pid);
00555 GWEN_SyncIo_Disconnect(sio);
00556 GWEN_SyncIo_free(sio);
00557 return rv;
00558 }
00559 bs=rv;
00560
00561
00562 rv=GWEN_MDigest_Update(md, fbuf, bs);
00563 if (rv<0) {
00564 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00565 GWEN_Gui_ProgressEnd(pid);
00566 GWEN_SyncIo_Disconnect(sio);
00567 GWEN_SyncIo_free(sio);
00568 return rv;
00569 }
00570
00571
00572 rv=GWEN_SyncIo_WriteForced(sr->archiveSio, fbuf, bs);
00573 if (rv<0) {
00574 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00575 GWEN_Gui_ProgressEnd(pid);
00576 GWEN_SyncIo_Disconnect(sio);
00577 GWEN_SyncIo_free(sio);
00578 return rv;
00579 }
00580
00581 if (bs>fsize) {
00582 DBG_ERROR(GWEN_LOGDOMAIN, "Internal error: bs>fsize (%lu>%lu)",
00583 (unsigned long int)bs, (unsigned long int) fsize);
00584 GWEN_Gui_ProgressEnd(pid);
00585 GWEN_SyncIo_Disconnect(sio);
00586 GWEN_SyncIo_free(sio);
00587 return rv;
00588 }
00589
00590 bytesDone+=bs;
00591 fsize-=bs;
00592
00593
00594 rv=GWEN_Gui_ProgressAdvance(pid, bytesDone);
00595 if (rv<0) {
00596 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00597 GWEN_Gui_ProgressEnd(pid);
00598 GWEN_SyncIo_Disconnect(sio);
00599 GWEN_SyncIo_free(sio);
00600 return rv;
00601 }
00602
00603 }
00604 GWEN_Gui_ProgressEnd(pid);
00605
00606
00607 GWEN_SyncIo_Disconnect(sio);
00608 GWEN_SyncIo_free(sio);
00609 }
00610
00611 return 0;
00612 }
00613
00614
00615
00616 int GWEN_Sar_AddAndDigestFileLink(GWEN_SAR *sr, const GWEN_SAR_FILEHEADER *fh, GWEN_MDIGEST *md) {
00617 #if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || (_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) || _POSIX_C_SOURCE >= 200112L || defined(OS_DARWIN)
00618 int rv;
00619 const char *fname;
00620 GWEN_BUFFER *hbuf;
00621 char lbuf[300];
00622 int len;
00623
00624 assert(sr);
00625 assert(sr->refCount);
00626
00627 fname=GWEN_SarFileHeader_GetPath(fh);
00628 assert(fname);
00629
00630
00631 rv=readlink(fname, lbuf, sizeof(lbuf)-1);
00632 if (rv<0) {
00633 DBG_ERROR(GWEN_LOGDOMAIN, "readlink(%s): %d (%s)",
00634 fname, errno, strerror(errno));
00635 return GWEN_ERROR_IO;
00636 }
00637 len=rv;
00638 lbuf[len]=0;
00639
00640
00641 hbuf=GWEN_Buffer_new(0, rv+8, 0, 1);
00642 GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_FILE, 0x00,
00643 lbuf, len+1,
00644 1, hbuf);
00645
00646
00647
00648 rv=GWEN_SyncIo_WriteForced(sr->archiveSio,
00649 (const uint8_t*) GWEN_Buffer_GetStart(hbuf),
00650 GWEN_Buffer_GetUsedBytes(hbuf));
00651 if (rv<0) {
00652 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00653 GWEN_Buffer_free(hbuf);
00654 return rv;
00655 }
00656 GWEN_Buffer_free(hbuf);
00657
00658
00659 rv=GWEN_MDigest_Update(md, (const uint8_t*) lbuf, len+1);
00660 if (rv<0) {
00661 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00662 return rv;
00663 }
00664
00665 return 0;
00666 #else
00667 # warning "Function readlink() is not available"
00668 DBG_ERROR(GWEN_LOGDOMAIN, "Function readlink() is not available");
00669 return GWEN_ERROR_IO;
00670 #endif
00671 }
00672
00673
00674
00675 int GWEN_Sar_AddAndDigestFile(GWEN_SAR *sr, const GWEN_SAR_FILEHEADER *fh, GWEN_MDIGEST *md) {
00676 int rv;
00677
00678 switch(GWEN_SarFileHeader_GetFileType(fh)) {
00679 case GWEN_SarFileHeader_FType_File:
00680 rv=GWEN_Sar_AddAndDigestFileReg(sr, fh, md);
00681 break;
00682 case GWEN_SarFileHeader_FType_Dir:
00683 rv=0;
00684 break;
00685 case GWEN_SarFileHeader_FType_SymLink:
00686 rv=GWEN_Sar_AddAndDigestFileLink(sr, fh, md);
00687 break;
00688 default:
00689 DBG_ERROR(GWEN_LOGDOMAIN, "File type %d not supported", GWEN_SarFileHeader_GetFileType(fh));
00690 return GWEN_ERROR_INVALID;
00691 }
00692
00693 if (rv<0) {
00694 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00695 return rv;
00696 }
00697
00698 return 0;
00699 }
00700
00701
00702
00703 int GWEN_Sar_AddFile(GWEN_SAR *sr, const char *fname) {
00704 struct stat st;
00705 int rv;
00706 GWEN_SAR_FILEHEADER *fh;
00707 GWEN_TIME *ti;
00708 GWEN_BUFFER *hbuf;
00709 GWEN_BUFFER *xbuf;
00710 GWEN_MDIGEST *md;
00711 uint64_t pos;
00712
00713 assert(sr);
00714 assert(sr->refCount);
00715
00716
00717 #if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
00718 rv=lstat(fname, &st);
00719 #else
00720 rv=stat(fname, &st);
00721 #endif
00722 if (rv) {
00723 DBG_ERROR(GWEN_LOGDOMAIN, "stat(%s): %d (%s)",
00724 fname, errno, strerror(errno));
00725 return GWEN_ERROR_IO;
00726 }
00727
00728
00729 fh=GWEN_SarFileHeader_new();
00730
00731
00732 GWEN_SarFileHeader_SetPath(fh, fname);
00733
00734
00735 switch(st.st_mode & S_IFMT) {
00736 #ifdef S_IFLNK
00737 case S_IFLNK:
00738 GWEN_SarFileHeader_SetFileType(fh, GWEN_SarFileHeader_FType_SymLink);
00739 break;
00740 #endif
00741 case S_IFREG:
00742 GWEN_SarFileHeader_SetFileType(fh, GWEN_SarFileHeader_FType_File);
00743 break;
00744 case S_IFDIR:
00745 GWEN_SarFileHeader_SetFileType(fh, GWEN_SarFileHeader_FType_Dir);
00746 break;
00747 default:
00748 GWEN_SarFileHeader_free(fh);
00749 return GWEN_ERROR_INVALID;
00750 }
00751
00752
00753 if (st.st_mode & S_IRUSR) GWEN_SarFileHeader_AddPermissions(fh, GWEN_SYNCIO_FILE_FLAGS_UREAD);
00754 if (st.st_mode & S_IWUSR) GWEN_SarFileHeader_AddPermissions(fh, GWEN_SYNCIO_FILE_FLAGS_UWRITE);
00755 if (st.st_mode & S_IXUSR) GWEN_SarFileHeader_AddPermissions(fh, GWEN_SYNCIO_FILE_FLAGS_UEXEC);
00756
00757 #ifdef S_IRGRP
00758 if (st.st_mode & S_IRGRP) GWEN_SarFileHeader_AddPermissions(fh, GWEN_SYNCIO_FILE_FLAGS_GREAD);
00759 #endif
00760 #ifdef S_IWGRP
00761 if (st.st_mode & S_IWGRP) GWEN_SarFileHeader_AddPermissions(fh, GWEN_SYNCIO_FILE_FLAGS_GWRITE);
00762 #endif
00763 #ifdef S_IXGRP
00764 if (st.st_mode & S_IXGRP) GWEN_SarFileHeader_AddPermissions(fh, GWEN_SYNCIO_FILE_FLAGS_GEXEC);
00765 #endif
00766
00767 #ifdef S_IROTH
00768 if (st.st_mode & S_IROTH) GWEN_SarFileHeader_AddPermissions(fh, GWEN_SYNCIO_FILE_FLAGS_OREAD);
00769 #endif
00770 #ifdef S_IWOTH
00771 if (st.st_mode & S_IWOTH) GWEN_SarFileHeader_AddPermissions(fh, GWEN_SYNCIO_FILE_FLAGS_OWRITE);
00772 #endif
00773 #ifdef S_IXOTH
00774 if (st.st_mode & S_IXOTH) GWEN_SarFileHeader_AddPermissions(fh, GWEN_SYNCIO_FILE_FLAGS_OEXEC);
00775 #endif
00776
00777
00778 ti=GWEN_Time_fromSeconds(st.st_atime);
00779 GWEN_SarFileHeader_SetAtime(fh, ti);
00780
00781
00782 ti=GWEN_Time_fromSeconds(st.st_mtime);
00783 GWEN_SarFileHeader_SetMtime(fh, ti);
00784
00785
00786 ti=GWEN_Time_fromSeconds(st.st_ctime);
00787 GWEN_SarFileHeader_SetCtime(fh, ti);
00788
00789
00790 GWEN_SarFileHeader_SetFileSize(fh, st.st_size);
00791
00792
00793
00794 hbuf=GWEN_Buffer_new(0, 256, 0, 1);
00795 GWEN_Buffer_ReserveBytes(hbuf, 16);
00796 rv=GWEN_Sar_FileHeaderToTlv(fh, hbuf);
00797 if (rv<0) {
00798 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00799 GWEN_Buffer_free(hbuf);
00800 GWEN_SarFileHeader_free(fh);
00801 return rv;
00802 }
00803
00804
00805 xbuf=GWEN_Buffer_new(0, 16, 0, 1);
00806 rv=GWEN_TLV_WriteHeader(GWEN_SAR_TAG_HEADER, 0xe0,
00807 GWEN_Buffer_GetUsedBytes(hbuf), 1, xbuf);
00808 if (rv<0) {
00809 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00810 GWEN_Buffer_free(xbuf);
00811 GWEN_Buffer_free(hbuf);
00812 GWEN_SarFileHeader_free(fh);
00813 return rv;
00814 }
00815
00816
00817 GWEN_Buffer_SetPos(hbuf, 0);
00818 GWEN_Buffer_InsertBytes(hbuf,
00819 GWEN_Buffer_GetStart(xbuf),
00820 GWEN_Buffer_GetUsedBytes(xbuf));
00821 GWEN_Buffer_SetPos(hbuf, GWEN_Buffer_GetUsedBytes(hbuf));
00822 GWEN_Buffer_free(xbuf);
00823
00824
00825 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, 0, GWEN_SyncIo_File_Whence_End);
00826 if (pos<0) {
00827 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
00828 GWEN_Buffer_free(hbuf);
00829 GWEN_SarFileHeader_free(fh);
00830 return (int) pos;
00831 }
00832
00833
00834 rv=GWEN_SyncIo_WriteForced(sr->archiveSio,
00835 (const uint8_t*) GWEN_Buffer_GetStart(hbuf),
00836 GWEN_Buffer_GetUsedBytes(hbuf));
00837 if (rv<0) {
00838 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00839 GWEN_Buffer_free(hbuf);
00840 GWEN_SarFileHeader_free(fh);
00841 return rv;
00842 }
00843
00844
00845 md=GWEN_MDigest_Rmd160_new();
00846 rv=GWEN_MDigest_Begin(md);
00847 if (rv<0) {
00848 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00849 GWEN_MDigest_free(md);
00850 GWEN_Buffer_free(hbuf);
00851 GWEN_SarFileHeader_free(fh);
00852 return rv;
00853 }
00854
00855
00856 rv=GWEN_MDigest_Update(md, (const uint8_t*) GWEN_Buffer_GetStart(hbuf), GWEN_Buffer_GetUsedBytes(hbuf));
00857 if (rv<0) {
00858 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00859 GWEN_MDigest_free(md);
00860 GWEN_Buffer_free(hbuf);
00861 GWEN_SarFileHeader_free(fh);
00862 return rv;
00863 }
00864
00865 GWEN_Buffer_Reset(hbuf);
00866
00867
00868 rv=GWEN_Sar_AddAndDigestFile(sr, fh, md);
00869 if (rv<0) {
00870 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00871 GWEN_MDigest_free(md);
00872 GWEN_Buffer_free(hbuf);
00873 GWEN_SarFileHeader_free(fh);
00874 return rv;
00875 }
00876
00877
00878 rv=GWEN_MDigest_End(md);
00879 if (rv<0) {
00880 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00881 GWEN_MDigest_free(md);
00882 GWEN_Buffer_free(hbuf);
00883 GWEN_SarFileHeader_free(fh);
00884 return rv;
00885 }
00886
00887
00888 GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_HASH, 0x00,
00889 GWEN_MDigest_GetDigestPtr(md),
00890 GWEN_MDigest_GetDigestSize(md),
00891 1, hbuf);
00892 GWEN_MDigest_free(md);
00893
00894
00895 rv=GWEN_SyncIo_WriteForced(sr->archiveSio,
00896 (const uint8_t*) GWEN_Buffer_GetStart(hbuf),
00897 GWEN_Buffer_GetUsedBytes(hbuf));
00898 if (rv<0) {
00899 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00900 GWEN_Buffer_free(hbuf);
00901 GWEN_SarFileHeader_free(fh);
00902 return rv;
00903 }
00904
00905
00906 GWEN_Buffer_free(hbuf);
00907 GWEN_SarFileHeader_free(fh);
00908 return 0;
00909 }
00910
00911
00912
00913
00914 int GWEN_Sar_ScanFile(GWEN_SAR *sr) {
00915 int rv;
00916 int64_t pos;
00917 GWEN_BUFFER *mbuf;
00918 GWEN_SAR_FILEHEADER *lastHeader=NULL;
00919
00920 assert(sr);
00921 assert(sr->refCount);
00922
00923 sr->signaturePos=0;
00924 sr->signatureSize=0;
00925
00926
00927 pos=0;
00928 mbuf=GWEN_Buffer_new(0, 1024, 0, 1);
00929 for (;;) {
00930 int64_t startOfTagHeader;
00931 int64_t startOfTagData;
00932 unsigned int tagType;
00933 uint32_t tagLength;
00934 uint32_t fullTagSize;
00935 uint32_t bs;
00936 GWEN_TLV *tlv;
00937 uint8_t buffer[32];
00938
00939 startOfTagHeader=pos;
00940 rv=GWEN_SyncIo_Read(sr->archiveSio, buffer, sizeof(buffer));
00941 if (rv<0) {
00942 if (rv==GWEN_ERROR_EOF)
00943 break;
00944 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00945 GWEN_Buffer_free(mbuf);
00946 return rv;
00947 }
00948 else if (rv==0) {
00949 DBG_VERBOUS(GWEN_LOGDOMAIN, "EOF met");
00950 break;
00951 }
00952 bs=rv;
00953
00954
00955 tlv=GWEN_TLV_new();
00956 rv=GWEN_TLV_ReadHeader(tlv, buffer, bs, 1);
00957 if (rv<2) {
00958 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00959 GWEN_TLV_free(tlv);
00960 GWEN_Buffer_free(mbuf);
00961 return rv;
00962 }
00963
00964 startOfTagData=pos+rv;
00965 tagLength=GWEN_TLV_GetTagLength(tlv);
00966 tagType=GWEN_TLV_GetTagType(tlv);
00967 fullTagSize=GWEN_TLV_GetTagSize(tlv);
00968 GWEN_TLV_free(tlv);
00969
00970
00971 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, startOfTagData, GWEN_SyncIo_File_Whence_Set);
00972 if (pos<0) {
00973 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
00974 GWEN_Buffer_free(mbuf);
00975 return (int) pos;
00976 }
00977
00978
00979 if (tagType==GWEN_SAR_TAG_HEADER) {
00980 GWEN_SAR_FILEHEADER *fh;
00981 const char *s;
00982
00983
00984 GWEN_Buffer_AllocRoom(mbuf, tagLength);
00985
00986
00987 rv=GWEN_SyncIo_ReadForced(sr->archiveSio, (uint8_t*) GWEN_Buffer_GetStart(mbuf), tagLength);
00988 if (rv<0) {
00989 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00990 GWEN_Buffer_free(mbuf);
00991 return rv;
00992 }
00993 GWEN_Buffer_IncrementPos(mbuf, tagLength);
00994 GWEN_Buffer_AdjustUsedBytes(mbuf);
00995 GWEN_Buffer_Rewind(mbuf);
00996
00997
00998 fh=GWEN_SarFileHeader_new();
00999 rv=GWEN_Sar_TlvToFileHeader(mbuf, fh);
01000 if (rv<0) {
01001 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01002 GWEN_SarFileHeader_free(fh);
01003 GWEN_Buffer_free(mbuf);
01004 return rv;
01005 }
01006
01007 GWEN_SarFileHeader_SetHeaderStartPos(fh, startOfTagHeader);
01008 GWEN_SarFileHeader_SetHeaderSize(fh, fullTagSize);
01009
01010 s=GWEN_SarFileHeader_GetPath(fh);
01011 DBG_DEBUG(GWEN_LOGDOMAIN, "Got entry [%s]", s?s:"(empty)");
01012
01013 GWEN_SarFileHeader_List_Add(fh, sr->headers);
01014 lastHeader=fh;
01015 }
01016 else if (tagType==GWEN_SAR_TAG_FILE) {
01017 if (lastHeader==NULL) {
01018 DBG_ERROR(GWEN_LOGDOMAIN, "Bad file structure: No file header before data");
01019 GWEN_Buffer_free(mbuf);
01020 return GWEN_ERROR_BAD_DATA;
01021 }
01022 if (GWEN_SarFileHeader_GetFileType(lastHeader)!=GWEN_SarFileHeader_FType_SymLink &&
01023 GWEN_SarFileHeader_GetFileSize(lastHeader)!=tagLength) {
01024 DBG_ERROR(GWEN_LOGDOMAIN, "File size in header and in archive differ (%s: hs=%lu, ts=%lu)",
01025 GWEN_SarFileHeader_GetPath(lastHeader),
01026 (unsigned long int) GWEN_SarFileHeader_GetFileSize(lastHeader),
01027 (unsigned long int) tagLength);
01028 GWEN_Buffer_free(mbuf);
01029 return GWEN_ERROR_BAD_DATA;
01030 }
01031
01032 GWEN_SarFileHeader_SetDataPos(lastHeader, startOfTagData);
01033 GWEN_SarFileHeader_SetDataSize(lastHeader, tagLength);
01034
01035
01036 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, tagLength, GWEN_SyncIo_File_Whence_Current);
01037 if (pos<0) {
01038 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
01039 GWEN_Buffer_free(mbuf);
01040 return (int) pos;
01041 }
01042 }
01043 else if (tagType==GWEN_SAR_TAG_HASH) {
01044 if (lastHeader==NULL) {
01045 DBG_ERROR(GWEN_LOGDOMAIN, "Bad file structure: No file header before data");
01046 GWEN_Buffer_free(mbuf);
01047 return GWEN_ERROR_BAD_DATA;
01048 }
01049
01050 GWEN_SarFileHeader_SetHashPos(lastHeader, startOfTagData);
01051
01052
01053 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, tagLength, GWEN_SyncIo_File_Whence_Current);
01054 if (pos<0) {
01055 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
01056 GWEN_Buffer_free(mbuf);
01057 return (int) pos;
01058 }
01059 }
01060 else if (tagType==GWEN_SAR_TAG_SIGNATURE) {
01061
01062 DBG_INFO(GWEN_LOGDOMAIN, "Signature found");
01063 sr->signaturePos=startOfTagData;
01064 sr->signatureSize=tagLength;
01065
01066
01067 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, tagLength, GWEN_SyncIo_File_Whence_Current);
01068 if (pos<0) {
01069 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
01070 GWEN_Buffer_free(mbuf);
01071 return (int) pos;
01072 }
01073 }
01074 else {
01075 DBG_WARN(GWEN_LOGDOMAIN, "Unknown TAG %d, ignoring", (int) tagType);
01076
01077 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, tagLength, GWEN_SyncIo_File_Whence_Current);
01078 if (pos<0) {
01079 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
01080 GWEN_Buffer_free(mbuf);
01081 return (int) pos;
01082 }
01083 }
01084
01085 GWEN_Buffer_Reset(mbuf);
01086 pos=startOfTagData+tagLength;
01087 }
01088
01089
01090 GWEN_Buffer_free(mbuf);
01091 return 0;
01092 }
01093
01094
01095
01096 int GWEN_Sar_ExtractAndDigestFileReg(GWEN_SAR *sr, const GWEN_SAR_FILEHEADER *fh, int checkOnly) {
01097 int rv;
01098 const char *fname;
01099 uint32_t perms;
01100 uint64_t dpos;
01101 uint64_t fsize;
01102 uint64_t bytesDone;
01103 uint64_t hsize;
01104 uint64_t hpos;
01105 uint64_t mpos;
01106 uint64_t pos;
01107 GWEN_MDIGEST *md;
01108
01109 assert(sr);
01110 assert(sr->refCount);
01111
01112 md=GWEN_MDigest_Rmd160_new();
01113 rv=GWEN_MDigest_Begin(md);
01114 if (rv<0) {
01115 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01116 GWEN_MDigest_free(md);
01117 return rv;
01118 }
01119
01120 fname=GWEN_SarFileHeader_GetPath(fh);
01121 assert(fname);
01122 perms=GWEN_SarFileHeader_GetPermissions(fh);
01123 fsize=GWEN_SarFileHeader_GetFileSize(fh);
01124 dpos=GWEN_SarFileHeader_GetDataPos(fh);
01125
01126 hpos=GWEN_SarFileHeader_GetHeaderStartPos(fh);
01127 hsize=GWEN_SarFileHeader_GetHeaderSize(fh);
01128 if (hsize>0) {
01129 GWEN_BUFFER *mbuf;
01130
01131
01132 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, hpos, GWEN_SyncIo_File_Whence_Set);
01133 if (pos<0) {
01134 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
01135 GWEN_MDigest_free(md);
01136 return (int) pos;
01137 }
01138
01139 mbuf=GWEN_Buffer_new(0, hsize, 0, 1);
01140 rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
01141 (uint8_t*) GWEN_Buffer_GetStart(mbuf),
01142 hsize);
01143 if (rv<0) {
01144 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01145 GWEN_Buffer_free(mbuf);
01146 GWEN_MDigest_free(md);
01147 return rv;
01148 }
01149 GWEN_Buffer_IncrementPos(mbuf, hsize);
01150 GWEN_Buffer_AdjustUsedBytes(mbuf);
01151
01152
01153 rv=GWEN_MDigest_Update(md, (const uint8_t*) GWEN_Buffer_GetStart(mbuf), GWEN_Buffer_GetUsedBytes(mbuf));
01154 if (rv<0) {
01155 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01156 GWEN_Buffer_free(mbuf);
01157 GWEN_MDigest_free(md);
01158 return rv;
01159 }
01160 GWEN_Buffer_free(mbuf);
01161 }
01162
01163
01164 if (1) {
01165 GWEN_SYNCIO *sio=NULL;
01166 uint32_t pid;
01167
01168
01169 if (!checkOnly) {
01170 sio=GWEN_SyncIo_File_new(fname, GWEN_SyncIo_File_CreationMode_CreateNew);
01171 GWEN_SyncIo_AddFlags(sio, GWEN_SYNCIO_FILE_FLAGS_READ | GWEN_SYNCIO_FILE_FLAGS_WRITE);
01172 GWEN_SyncIo_AddFlags(sio, perms);
01173 rv=GWEN_SyncIo_Connect(sio);
01174 if (rv<0) {
01175 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01176 GWEN_SyncIo_free(sio);
01177 GWEN_MDigest_free(md);
01178 return rv;
01179 }
01180 }
01181
01182 if (fsize>0) {
01183
01184 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, dpos, GWEN_SyncIo_File_Whence_Set);
01185 if (pos<0) {
01186 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
01187 if (!checkOnly) {
01188 GWEN_SyncIo_Disconnect(sio);
01189 GWEN_SyncIo_free(sio);
01190 }
01191 GWEN_MDigest_free(md);
01192 return (int) pos;
01193 }
01194
01195
01196 pid=GWEN_Gui_ProgressStart(GWEN_GUI_PROGRESS_DELAY |
01197 GWEN_GUI_PROGRESS_SHOW_ABORT |
01198 GWEN_GUI_PROGRESS_ALLOW_EMBED |
01199 GWEN_GUI_PROGRESS_SHOW_PROGRESS,
01200 I18N("File Operation"),
01201 I18N("Extracting file from archive"),
01202 fsize,
01203 0);
01204 bytesDone=0;
01205 while(fsize) {
01206 uint8_t fbuf[10240];
01207 uint64_t bs;
01208
01209 bs=fsize;
01210 if (bs>sizeof(fbuf))
01211 bs=sizeof(fbuf);
01212
01213
01214 rv=GWEN_SyncIo_Read(sr->archiveSio, fbuf, bs);
01215 if (rv<0) {
01216 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01217 GWEN_Gui_ProgressEnd(pid);
01218 if (!checkOnly) {
01219 GWEN_SyncIo_Disconnect(sio);
01220 GWEN_SyncIo_free(sio);
01221 }
01222 GWEN_MDigest_free(md);
01223 return rv;
01224 }
01225 bs=rv;
01226
01227
01228 rv=GWEN_MDigest_Update(md, fbuf, bs);
01229 if (rv<0) {
01230 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01231 GWEN_Gui_ProgressEnd(pid);
01232 if (!checkOnly) {
01233 GWEN_SyncIo_Disconnect(sio);
01234 GWEN_SyncIo_free(sio);
01235 }
01236 GWEN_MDigest_free(md);
01237 return rv;
01238 }
01239
01240 if (!checkOnly) {
01241
01242 rv=GWEN_SyncIo_WriteForced(sio, fbuf, bs);
01243 if (rv<0) {
01244 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01245 GWEN_Gui_ProgressEnd(pid);
01246 if (!checkOnly) {
01247 GWEN_SyncIo_Disconnect(sio);
01248 GWEN_SyncIo_free(sio);
01249 }
01250 GWEN_MDigest_free(md);
01251 return rv;
01252 }
01253 }
01254
01255 if (bs>fsize) {
01256 DBG_ERROR(GWEN_LOGDOMAIN, "Internal error: bs>fsize (%lu>%lu)",
01257 (unsigned long int)bs, (unsigned long int) fsize);
01258 GWEN_Gui_ProgressEnd(pid);
01259 if (!checkOnly) {
01260 GWEN_SyncIo_Disconnect(sio);
01261 GWEN_SyncIo_free(sio);
01262 }
01263 GWEN_MDigest_free(md);
01264 return rv;
01265 }
01266
01267 bytesDone+=bs;
01268 fsize-=bs;
01269
01270
01271 rv=GWEN_Gui_ProgressAdvance(pid, bytesDone);
01272 if (rv<0) {
01273 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01274 GWEN_Gui_ProgressEnd(pid);
01275 if (!checkOnly) {
01276 GWEN_SyncIo_Disconnect(sio);
01277 GWEN_SyncIo_free(sio);
01278 }
01279 GWEN_MDigest_free(md);
01280 return rv;
01281 }
01282
01283 }
01284 GWEN_Gui_ProgressEnd(pid);
01285 }
01286
01287 if (!checkOnly) {
01288
01289 GWEN_SyncIo_Disconnect(sio);
01290 GWEN_SyncIo_free(sio);
01291 }
01292
01293
01294 rv=GWEN_MDigest_End(md);
01295 if (rv<0) {
01296 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01297 GWEN_MDigest_free(md);
01298 return rv;
01299 }
01300
01301
01302 mpos=GWEN_SarFileHeader_GetHashPos(fh);
01303 if (mpos) {
01304 GWEN_BUFFER *mbuf;
01305
01306
01307 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, mpos, GWEN_SyncIo_File_Whence_Set);
01308 if (pos<0) {
01309 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
01310 GWEN_MDigest_free(md);
01311 return (int) pos;
01312 }
01313
01314
01315 mbuf=GWEN_Buffer_new(0, 20, 0, 1);
01316 rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
01317 (uint8_t*) GWEN_Buffer_GetStart(mbuf),
01318 20);
01319 if (rv<0) {
01320 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01321 GWEN_Buffer_free(mbuf);
01322 GWEN_MDigest_free(md);
01323 return rv;
01324 }
01325 GWEN_Buffer_IncrementPos(mbuf, 20);
01326 GWEN_Buffer_AdjustUsedBytes(mbuf);
01327
01328 if (memcmp(GWEN_MDigest_GetDigestPtr(md),
01329 GWEN_Buffer_GetStart(mbuf),
01330 20)!=0) {
01331 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01332 DBG_ERROR(0, "Hash don't match:");
01333 GWEN_Text_LogString((const char*) GWEN_MDigest_GetDigestPtr(md), 20,
01334 GWEN_LOGDOMAIN, GWEN_LoggerLevel_Error);
01335
01336 GWEN_Text_LogString(GWEN_Buffer_GetStart(mbuf), 20,
01337 GWEN_LOGDOMAIN, GWEN_LoggerLevel_Error);
01338 GWEN_Buffer_free(mbuf);
01339 GWEN_MDigest_free(md);
01340 return GWEN_ERROR_BAD_DATA;
01341 }
01342
01343 GWEN_Buffer_free(mbuf);
01344 }
01345
01346 GWEN_MDigest_free(md);
01347 }
01348
01349 return 0;
01350 }
01351
01352
01353
01354 int GWEN_Sar_ExtractAndDigestFileLink(GWEN_SAR *sr, const GWEN_SAR_FILEHEADER *fh, int checkOnly) {
01355 #if _BSD_SOURCE || _XOPEN_SOURCE >= 500 || (_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) || _POSIX_C_SOURCE >= 200112L || defined(OS_DARWIN)
01356 int rv;
01357 const char *fname;
01358 uint32_t perms;
01359 uint64_t dpos;
01360 uint64_t fsize;
01361 uint64_t hsize;
01362 uint64_t hpos;
01363 uint64_t mpos;
01364 uint64_t pos;
01365 GWEN_MDIGEST *md;
01366
01367 assert(sr);
01368 assert(sr->refCount);
01369
01370 md=GWEN_MDigest_Rmd160_new();
01371 rv=GWEN_MDigest_Begin(md);
01372 if (rv<0) {
01373 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01374 GWEN_MDigest_free(md);
01375 return rv;
01376 }
01377
01378 fname=GWEN_SarFileHeader_GetPath(fh);
01379 perms=GWEN_SarFileHeader_GetPermissions(fh);
01380 assert(fname);
01381 fsize=GWEN_SarFileHeader_GetDataSize(fh);
01382 dpos=GWEN_SarFileHeader_GetDataPos(fh);
01383
01384 hpos=GWEN_SarFileHeader_GetHeaderStartPos(fh);
01385 hsize=GWEN_SarFileHeader_GetHeaderSize(fh);
01386 if (hsize>0) {
01387 GWEN_BUFFER *mbuf;
01388
01389
01390 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, hpos, GWEN_SyncIo_File_Whence_Set);
01391 if (pos<0) {
01392 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
01393 GWEN_MDigest_free(md);
01394 return (int) pos;
01395 }
01396
01397 mbuf=GWEN_Buffer_new(0, hsize, 0, 1);
01398 rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
01399 (uint8_t*) GWEN_Buffer_GetStart(mbuf),
01400 hsize);
01401 if (rv<0) {
01402 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01403 GWEN_Buffer_free(mbuf);
01404 GWEN_MDigest_free(md);
01405 return rv;
01406 }
01407 GWEN_Buffer_IncrementPos(mbuf, hsize);
01408 GWEN_Buffer_AdjustUsedBytes(mbuf);
01409
01410
01411 rv=GWEN_MDigest_Update(md, (const uint8_t*) GWEN_Buffer_GetStart(mbuf), GWEN_Buffer_GetUsedBytes(mbuf));
01412 if (rv<0) {
01413 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01414 GWEN_Buffer_free(mbuf);
01415 GWEN_MDigest_free(md);
01416 return rv;
01417 }
01418 GWEN_Buffer_free(mbuf);
01419 }
01420
01421
01422 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, dpos, GWEN_SyncIo_File_Whence_Set);
01423 if (pos<0) {
01424 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
01425 GWEN_MDigest_free(md);
01426 return (int) pos;
01427 }
01428
01429
01430 if (fsize>0) {
01431 GWEN_BUFFER *mbuf;
01432
01433 mbuf=GWEN_Buffer_new(0, fsize, 0, 1);
01434 rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
01435 (uint8_t*) GWEN_Buffer_GetStart(mbuf),
01436 fsize);
01437 if (rv<0) {
01438 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01439 GWEN_Buffer_free(mbuf);
01440 GWEN_MDigest_free(md);
01441 return rv;
01442 }
01443 GWEN_Buffer_IncrementPos(mbuf, fsize);
01444 GWEN_Buffer_AdjustUsedBytes(mbuf);
01445
01446
01447 rv=GWEN_MDigest_Update(md, (const uint8_t*) GWEN_Buffer_GetStart(mbuf), GWEN_Buffer_GetUsedBytes(mbuf));
01448 if (rv<0) {
01449 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01450 GWEN_Buffer_free(mbuf);
01451 GWEN_MDigest_free(md);
01452 return rv;
01453 }
01454
01455 if (!checkOnly) {
01456 mode_t mode=0;
01457
01458 if (symlink(GWEN_Buffer_GetStart(mbuf), fname)) {
01459 DBG_ERROR(GWEN_LOGDOMAIN, "symlink(%s, %s): %d (%s)",
01460 GWEN_Buffer_GetStart(mbuf),
01461 fname, errno, strerror(errno));
01462 GWEN_Buffer_free(mbuf);
01463 GWEN_MDigest_free(md);
01464 return GWEN_ERROR_IO;
01465 }
01466
01467 if (perms & GWEN_SYNCIO_FILE_FLAGS_UREAD)
01468 mode|=S_IRUSR;
01469 if (perms & GWEN_SYNCIO_FILE_FLAGS_UWRITE)
01470 mode|=S_IWUSR;
01471 if (perms & GWEN_SYNCIO_FILE_FLAGS_UEXEC)
01472 mode|=S_IXUSR;
01473
01474 #if 0
01475
01476
01477 #ifdef S_IRGRP
01478 if (perms & GWEN_SYNCIO_FILE_FLAGS_GREAD) mode|=S_IRGRP;
01479 #endif
01480 #ifdef S_IWGRP
01481 if (perms & GWEN_SYNCIO_FILE_FLAGS_GWRITE) mode|=S_IWGRP;
01482 #endif
01483 #ifdef S_IXGRP
01484 if (perms & GWEN_SYNCIO_FILE_FLAGS_GEXEC) mode|=S_IXGRP;
01485 #endif
01486
01487
01488 #ifdef S_IROTH
01489 if (perms & GWEN_SYNCIO_FILE_FLAGS_OREAD) mode|=S_IROTH;
01490 #endif
01491 #ifdef S_IWOTH
01492 if (perms & GWEN_SYNCIO_FILE_FLAGS_OWRITE) mode|=S_IWOTH;
01493 #endif
01494 #ifdef S_IXOTH
01495 if (perms & GWEN_SYNCIO_FILE_FLAGS_OEXEC) mode|=S_IXOTH;
01496 #endif
01497
01498 rv=chmod(fname, mode);
01499 if (rv<0) {
01500 DBG_WARN(GWEN_LOGDOMAIN, "chmod(%s): %d (%s), ignoring",
01501 fname, errno, strerror(errno));
01502 }
01503
01504 #endif
01505 }
01506 GWEN_Buffer_free(mbuf);
01507 }
01508
01509
01510 rv=GWEN_MDigest_End(md);
01511 if (rv<0) {
01512 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01513 GWEN_MDigest_free(md);
01514 return rv;
01515 }
01516
01517
01518 mpos=GWEN_SarFileHeader_GetHashPos(fh);
01519 if (mpos) {
01520 GWEN_BUFFER *mbuf;
01521
01522
01523 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, mpos, GWEN_SyncIo_File_Whence_Set);
01524 if (pos<0) {
01525 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
01526 GWEN_MDigest_free(md);
01527 return (int) pos;
01528 }
01529
01530
01531 mbuf=GWEN_Buffer_new(0, 20, 0, 1);
01532 rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
01533 (uint8_t*) GWEN_Buffer_GetStart(mbuf),
01534 20);
01535 if (rv<0) {
01536 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01537 GWEN_Buffer_free(mbuf);
01538 GWEN_MDigest_free(md);
01539 if (!checkOnly)
01540 unlink(fname);
01541 return rv;
01542 }
01543 GWEN_Buffer_IncrementPos(mbuf, 20);
01544 GWEN_Buffer_AdjustUsedBytes(mbuf);
01545
01546 if (memcmp(GWEN_MDigest_GetDigestPtr(md),
01547 GWEN_Buffer_GetStart(mbuf),
01548 20)!=0) {
01549 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01550 GWEN_Buffer_free(mbuf);
01551 GWEN_MDigest_free(md);
01552 if (!checkOnly)
01553 unlink(fname);
01554 return GWEN_ERROR_BAD_DATA;
01555 }
01556
01557 GWEN_Buffer_free(mbuf);
01558 }
01559
01560 GWEN_MDigest_free(md);
01561
01562 return 0;
01563 #else
01564 # warning "Function symlink() is not available"
01565 DBG_ERROR(GWEN_LOGDOMAIN, "Function symlink() is not available");
01566 return GWEN_ERROR_IO;
01567 #endif
01568 }
01569
01570
01571
01572 int GWEN_Sar_ExtractAndDigestFileDir(GWEN_SAR *sr, const GWEN_SAR_FILEHEADER *fh, int checkOnly) {
01573 int rv;
01574 const char *fname;
01575 uint64_t dpos;
01576 uint64_t fsize;
01577 uint64_t hsize;
01578 uint64_t hpos;
01579 uint64_t mpos;
01580 uint64_t pos;
01581 GWEN_MDIGEST *md;
01582 GWEN_BUFFER *mbuf;
01583 uint32_t perms;
01584
01585 assert(sr);
01586 assert(sr->refCount);
01587
01588 md=GWEN_MDigest_Rmd160_new();
01589 rv=GWEN_MDigest_Begin(md);
01590 if (rv<0) {
01591 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01592 GWEN_MDigest_free(md);
01593 return rv;
01594 }
01595
01596 fname=GWEN_SarFileHeader_GetPath(fh);
01597 assert(fname);
01598 perms=GWEN_SarFileHeader_GetPermissions(fh);
01599 fsize=GWEN_SarFileHeader_GetDataSize(fh);
01600 dpos=GWEN_SarFileHeader_GetDataPos(fh);
01601
01602 hpos=GWEN_SarFileHeader_GetHeaderStartPos(fh);
01603 hsize=GWEN_SarFileHeader_GetHeaderSize(fh);
01604 assert(hsize);
01605
01606
01607 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, hpos, GWEN_SyncIo_File_Whence_Set);
01608 if (pos<0) {
01609 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
01610 GWEN_MDigest_free(md);
01611 return (int) pos;
01612 }
01613
01614 mbuf=GWEN_Buffer_new(0, hsize, 0, 1);
01615 rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
01616 (uint8_t*) GWEN_Buffer_GetStart(mbuf),
01617 hsize);
01618 if (rv<0) {
01619 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01620 GWEN_Buffer_free(mbuf);
01621 GWEN_MDigest_free(md);
01622 return rv;
01623 }
01624 GWEN_Buffer_IncrementPos(mbuf, hsize);
01625 GWEN_Buffer_AdjustUsedBytes(mbuf);
01626
01627
01628 rv=GWEN_MDigest_Update(md, (const uint8_t*) GWEN_Buffer_GetStart(mbuf), GWEN_Buffer_GetUsedBytes(mbuf));
01629 if (rv<0) {
01630 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01631 GWEN_Buffer_free(mbuf);
01632 GWEN_MDigest_free(md);
01633 return rv;
01634 }
01635 GWEN_Buffer_free(mbuf);
01636
01637
01638 rv=GWEN_MDigest_End(md);
01639 if (rv<0) {
01640 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01641 GWEN_MDigest_free(md);
01642 return rv;
01643 }
01644
01645
01646 mpos=GWEN_SarFileHeader_GetHashPos(fh);
01647 if (mpos) {
01648 GWEN_BUFFER *mbuf;
01649
01650
01651 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, mpos, GWEN_SyncIo_File_Whence_Set);
01652 if (pos<0) {
01653 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
01654 GWEN_MDigest_free(md);
01655 return (int) pos;
01656 }
01657
01658
01659 mbuf=GWEN_Buffer_new(0, 20, 0, 1);
01660 rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
01661 (uint8_t*) GWEN_Buffer_GetStart(mbuf),
01662 20);
01663 if (rv<0) {
01664 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01665 GWEN_Buffer_free(mbuf);
01666 GWEN_MDigest_free(md);
01667 unlink(fname);
01668 return rv;
01669 }
01670 GWEN_Buffer_IncrementPos(mbuf, 20);
01671 GWEN_Buffer_AdjustUsedBytes(mbuf);
01672
01673 if (memcmp(GWEN_MDigest_GetDigestPtr(md),
01674 GWEN_Buffer_GetStart(mbuf),
01675 20)!=0) {
01676 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01677 GWEN_Buffer_free(mbuf);
01678 GWEN_MDigest_free(md);
01679 unlink(fname);
01680 return GWEN_ERROR_BAD_DATA;
01681 }
01682
01683 GWEN_Buffer_free(mbuf);
01684 }
01685
01686 GWEN_MDigest_free(md);
01687
01688 if (!checkOnly) {
01689 mode_t mode=0;
01690
01691
01692 if (perms & GWEN_SYNCIO_FILE_FLAGS_UREAD)
01693 mode|=S_IRUSR;
01694 if (perms & GWEN_SYNCIO_FILE_FLAGS_UWRITE)
01695 mode|=S_IWUSR;
01696 if (perms & GWEN_SYNCIO_FILE_FLAGS_UEXEC)
01697 mode|=S_IXUSR;
01698
01699
01700 #ifdef S_IRGRP
01701 if (perms & GWEN_SYNCIO_FILE_FLAGS_GREAD) mode|=S_IRGRP;
01702 #endif
01703 #ifdef S_IWGRP
01704 if (perms & GWEN_SYNCIO_FILE_FLAGS_GWRITE) mode|=S_IWGRP;
01705 #endif
01706 #ifdef S_IXGRP
01707 if (perms & GWEN_SYNCIO_FILE_FLAGS_GEXEC) mode|=S_IXGRP;
01708 #endif
01709
01710
01711 #ifdef S_IROTH
01712 if (perms & GWEN_SYNCIO_FILE_FLAGS_OREAD) mode|=S_IROTH;
01713 #endif
01714 #ifdef S_IWOTH
01715 if (perms & GWEN_SYNCIO_FILE_FLAGS_OWRITE) mode|=S_IWOTH;
01716 #endif
01717 #ifdef S_IXOTH
01718 if (perms & GWEN_SYNCIO_FILE_FLAGS_OEXEC) mode|=S_IXOTH;
01719 #endif
01720
01721
01722 #ifndef OS_WIN32
01723 rv=mkdir(fname, mode);
01724 #else
01725 rv=mkdir(fname);
01726 #endif
01727 if (rv) {
01728 DBG_ERROR(GWEN_LOGDOMAIN, "mkdir(%s): %d (%s)",
01729 fname, errno, strerror(errno));
01730 return GWEN_ERROR_IO;
01731 }
01732 }
01733
01734 return 0;
01735 }
01736
01737
01738
01739 int GWEN_Sar_ExtractAndDigestFile(GWEN_SAR *sr, const GWEN_SAR_FILEHEADER *fh, int checkOnly) {
01740 int rv;
01741
01742 switch(GWEN_SarFileHeader_GetFileType(fh)) {
01743 case GWEN_SarFileHeader_FType_File:
01744 rv=GWEN_Sar_ExtractAndDigestFileReg(sr, fh, checkOnly);
01745 break;
01746 case GWEN_SarFileHeader_FType_Dir:
01747 rv=GWEN_Sar_ExtractAndDigestFileDir(sr, fh, checkOnly);
01748 break;
01749 case GWEN_SarFileHeader_FType_SymLink:
01750 rv=GWEN_Sar_ExtractAndDigestFileLink(sr, fh, checkOnly);
01751 break;
01752 default:
01753 DBG_ERROR(GWEN_LOGDOMAIN, "File type %d not supported", GWEN_SarFileHeader_GetFileType(fh));
01754 return GWEN_ERROR_INVALID;
01755 }
01756
01757 if (rv<0) {
01758 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01759 return rv;
01760 }
01761
01762 return 0;
01763 }
01764
01765
01766
01767 int GWEN_Sar_ExtractFile(GWEN_SAR *sr, const GWEN_SAR_FILEHEADER *fh) {
01768 int rv;
01769
01770 rv=GWEN_Sar_ExtractAndDigestFile(sr, fh, 0);
01771 if (rv<0) {
01772 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01773 return rv;
01774 }
01775
01776 return rv;
01777 }
01778
01779
01780
01781 int GWEN_Sar_CheckFile(GWEN_SAR *sr, const GWEN_SAR_FILEHEADER *fh) {
01782 int rv;
01783
01784 rv=GWEN_Sar_ExtractAndDigestFile(sr, fh, 1);
01785 if (rv<0) {
01786 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01787 return rv;
01788 }
01789
01790 return rv;
01791 }
01792
01793
01794
01795 const GWEN_SAR_FILEHEADER_LIST *GWEN_Sar_GetHeaders(GWEN_SAR *sr) {
01796 assert(sr);
01797 assert(sr->refCount);
01798 return sr->headers;
01799 }
01800
01801
01802
01803 int GWEN_Sar__UnpackArchive(const char *inFile, const char *where) {
01804 GWEN_SAR *sr;
01805 int rv;
01806 const GWEN_SAR_FILEHEADER_LIST *fhl;
01807
01808
01809 sr=GWEN_Sar_new();
01810 rv=GWEN_Sar_OpenArchive(sr, inFile,
01811 GWEN_SyncIo_File_CreationMode_OpenExisting,
01812 GWEN_SYNCIO_FILE_FLAGS_READ);
01813 if (rv<0) {
01814 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01815 return rv;
01816 }
01817
01818
01819 if (chdir(where)) {
01820 DBG_ERROR(GWEN_LOGDOMAIN, "chdir(%s): %s", where, strerror(errno));
01821 GWEN_Sar_CloseArchive(sr, 1);
01822 GWEN_Sar_free(sr);
01823 return GWEN_ERROR_IO;
01824 }
01825
01826 fhl=GWEN_Sar_GetHeaders(sr);
01827 if (fhl) {
01828 const GWEN_SAR_FILEHEADER *fh;
01829 uint32_t pid;
01830
01831 pid=GWEN_Gui_ProgressStart(GWEN_GUI_PROGRESS_DELAY |
01832 GWEN_GUI_PROGRESS_SHOW_ABORT |
01833 GWEN_GUI_PROGRESS_ALLOW_EMBED |
01834 GWEN_GUI_PROGRESS_SHOW_PROGRESS,
01835 I18N("File Operation"),
01836 I18N("Unpacking archive file"),
01837 GWEN_SarFileHeader_List_GetCount(fhl),
01838 0);
01839
01840 fh=GWEN_SarFileHeader_List_First(fhl);
01841 while(fh) {
01842 const char *s;
01843
01844 s=GWEN_SarFileHeader_GetPath(fh);
01845 rv=GWEN_Sar_ExtractFile(sr, fh);
01846 if (rv<0) {
01847 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01848 GWEN_Gui_ProgressEnd(pid);
01849 GWEN_Sar_CloseArchive(sr, 1);
01850 GWEN_Sar_free(sr);
01851 }
01852
01853 rv=GWEN_Gui_ProgressAdvance(pid, GWEN_GUI_PROGRESS_ONE);
01854 if (rv<0) {
01855 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01856 GWEN_Gui_ProgressEnd(pid);
01857 GWEN_Sar_CloseArchive(sr, 1);
01858 GWEN_Sar_free(sr);
01859 return rv;
01860 }
01861
01862 fh=GWEN_SarFileHeader_List_Next(fh);
01863 }
01864 GWEN_Gui_ProgressEnd(pid);
01865 }
01866
01867 rv=GWEN_Sar_CloseArchive(sr, 0);
01868 if (rv<0) {
01869 fprintf(stderr, "Error closing archive (%d)\n", rv);
01870 return 2;
01871 }
01872
01873 return 0;
01874 }
01875
01876
01877
01878 int GWEN_Sar_UnpackArchive(const char *inFile, const char *where) {
01879 char savedPwd[300];
01880 int rv;
01881
01882
01883 if (getcwd(savedPwd, sizeof(savedPwd)-1)==NULL) {
01884 DBG_ERROR(GWEN_LOGDOMAIN, "getcwd(): %s", strerror(errno));
01885 return GWEN_ERROR_IO;
01886 }
01887 savedPwd[sizeof(savedPwd)-1]=0;
01888
01889 rv=GWEN_Sar__UnpackArchive(inFile, where);
01890 if (rv<0) {
01891 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01892 }
01893
01894
01895 if (chdir(savedPwd)) {
01896 DBG_ERROR(GWEN_LOGDOMAIN, "chdir(%s): %s", savedPwd, strerror(errno));
01897 return GWEN_ERROR_IO;
01898 }
01899
01900 return rv;
01901 }
01902
01903
01904
01905 int GWEN_Sar_Sign(GWEN_SAR *sr, GWEN_CRYPTMGR *cm) {
01906 int rv;
01907 GWEN_SAR_FILEHEADER_LIST *fhl;
01908
01909 assert(sr);
01910 assert(sr->refCount);
01911
01912 if (sr->openMode!=GWEN_Sar_OpenMode_Opened &&
01913 sr->openMode!=GWEN_Sar_OpenMode_Created) {
01914 DBG_ERROR(GWEN_LOGDOMAIN, "Archive not open");
01915 return GWEN_ERROR_NOT_OPEN;
01916 }
01917
01918 if (sr->signaturePos!=0 || sr->signatureSize!=0) {
01919 DBG_ERROR(GWEN_LOGDOMAIN, "There already is a signature in the archive file");
01920 return GWEN_ERROR_INVALID;
01921 }
01922
01923 fhl=sr->headers;
01924 if (fhl) {
01925 GWEN_SAR_FILEHEADER *fh;
01926 uint32_t pid;
01927 GWEN_MDIGEST *md;
01928 uint8_t hashBuf[21];
01929 GWEN_BUFFER *sbuf;
01930 GWEN_BUFFER *tbuf;
01931 int64_t pos;
01932
01933 md=GWEN_MDigest_Rmd160_new();
01934 rv=GWEN_MDigest_Begin(md);
01935 if (rv<0) {
01936 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01937 GWEN_MDigest_free(md);
01938 return rv;
01939 }
01940
01941
01942 fh=GWEN_SarFileHeader_List_First(fhl);
01943 while(fh) {
01944 GWEN_SarFileHeader_SubFlags(fh, GWEN_SAR_FILEHEADER_FLAGS_SIGNED);
01945 fh=GWEN_SarFileHeader_List_Next(fh);
01946 }
01947
01948
01949 pid=GWEN_Gui_ProgressStart(GWEN_GUI_PROGRESS_DELAY |
01950 GWEN_GUI_PROGRESS_SHOW_ABORT |
01951 GWEN_GUI_PROGRESS_ALLOW_EMBED |
01952 GWEN_GUI_PROGRESS_SHOW_PROGRESS,
01953 I18N("File Operation"),
01954 I18N("Signing archive file"),
01955 GWEN_SarFileHeader_List_GetCount(fhl),
01956 0);
01957 fh=GWEN_SarFileHeader_List_First(fhl);
01958 while(fh) {
01959 const char *s;
01960 uint64_t hpos;
01961
01962 s=GWEN_SarFileHeader_GetPath(fh);
01963 hpos=GWEN_SarFileHeader_GetHashPos(fh);
01964 if (hpos==0) {
01965 DBG_WARN(GWEN_LOGDOMAIN, "File %s has no valid hash", s?s:"(unnamed)");
01966 }
01967 else {
01968
01969 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, hpos, GWEN_SyncIo_File_Whence_Set);
01970 if (pos<0) {
01971 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
01972 GWEN_Gui_ProgressEnd(pid);
01973 GWEN_MDigest_free(md);
01974 return (int) pos;
01975 }
01976
01977
01978 rv=GWEN_SyncIo_ReadForced(sr->archiveSio, hashBuf, 20);
01979 if (rv<0) {
01980 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01981 GWEN_Gui_ProgressEnd(pid);
01982 GWEN_MDigest_free(md);
01983 return rv;
01984 }
01985
01986
01987 rv=GWEN_MDigest_Update(md, hashBuf, 20);
01988 if (rv<0) {
01989 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01990 GWEN_Gui_ProgressEnd(pid);
01991 GWEN_MDigest_free(md);
01992 return rv;
01993 }
01994
01995
01996 GWEN_SarFileHeader_AddFlags(fh, GWEN_SAR_FILEHEADER_FLAGS_SIGNED);
01997 }
01998
01999 rv=GWEN_Gui_ProgressAdvance(pid, GWEN_GUI_PROGRESS_ONE);
02000 if (rv<0) {
02001 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02002 GWEN_Gui_ProgressEnd(pid);
02003 GWEN_MDigest_free(md);
02004 return rv;
02005 }
02006
02007 fh=GWEN_SarFileHeader_List_Next(fh);
02008 }
02009
02010
02011 rv=GWEN_MDigest_End(md);
02012 if (rv<0) {
02013 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02014 GWEN_Gui_ProgressEnd(pid);
02015 GWEN_MDigest_free(md);
02016 return rv;
02017 }
02018
02019
02020 sbuf=GWEN_Buffer_new(0, 256, 0, 1);
02021 rv=GWEN_CryptMgr_Sign(cm,
02022 GWEN_MDigest_GetDigestPtr(md),
02023 GWEN_MDigest_GetDigestSize(md),
02024 sbuf);
02025 if (rv<0) {
02026 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02027 GWEN_Buffer_free(sbuf);
02028 GWEN_Gui_ProgressEnd(pid);
02029 GWEN_MDigest_free(md);
02030 return rv;
02031 }
02032 GWEN_MDigest_free(md);
02033
02034
02035 tbuf=GWEN_Buffer_new(0, 256, 0, 1);
02036 rv=GWEN_TLV_DirectlyToBuffer(GWEN_SAR_TAG_SIGNATURE, 0x00,
02037 GWEN_Buffer_GetStart(sbuf),
02038 GWEN_Buffer_GetUsedBytes(sbuf),
02039 1, tbuf);
02040 if (rv<0) {
02041 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02042 GWEN_Buffer_free(tbuf);
02043 GWEN_Buffer_free(sbuf);
02044 GWEN_Gui_ProgressEnd(pid);
02045 return rv;
02046 }
02047
02048
02049 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, 0, GWEN_SyncIo_File_Whence_End);
02050 if (pos<0) {
02051 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
02052 GWEN_Buffer_free(tbuf);
02053 GWEN_Buffer_free(sbuf);
02054 GWEN_Gui_ProgressEnd(pid);
02055 return (int) pos;
02056 }
02057
02058
02059 rv=GWEN_SyncIo_WriteForced(sr->archiveSio,
02060 (const uint8_t*) GWEN_Buffer_GetStart(tbuf),
02061 GWEN_Buffer_GetUsedBytes(tbuf));
02062 if (rv<0) {
02063 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02064 GWEN_Buffer_free(tbuf);
02065 GWEN_Buffer_free(sbuf);
02066 GWEN_Gui_ProgressEnd(pid);
02067 return rv;
02068 }
02069
02070
02071 GWEN_Buffer_free(tbuf);
02072 GWEN_Buffer_free(sbuf);
02073
02074 GWEN_Gui_ProgressEnd(pid);
02075 }
02076
02077 return 0;
02078 }
02079
02080
02081
02082 int GWEN_Sar_Verify(GWEN_SAR *sr, GWEN_CRYPTMGR *cm) {
02083 int rv;
02084 GWEN_SAR_FILEHEADER_LIST *fhl;
02085
02086 assert(sr);
02087 assert(sr->refCount);
02088
02089 if (sr->openMode!=GWEN_Sar_OpenMode_Opened &&
02090 sr->openMode!=GWEN_Sar_OpenMode_Created) {
02091 DBG_ERROR(GWEN_LOGDOMAIN, "Archive not open");
02092 return GWEN_ERROR_NOT_OPEN;
02093 }
02094
02095 if (sr->signaturePos==0 || sr->signatureSize==0) {
02096 DBG_ERROR(GWEN_LOGDOMAIN, "No valid signature data in the archive file");
02097 return GWEN_ERROR_INVALID;
02098 }
02099
02100 fhl=sr->headers;
02101 if (fhl) {
02102 GWEN_SAR_FILEHEADER *fh;
02103 uint32_t pid;
02104 GWEN_MDIGEST *md;
02105 uint8_t hashBuf[21];
02106 GWEN_BUFFER *sbuf;
02107 GWEN_BUFFER *hbuf;
02108 int64_t pos;
02109
02110 md=GWEN_MDigest_Rmd160_new();
02111 rv=GWEN_MDigest_Begin(md);
02112 if (rv<0) {
02113 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02114 GWEN_MDigest_free(md);
02115 return rv;
02116 }
02117
02118
02119 fh=GWEN_SarFileHeader_List_First(fhl);
02120 while(fh) {
02121 GWEN_SarFileHeader_SubFlags(fh, GWEN_SAR_FILEHEADER_FLAGS_SIGNED);
02122 fh=GWEN_SarFileHeader_List_Next(fh);
02123 }
02124
02125
02126 pid=GWEN_Gui_ProgressStart(GWEN_GUI_PROGRESS_DELAY |
02127 GWEN_GUI_PROGRESS_SHOW_ABORT |
02128 GWEN_GUI_PROGRESS_ALLOW_EMBED |
02129 GWEN_GUI_PROGRESS_SHOW_PROGRESS,
02130 I18N("File Operation"),
02131 I18N("Signing archive file"),
02132 GWEN_SarFileHeader_List_GetCount(fhl),
02133 0);
02134 fh=GWEN_SarFileHeader_List_First(fhl);
02135 while(fh) {
02136 const char *s;
02137 uint64_t hpos;
02138
02139 s=GWEN_SarFileHeader_GetPath(fh);
02140 hpos=GWEN_SarFileHeader_GetHashPos(fh);
02141 if (hpos==0) {
02142 DBG_WARN(GWEN_LOGDOMAIN, "File %s has no valid hash", s?s:"(unnamed)");
02143 }
02144 else {
02145
02146 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, hpos, GWEN_SyncIo_File_Whence_Set);
02147 if (pos<0) {
02148 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
02149 GWEN_Gui_ProgressEnd(pid);
02150 GWEN_MDigest_free(md);
02151 return (int) pos;
02152 }
02153
02154
02155 rv=GWEN_SyncIo_ReadForced(sr->archiveSio, hashBuf, 20);
02156 if (rv<0) {
02157 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02158 GWEN_Gui_ProgressEnd(pid);
02159 GWEN_MDigest_free(md);
02160 return rv;
02161 }
02162
02163
02164 rv=GWEN_MDigest_Update(md, hashBuf, 20);
02165 if (rv<0) {
02166 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02167 GWEN_Gui_ProgressEnd(pid);
02168 GWEN_MDigest_free(md);
02169 return rv;
02170 }
02171
02172
02173 GWEN_SarFileHeader_AddFlags(fh, GWEN_SAR_FILEHEADER_FLAGS_SIGNED);
02174 }
02175
02176 rv=GWEN_Gui_ProgressAdvance(pid, GWEN_GUI_PROGRESS_ONE);
02177 if (rv<0) {
02178 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02179 GWEN_Gui_ProgressEnd(pid);
02180 GWEN_MDigest_free(md);
02181 return rv;
02182 }
02183
02184 fh=GWEN_SarFileHeader_List_Next(fh);
02185 }
02186
02187
02188 rv=GWEN_MDigest_End(md);
02189 if (rv<0) {
02190 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02191 GWEN_Gui_ProgressEnd(pid);
02192 GWEN_MDigest_free(md);
02193 return rv;
02194 }
02195
02196
02197 pos=GWEN_SyncIo_File_Seek(sr->archiveSio, sr->signaturePos, GWEN_SyncIo_File_Whence_Set);
02198 if (pos<0) {
02199 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", (int) pos);
02200 GWEN_Gui_ProgressEnd(pid);
02201 GWEN_MDigest_free(md);
02202 return (int) pos;
02203 }
02204
02205
02206 sbuf=GWEN_Buffer_new(0, sr->signatureSize, 0, 1);
02207 rv=GWEN_SyncIo_ReadForced(sr->archiveSio,
02208 (uint8_t*) GWEN_Buffer_GetStart(sbuf),
02209 sr->signatureSize);
02210 if (rv<0) {
02211 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02212 GWEN_Buffer_free(sbuf);
02213 GWEN_Gui_ProgressEnd(pid);
02214 GWEN_MDigest_free(md);
02215 return rv;
02216 }
02217 GWEN_Buffer_IncrementPos(sbuf, sr->signatureSize);
02218 GWEN_Buffer_AdjustUsedBytes(sbuf);
02219
02220
02221 hbuf=GWEN_Buffer_new(0, 256, 0, 1);
02222 rv=GWEN_CryptMgr_Verify(cm,
02223 (const uint8_t*) GWEN_Buffer_GetStart(sbuf),
02224 GWEN_Buffer_GetUsedBytes(sbuf),
02225 hbuf);
02226 if (rv<0) {
02227 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02228 GWEN_Buffer_free(hbuf);
02229 GWEN_Buffer_free(sbuf);
02230 GWEN_Gui_ProgressEnd(pid);
02231 GWEN_MDigest_free(md);
02232 return rv;
02233 }
02234 GWEN_Buffer_free(sbuf);
02235
02236
02237 if (GWEN_Buffer_GetUsedBytes(hbuf)!=20) {
02238 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid size of signed hash (%d)", GWEN_Buffer_GetUsedBytes(hbuf));
02239 GWEN_Buffer_free(hbuf);
02240 GWEN_Gui_ProgressEnd(pid);
02241 GWEN_MDigest_free(md);
02242 return GWEN_ERROR_BAD_DATA;
02243 }
02244 if (memcmp(GWEN_Buffer_GetStart(hbuf), GWEN_MDigest_GetDigestPtr(md), 20)!=0) {
02245 DBG_ERROR(GWEN_LOGDOMAIN, "Invalid hash, data is invalid!");
02246 GWEN_Buffer_free(hbuf);
02247 GWEN_Gui_ProgressEnd(pid);
02248 GWEN_MDigest_free(md);
02249 return GWEN_ERROR_VERIFY;
02250 }
02251 DBG_INFO(GWEN_LOGDOMAIN, "Signature is valid");
02252
02253 GWEN_MDigest_free(md);
02254 GWEN_Buffer_free(hbuf);
02255
02256 GWEN_Gui_ProgressEnd(pid);
02257 }
02258
02259 return 0;
02260 }
02261
02262
02263
02264 int GWEN_Sar_VerifyArchive(const char *inFile, const char *signer, GWEN_CRYPT_KEY *key) {
02265 GWEN_SAR *sr;
02266 int rv;
02267
02268
02269 sr=GWEN_Sar_new();
02270 rv=GWEN_Sar_OpenArchive(sr, inFile,
02271 GWEN_SyncIo_File_CreationMode_OpenExisting,
02272 GWEN_SYNCIO_FILE_FLAGS_READ);
02273 if (rv<0) {
02274 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02275 GWEN_Sar_free(sr);
02276 return rv;
02277 }
02278 else {
02279 GWEN_CRYPTMGR *cm;
02280
02281 cm=GWEN_CryptMgrKeys_new(NULL, NULL, signer, key, 0);
02282
02283
02284 rv=GWEN_Sar_Verify(sr, cm);
02285 if (rv<0) {
02286 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02287 GWEN_CryptMgr_free(cm);
02288 GWEN_Sar_CloseArchive(sr, 1);
02289 GWEN_Sar_free(sr);
02290 return rv;
02291 }
02292 GWEN_CryptMgr_free(cm);
02293
02294
02295 rv=GWEN_Sar_CloseArchive(sr, 0);
02296 if (rv<0) {
02297 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02298 GWEN_Sar_CloseArchive(sr, 1);
02299 GWEN_Sar_free(sr);
02300 return rv;
02301 }
02302 GWEN_Sar_free(sr);
02303 return 0;
02304 }
02305 }
02306
02307
02308
02309 int GWEN_Sar_SignArchive(const char *inFile, const char *signer, GWEN_CRYPT_KEY *key) {
02310 GWEN_SAR *sr;
02311 int rv;
02312
02313
02314 sr=GWEN_Sar_new();
02315 rv=GWEN_Sar_OpenArchive(sr, inFile,
02316 GWEN_SyncIo_File_CreationMode_OpenExisting,
02317 GWEN_SYNCIO_FILE_FLAGS_READ);
02318 if (rv<0) {
02319 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02320 GWEN_Sar_free(sr);
02321 return rv;
02322 }
02323 else {
02324 GWEN_CRYPTMGR *cm;
02325
02326 cm=GWEN_CryptMgrKeys_new(NULL, NULL, signer, key, 0);
02327
02328
02329 rv=GWEN_Sar_Sign(sr, cm);
02330 if (rv<0) {
02331 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02332 GWEN_CryptMgr_free(cm);
02333 GWEN_Sar_CloseArchive(sr, 1);
02334 GWEN_Sar_free(sr);
02335 return rv;
02336 }
02337 GWEN_CryptMgr_free(cm);
02338
02339
02340 rv=GWEN_Sar_CloseArchive(sr, 0);
02341 if (rv<0) {
02342 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02343 GWEN_Sar_CloseArchive(sr, 1);
02344 GWEN_Sar_free(sr);
02345 return rv;
02346 }
02347 GWEN_Sar_free(sr);
02348 return 0;
02349 }
02350 }
02351
02352
02353
02354 int GWEN_Sar_CheckArchive(const char *inFile) {
02355 GWEN_SAR *sr;
02356 int rv;
02357 const GWEN_SAR_FILEHEADER_LIST *fhl;
02358
02359
02360 sr=GWEN_Sar_new();
02361 rv=GWEN_Sar_OpenArchive(sr, inFile,
02362 GWEN_SyncIo_File_CreationMode_OpenExisting,
02363 GWEN_SYNCIO_FILE_FLAGS_READ);
02364 if (rv<0) {
02365 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02366 return rv;
02367 }
02368
02369 fhl=GWEN_Sar_GetHeaders(sr);
02370 if (fhl) {
02371 const GWEN_SAR_FILEHEADER *fh;
02372 uint32_t pid;
02373
02374 pid=GWEN_Gui_ProgressStart(GWEN_GUI_PROGRESS_DELAY |
02375 GWEN_GUI_PROGRESS_SHOW_ABORT |
02376 GWEN_GUI_PROGRESS_ALLOW_EMBED |
02377 GWEN_GUI_PROGRESS_SHOW_PROGRESS,
02378 I18N("File Operation"),
02379 I18N("Checking archive file"),
02380 GWEN_SarFileHeader_List_GetCount(fhl),
02381 0);
02382
02383 fh=GWEN_SarFileHeader_List_First(fhl);
02384 while(fh) {
02385 const char *s;
02386
02387 s=GWEN_SarFileHeader_GetPath(fh);
02388 rv=GWEN_Sar_CheckFile(sr, fh);
02389 if (rv<0) {
02390 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02391 GWEN_Gui_ProgressEnd(pid);
02392 GWEN_Sar_CloseArchive(sr, 1);
02393 GWEN_Sar_free(sr);
02394 }
02395
02396 rv=GWEN_Gui_ProgressAdvance(pid, GWEN_GUI_PROGRESS_ONE);
02397 if (rv<0) {
02398 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
02399 GWEN_Gui_ProgressEnd(pid);
02400 GWEN_Sar_CloseArchive(sr, 1);
02401 GWEN_Sar_free(sr);
02402 return rv;
02403 }
02404
02405 fh=GWEN_SarFileHeader_List_Next(fh);
02406 }
02407 GWEN_Gui_ProgressEnd(pid);
02408 }
02409
02410 rv=GWEN_Sar_CloseArchive(sr, 0);
02411 if (rv<0) {
02412 fprintf(stderr, "Error closing archive (%d)\n", rv);
02413 return 2;
02414 }
02415 GWEN_Sar_free(sr);
02416
02417 return 0;
02418 }
02419
02420
02421