gwenhywfar  4.3.1
sar.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  begin       : Wed Jun 22 2011
00003  copyright   : (C) 2011 by Martin Preuss
00004  email       : martin@libchipcard.de
00005 
00006  ***************************************************************************
00007  *                                                                         *
00008  *   This library is free software; you can redistribute it and/or         *
00009  *   modify it under the terms of the GNU Lesser General Public            *
00010  *   License as published by the Free Software Foundation; either          *
00011  *   version 2.1 of the License, or (at your option) any later version.    *
00012  *                                                                         *
00013  *   This library is distributed in the hope that it will be useful,       *
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00016  *   Lesser General Public License for more details.                       *
00017  *                                                                         *
00018  *   You should have received a copy of the GNU Lesser General Public      *
00019  *   License along with this library; if not, write to the Free Software   *
00020  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00021  *   MA  02111-1307  USA                                                   *
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     /* flush */
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   /* disconnect */
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   /* header version */
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   /* status */
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   /* flags */
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   /* path */
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   /* file type */
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   /* permissions */
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   /* atime */
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   /* mtime */
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   /* ctime */
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   /* file size */
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   /* create TLV header */
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   /* write TLV header */
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   /* copy file if fsize>0 */
00519   if (fsize>0) {
00520     GWEN_SYNCIO *sio;
00521     uint32_t pid;
00522 
00523     /* open input file */
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       /* read from input */
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       /* digest data */
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       /* write to archive */
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       /* advance progress bar */
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     } /* while */
00604     GWEN_Gui_ProgressEnd(pid);
00605 
00606     /* close input file */
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   /* read link content */
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   /* create TLV header */
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   /* write TLV */
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   /* digest data */
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   /* stat file to be added */
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   /* create and setup file header */
00729   fh=GWEN_SarFileHeader_new();
00730 
00731   /* path */
00732   GWEN_SarFileHeader_SetPath(fh, fname);
00733 
00734   /* file type */
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   /* permissions */
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   /* atime */
00778   ti=GWEN_Time_fromSeconds(st.st_atime);
00779   GWEN_SarFileHeader_SetAtime(fh, ti);
00780 
00781   /* mtime */
00782   ti=GWEN_Time_fromSeconds(st.st_mtime);
00783   GWEN_SarFileHeader_SetMtime(fh, ti);
00784 
00785   /* ctime */
00786   ti=GWEN_Time_fromSeconds(st.st_ctime);
00787   GWEN_SarFileHeader_SetCtime(fh, ti);
00788 
00789   /* file size */
00790   GWEN_SarFileHeader_SetFileSize(fh, st.st_size);
00791 
00792 
00793   /* prepare header */
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   /* create TLV header for file header */
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   /* insert TLV header into file header buffer */
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   /* seek to end of file */
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   /* write header into archive file */
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   /* prepare digest */
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   /* digest header */
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   /* copy file into archive */
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   /* finish hash */
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   /* create hash TLV */
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   /* write hash into archive file */
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   /* done */
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   /* scan all TLV elements */
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     /* read start of fileheader TLV */
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     /* got it, now calculate start of tag data */
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     /* seek to start of header data */
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     /* now read or skip info */
00979     if (tagType==GWEN_SAR_TAG_HEADER) {
00980       GWEN_SAR_FILEHEADER *fh;
00981       const char *s;
00982 
00983       /* alloc memory for data */
00984       GWEN_Buffer_AllocRoom(mbuf, tagLength);
00985 
00986       /* read header data */
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       /* now parse header */
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       /* only store position of file data */
01032       GWEN_SarFileHeader_SetDataPos(lastHeader, startOfTagData);
01033       GWEN_SarFileHeader_SetDataSize(lastHeader, tagLength);
01034 
01035       /* skip data */
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       /* only store position of file data */
01050       GWEN_SarFileHeader_SetHashPos(lastHeader, startOfTagData);
01051 
01052       /* skip data */
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       /* only store position of file data */
01062       DBG_INFO(GWEN_LOGDOMAIN, "Signature found");
01063       sr->signaturePos=startOfTagData;
01064       sr->signatureSize=tagLength;
01065 
01066       /* skip data */
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       /* just skip data */
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   } /* for */
01088 
01089   /* done */
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     /* seek to start of header */
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     /* digest TLV */
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   /* copy file if fsize>0 */
01164   if (1) {
01165     GWEN_SYNCIO *sio=NULL;
01166     uint32_t pid;
01167 
01168     /* open input file */
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       /* seek to start of data */
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       /* start extracting */
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         /* read from input */
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         /* digest data */
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           /* write to archive */
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         /* advance progress bar */
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       } /* while */
01284       GWEN_Gui_ProgressEnd(pid);
01285     }
01286 
01287     if (!checkOnly) {
01288       /* close output file */
01289       GWEN_SyncIo_Disconnect(sio);
01290       GWEN_SyncIo_free(sio);
01291     }
01292 
01293     /* finish hash */
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     /* read and check hash */
01302     mpos=GWEN_SarFileHeader_GetHashPos(fh);
01303     if (mpos) {
01304       GWEN_BUFFER *mbuf;
01305   
01306       /* seek to end of file */
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       /* read 20 bytes of hash */
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); /* not FileSize!! */
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     /* seek to header pos */
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     /* digest header TLV */
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   /* seek to data pos */
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   /* copy file if fsize>0 */
01430   if (fsize>0) { /* fsize is the size of the file tag data */
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     /* digest TLV */
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       /* owner perms */
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 /* CHMOD on symlinks doesn't work */
01475 
01476       /* group perms */
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       /* other perms */
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   /* finish hash */
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   /* read and check hash */
01518   mpos=GWEN_SarFileHeader_GetHashPos(fh);
01519   if (mpos) {
01520     GWEN_BUFFER *mbuf;
01521 
01522     /* seek to end of file */
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     /* read 20 bytes of hash */
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); /* not FileSize!! */
01600   dpos=GWEN_SarFileHeader_GetDataPos(fh);
01601 
01602   hpos=GWEN_SarFileHeader_GetHeaderStartPos(fh);
01603   hsize=GWEN_SarFileHeader_GetHeaderSize(fh);
01604   assert(hsize);
01605 
01606   /* seek to end of file */
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   /* digest TLV */
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   /* finish hash */
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   /* read and check hash */
01646   mpos=GWEN_SarFileHeader_GetHashPos(fh);
01647   if (mpos) {
01648     GWEN_BUFFER *mbuf;
01649 
01650     /* seek to end of file */
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     /* read 20 bytes of hash */
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     /* owner perms */
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     /* group perms */
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     /* other perms */
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     /* create folder */
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   /* open archive file */
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   /* change to "where" */
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   /* get current working dir */
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   /* change back to previous pwd */
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     /* clear SIGNED flags */
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     /* calculate hash over all file hashes */
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         /* seek to start of hash */
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         /* read hash */
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         /* digest hash */
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     /* finish hash */
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     /* sign hash */
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     /* create signature TLV */
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     /* seek to end of file */
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     /* write TLV into archive file */
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     /* clear SIGNED flags */
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     /* calculate hash over all file hashes */
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         /* seek to start of hash */
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         /* read hash */
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         /* digest hash */
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     /* finish hash */
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     /* seek to start of signature data */
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     /* read signature data */
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     /* verify signature */
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     /* verify hash */
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   /* open archive file */
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     /* verify */
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     /* close archive */
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   /* open archive file */
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     /* verify */
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     /* close archive */
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   /* open archive file */
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