"Fossies" - the Fresh Open Source Software Archive

Member "unipkg-0.6.5/unipkglib/unipkg-deb.c" (16 Dec 2005, 19800 Bytes) of package /linux/privat/old/unipkg-0.6.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.


    1 /******************************************************************************\
    2 *                                                                              *
    3 * UNIPKG (c) iSteve <isteve@bofh.cz>, 2005                                     *
    4 *                                                                              *
    5 * Universal PacKaGer.                                                          *
    6 * Licensed under GNU/GPL - if you don't like the software, fix it!             *
    7 *                                                                              *
    8 \******************************************************************************/
    9 
   10 ///////////////////////////////////////////////////////////////////////////////
   11 //                                                                           //
   12 // B A S E   I N C L U S I O N S   A N D   D E F I N I T I O N S             //
   13 //                                                                           //
   14 ///////////////////////////////////////////////////////////////////////////////
   15 #define _GNU_SOURCE
   16 #include <stdlib.h>
   17 #include <stdio.h>
   18 #include <string.h>
   19 #include <unistd.h>
   20 #include <fcntl.h>
   21 #include <sys/types.h>
   22 #include <sys/mman.h>
   23 #include <sys/stat.h>
   24 
   25 #ifdef HAVE_SYSMACROS_H
   26 #include <sys/sysmacros.h>
   27 #endif
   28 
   29 #include <errno.h>
   30 #include <zlib.h>
   31 
   32 #include "../archive.h"
   33 #include "../common.h"
   34 #include "../compression.h"
   35 
   36 #define DEBCTLRBUFS 512
   37 #define DEB_MAGIC       "!<arch>\ndebian-binary"
   38 #define DEB_MAGICSIZE   21
   39 
   40 #define ARMAGIC         "!<arch>\n"
   41 #define ARMAGICLEN  8
   42 
   43 #define ADMINMEMBER                     "control.tar.gz  "
   44 #define ADMINMEMBER_COMPAT          "control.tar.gz/ "
   45 #define DATAMEMBER_GZ                   "data.tar.gz     "
   46 #define DATAMEMBER_COMPAT_GZ        "data.tar.gz/    "
   47 #define DATAMEMBER_BZ2                  "data.tar.bz2    "
   48 #define DATAMEMBER_COMPAT_BZ2       "data.tar.bz2/   "
   49 #define DATAMEMBER_CAT              "data.tar        "
   50 #define DATAMEMBER_COMPAT_CAT   "data.tar/       "
   51 
   52 ///////////////////////////////////////////////////////////////////////////////
   53 //                                                                           //
   54 // B A S E   F U N C T I O N S                                               //
   55 //                                                                           //
   56 ///////////////////////////////////////////////////////////////////////////////
   57 
   58 // GETCTRLHDR()
   59 //
   60 // Gets a value from debian's control file
   61 //
   62 // Parameters:
   63 //   the whole control file
   64 //   the header we look for
   65 //   the size of the control file
   66 //
   67 // Return value:
   68 //   malloced string
   69 static char *getctrlhdr(char *fullfile, char *hdr, off_t size) {
   70     char *start, *end, *tar;
   71     
   72     if ((start = pstrnstr(fullfile, hdr, size, 0)) == NULL) {
   73         return NULL;
   74     }
   75     if (start != fullfile) {    // Is it at the start of the file?
   76         if (*(start-1) != '\n') {   // No? And is it on a new line?
   77             return NULL;            // No? Baibai.
   78         }
   79     }
   80     start = start + strlen(hdr);
   81     
   82     while ((*start == ' ') && (start < fullfile+size)) { start++; } // Skip all spaces after the start, since there may be issues.
   83     
   84     if ((end = pstrnstr(start, "\n", size, 0)) == NULL) {
   85         return NULL;
   86     }
   87     tar = malloc((int)end - (int)start + 1);
   88     strncpy(tar, start, (int)end - (int)start);
   89     tar[(int)end - (int)start] = 0x0;
   90     return tar;
   91 }
   92 
   93 // SWITCH_CONTROL_NAMES()
   94 //
   95 // Identifies the filename as member of control archive.
   96 //
   97 // Parameters:
   98 //   the filename
   99 //
  100 // Return value:
  101 //   0 if control
  102 //   1 if preinst script
  103 //   2 if postinst script
  104 //   3 if prerm script
  105 //   4 if postrm script
  106 //   -1 if none of above (eg. md5sum)
  107 static int switch_control_names(char *fn) {
  108     char *bn;
  109     
  110     bn = basename(fn);
  111     if (!strcmp(bn, "control")) { return 0; }
  112     if (!strcmp(bn, "preinst")) { return 1; }
  113     if (!strcmp(bn, "postinst")) { return 2; }
  114     if (!strcmp(bn, "prerm")) { return 3; }
  115     if (!strcmp(bn, "postrm")) { return 4; }
  116     
  117     return -1;
  118 }
  119 
  120 // SWITCH_DEB_NAMES()
  121 //
  122 // Switches names of members or ar archive in debian package.
  123 //
  124 // Parameters:
  125 //   the filename we are checking
  126 //
  127 // Return value:
  128 //   0 if control
  129 //   1 if gzipped data
  130 //   2 if bzip2ed data
  131 //   3 if uncompressed data
  132 static int switch_deb_names(char *fn) {
  133     if ((!strcmp(fn, ADMINMEMBER)) || (!strcmp(fn, ADMINMEMBER_COMPAT))) { return 0; }
  134     if ((!strcmp(fn, DATAMEMBER_GZ)) || (!strcmp(fn, DATAMEMBER_COMPAT_GZ))) { return 1; }
  135     if ((!strcmp(fn, DATAMEMBER_BZ2)) || (!strcmp(fn, DATAMEMBER_COMPAT_BZ2))) { return 2; }
  136     if ((!strcmp(fn, DATAMEMBER_CAT)) || (!strcmp(fn, DATAMEMBER_COMPAT_CAT))) { return 3; }
  137     
  138     return -1;
  139 }
  140 
  141 ///////////////////////////////////////////////////////////////////////////////
  142 //                                                                           //
  143 // A P I   F U N C T I O N S                                                 //
  144 //                                                                           //
  145 ///////////////////////////////////////////////////////////////////////////////
  146 
  147 int identify(packdef pdef) {
  148     char    buf[DEB_MAGICSIZE];
  149     off_t   curpos;
  150     
  151     if ((curpos = ftell(pdef.filepointer)) == -1) {
  152         return 2;
  153     }
  154     if (fseek(pdef.filepointer, 0, SEEK_SET)) {
  155         return 2;
  156     }
  157     
  158     if (!fread(buf, DEB_MAGICSIZE, 1, pdef.filepointer)) {
  159         return 2;
  160     }
  161     
  162     if (fseek(pdef.filepointer, curpos, SEEK_SET)) {
  163         return 2;
  164     }
  165     
  166     if (memcmp(buf, DEB_MAGIC, DEB_MAGICSIZE) == 0) {
  167         return 0;
  168     }
  169     else {
  170         return 1;
  171     }
  172 }
  173 
  174 int pkgdetails(packdef pdef, pkginfo *pinfo) {
  175     int             err;
  176     
  177     void            *filemap;
  178     off_t               offset;
  179     
  180     off_t               fsize;
  181     struct stat     statbuf;
  182 
  183     char            *fullfile;
  184     
  185     char            *obuf;
  186     unsigned long   obuflen;
  187     
  188     int             archive_file;
  189     c_compdata      cstream;
  190     comarchive      *tar_archive, *ar_archive;
  191     
  192     fstat(fileno(pdef.filepointer), &statbuf);
  193     fsize = statbuf.st_size;
  194     
  195     filemap = mmap(0, fsize, PROT_READ, MAP_SHARED, fileno(pdef.filepointer), 0);
  196     if (filemap == MAP_FAILED) { return 1; }
  197     
  198     offset = 0;
  199     if (memcmp(filemap + offset, ARMAGIC, ARMAGICLEN)) { return 1; }
  200     offset += ARMAGICLEN;
  201     
  202     pinfo->files=NULL;
  203     pinfo->filecount = 0;
  204     
  205     ar_archive = init_archive(AT_AR);
  206     do {
  207         if (*((char*)filemap + offset) == '\n') { offset++; }
  208         update_nextblock(ar_archive);
  209         if (ar_archive->stage == AS_HEADER)
  210             clear_archive_member(ar_archive);
  211         
  212         err = parse_block(ar_archive, filemap + offset);
  213         
  214         if (err)
  215             break;
  216         
  217         offset += ar_archive -> nextblock;
  218         
  219         // We are "unpacking" them right away, because we mmap it...
  220         update_upfilesize(ar_archive);
  221         
  222         archive_file = switch_deb_names(ar_archive->name);
  223         switch (archive_file) {
  224 /*****************************************************************************\
  225 * Control -- GZIP                                                             *
  226 \*****************************************************************************/
  227             case 0:
  228                 obuflen = 512;
  229                 obuf = malloc(obuflen);
  230             
  231                 err = decompression_setup(&cstream, filemap, offset, ar_archive->filesize, obuf, obuflen, C_GZIP);
  232                 fullfile = NULL;
  233                 
  234                 if ((decompression_init(&cstream) != CE_OK) || (err != CE_OK)) {
  235                     // A corrupted control archive.
  236                     decompression_cleanup(&cstream);
  237                     munmap(filemap, fsize);
  238                     free(obuf);
  239                     return 1;
  240                 }
  241                 
  242                 tar_archive = init_archive(AT_TAR);
  243                 do {
  244                     if (tar_archive->stage == AS_NEWFILE) {
  245                         if (switch_control_names(tar_archive->name) != -1)
  246                             fullfile = malloc(tar_archive->filesize);
  247                     }
  248                     
  249                     update_nextblock(tar_archive);
  250                     if (tar_archive->nextblock > obuflen) {
  251                         obuflen = tar_archive->nextblock;
  252                         obuf = realloc(obuf, obuflen);
  253                     }
  254                     
  255                     if (decompression_decompress(&cstream, tar_archive->nextblock, obuf) != CE_OK)
  256                         break;
  257                     
  258                     if (decompression_ammount_not_processed(&cstream) > 0)
  259                         break;
  260                     
  261                     update_stage(tar_archive);
  262                     
  263                     switch (tar_archive->stage) {
  264                         case AS_DATA:
  265                             if (fullfile != NULL) {
  266                                 memcpy(fullfile + tar_archive->upfilesize, obuf, ((tar_archive->filesize - tar_archive->upfilesize) > tar_archive->nextblock) ? tar_archive->nextblock : tar_archive->filesize - tar_archive->upfilesize);
  267                             }
  268                             
  269                             update_upfilesize(tar_archive);
  270                             break;
  271                         case AS_HEADER:
  272                             if (fullfile != NULL) {
  273                                 switch (switch_control_names(tar_archive->name)) {
  274                                     case 0:
  275                                         pinfo->name = getctrlhdr(fullfile, "Package:", tar_archive->filesize);
  276                                         pinfo->version = getctrlhdr(fullfile, "Version:", tar_archive->filesize);
  277                                         pinfo->description = getctrlhdr(fullfile, "Description:", tar_archive->filesize);
  278                                         break;
  279                                     case 1:
  280                                         pinfo->preinst.data = malloc(tar_archive->filesize);
  281                                         pinfo->preinst.len = tar_archive->filesize;
  282                                         memcpy(pinfo->preinst.data, fullfile, tar_archive->filesize);
  283                                         break;
  284                                     case 2:
  285                                         pinfo->postinst.data = malloc(tar_archive->filesize);
  286                                         pinfo->postinst.len = tar_archive->filesize;
  287                                         memcpy(pinfo->postinst.data, fullfile, tar_archive->filesize);
  288                                         break;
  289                                     case 3:
  290                                         pinfo->prerm.data = malloc(tar_archive->filesize);
  291                                         pinfo->prerm.len = tar_archive->filesize;
  292                                         memcpy(pinfo->prerm.data, fullfile, tar_archive->filesize);
  293                                         break;
  294                                     case 4:
  295                                         pinfo->postrm.data = malloc(tar_archive->filesize);
  296                                         pinfo->postrm.len = tar_archive->filesize;
  297                                         memcpy(pinfo->postrm.data, fullfile, tar_archive->filesize);
  298                                         break;
  299                                 }
  300                                 
  301                                 free(fullfile);
  302                                 fullfile = NULL;
  303                             }
  304                             
  305                             clear_archive_member(tar_archive);
  306                             break;
  307                     }
  308                     
  309                     err = parse_block(tar_archive, obuf);
  310                     
  311                     if (err)
  312                         break;
  313                 } while (decompression_ammount_left(&cstream, 0) > 0);
  314                 
  315                 deinit_archive(tar_archive);
  316                 decompression_cleanup(&cstream);
  317             
  318                 free(obuf);
  319                 break;
  320 
  321 /*****************************************************************************\
  322 * Data -- GZIP, BZIP2, UNCOMPRESSED                                           *
  323 \*****************************************************************************/
  324             case 1:
  325             case 2:
  326             case 3:
  327                 obuflen = 512;
  328                 obuf = malloc(obuflen);
  329                 
  330                 err = CE_OK;
  331             
  332                 switch (archive_file) {
  333                     case 1:
  334                         err = decompression_setup(&cstream, filemap, offset, ar_archive->filesize, obuf, obuflen, C_GZIP);
  335                         break;
  336                     case 2:
  337                         err = decompression_setup(&cstream, filemap, offset, ar_archive->filesize, obuf, obuflen, C_BZIP2);
  338                         break;
  339                     case 3:
  340                         err = decompression_setup(&cstream, filemap, offset, ar_archive->filesize, obuf, obuflen, C_NONE);
  341                         break;
  342                 }
  343                 
  344                 if ((decompression_init(&cstream) != CE_OK) || (err != CE_OK)) {
  345                     // A corrupted file archive.
  346                     decompression_cleanup(&cstream);
  347                     munmap(filemap, fsize);
  348                     free(obuf);
  349                     deinit_archive(ar_archive);
  350                     return 1;
  351                 }
  352                 
  353                 tar_archive = init_archive(AT_TAR);
  354                 do {
  355                     if (tar_archive->stage == AS_NEWFILE) {
  356                         addfile(pinfo, absolutizestr(tar_archive->name, "/"), (tar_archive->ftype == AF_DIRECTORY) ? F_DIRECTORY : F_REGULAR);
  357                         pinfo->pkgsize += tar_archive->filesize;
  358                     }
  359                     
  360                     update_nextblock(tar_archive);
  361                     if (tar_archive->nextblock > obuflen) {
  362                         obuflen = tar_archive->nextblock;
  363                         obuf = realloc(obuf, obuflen);
  364                     }
  365                     
  366                     if (decompression_decompress(&cstream, tar_archive->nextblock, obuf) != CE_OK)
  367                         break;
  368                     
  369                     if (decompression_ammount_not_processed(&cstream) > 0)
  370                         break;
  371                     
  372                     update_stage(tar_archive);
  373                     
  374                     switch (tar_archive->stage) {
  375                         case AS_DATA:
  376                             update_upfilesize(tar_archive);
  377                             // Perform data handling when actually unpacking stuff
  378                             break;
  379                         case AS_HEADER:
  380                             clear_archive_member(tar_archive);
  381                             break;
  382                     }
  383                     
  384                     err = parse_block(tar_archive, obuf);
  385                     
  386                     if (err)
  387                         break;
  388                 } while (decompression_ammount_left(&cstream, 0) > 0);
  389                 
  390                 deinit_archive(tar_archive);
  391                 decompression_cleanup(&cstream);
  392                 
  393                 free(obuf);         
  394                 break;
  395         }
  396         
  397         offset += ar_archive->filesize;
  398     } while (offset < fsize - 1);
  399     deinit_archive(ar_archive);
  400     
  401     munmap(filemap, fsize);
  402     
  403     if (pinfo->description == NULL) { pinfo->description = strdup("Debian package, no description."); }
  404     if (pinfo->version == NULL) { pinfo->version = strdup("unknown"); }
  405     if (pinfo->name == NULL) { return 1; }
  406     
  407     // These are various parameters to be used in various cases with the handling scripts.
  408     // They are only given if the script exists.
  409     if (pinfo->preinst.data != NULL) {
  410         pinfo->preinst.parameters[A_IRRELEVANT] = strdup("configure");
  411         pinfo->preinst.parameters[A_UPGRADE] = strdup("upgrade");
  412         pinfo->preinst.parameters[A_DOWNGRADE] = strdup("upgrade");
  413         pinfo->preinst.parameters[A_REINSTALL] = strdup("upgrade");
  414     }
  415 
  416     if (pinfo->postinst.data != NULL) {
  417         pinfo->postinst.parameters[A_IRRELEVANT] = strdup("configure");
  418         pinfo->postinst.parameters[A_UPGRADE] = strdup("upgrade");
  419         pinfo->postinst.parameters[A_DOWNGRADE] = strdup("upgrade");
  420         pinfo->postinst.parameters[A_REINSTALL] = strdup("upgrade");
  421     }
  422 
  423     if (pinfo->prerm.data != NULL) {
  424         pinfo->prerm.parameters[A_IRRELEVANT] = strdup("remove");
  425         pinfo->prerm.parameters[A_REMOVE] = strdup("remove");
  426         pinfo->prerm.parameters[A_UPGRADE] = strdup("upgrade");
  427         pinfo->prerm.parameters[A_DOWNGRADE] = strdup("upgrade");
  428         pinfo->prerm.parameters[A_REINSTALL] = strdup("upgrade");
  429     }
  430 
  431     if (pinfo->postrm.data != NULL) {
  432         pinfo->postrm.parameters[A_IRRELEVANT] = strdup("remove");
  433         pinfo->postrm.parameters[A_REMOVE] = strdup("remove");
  434         pinfo->postrm.parameters[A_UPGRADE] = strdup("upgrade");
  435         pinfo->postrm.parameters[A_DOWNGRADE] = strdup("upgrade");
  436         pinfo->postrm.parameters[A_REINSTALL] = strdup("upgrade");
  437     }
  438     
  439     return 0;
  440 }
  441 
  442 int pkginstall(packdef pdef) {
  443     FILE                *fpout;
  444     int             err;
  445     void            *filemap;
  446     off_t               fsize;
  447     struct stat     statbuf;
  448     
  449     char            *curpath;
  450     char            *obuf;
  451     unsigned long   obuflen;
  452     
  453     off_t               offset;
  454     int                 archive_file;
  455 
  456     c_compdata      cstream;
  457     comarchive      *tar_archive, *ar_archive;
  458 
  459     fstat(fileno(pdef.filepointer), &statbuf);
  460     fsize = statbuf.st_size;
  461     
  462     curpath = NULL;
  463     fpout = NULL;
  464     filemap = NULL;
  465     filemap = mmap(0, fsize, PROT_READ, MAP_SHARED, fileno(pdef.filepointer), 0);
  466     if (filemap == MAP_FAILED) { return 1; }
  467     
  468     offset = 0;
  469     if (memcmp(filemap + offset, ARMAGIC, ARMAGICLEN)) { return 1; }
  470     offset += ARMAGICLEN;
  471 
  472     ar_archive = init_archive(AT_AR);
  473     do {
  474         if (*((char*)filemap + offset) == '\n') { offset++; }
  475         
  476         update_nextblock(ar_archive);
  477         update_stage(ar_archive);
  478         if (ar_archive->stage == AS_HEADER)
  479             clear_archive_member(ar_archive);
  480         
  481         err = parse_block(ar_archive, filemap + offset);
  482         
  483         if (err)
  484             break;
  485         
  486         offset += ar_archive -> nextblock;
  487         
  488         // We are "unpacking" them right away, because we mmap it...
  489         ar_archive -> upfilesize = ar_archive -> filesize;
  490         
  491         archive_file = switch_deb_names(ar_archive->name);
  492         switch (archive_file) {
  493 /*****************************************************************************\
  494 * Control -- GZIP                                                             *
  495 \*****************************************************************************/
  496             case 0:
  497                 // We don't care.
  498                 break;
  499 
  500 /*****************************************************************************\
  501 * Data -- GZIP, BZIP2, UNCOMPRESSED                                           *
  502 \*****************************************************************************/
  503             case 1:
  504             case 2:
  505             case 3:
  506                 obuflen = 512;
  507                 obuf = malloc(obuflen);
  508             
  509                 err = CE_OK;
  510             
  511                 switch (archive_file) {
  512                     case 1:
  513                         err = decompression_setup(&cstream, filemap, offset, ar_archive->filesize, obuf, obuflen, C_GZIP);
  514                         break;
  515                     case 2:
  516                         err = decompression_setup(&cstream, filemap, offset, ar_archive->filesize, obuf, obuflen, C_BZIP2);
  517                         break;
  518                     case 3:
  519                         err = decompression_setup(&cstream, filemap, offset, ar_archive->filesize, obuf, obuflen, C_NONE);
  520                         break;
  521                 }
  522                 
  523                 if ((err != CE_OK) || (decompression_init(&cstream))) {
  524                     // A corrupted file archive.
  525                     decompression_cleanup(&cstream);
  526                     munmap(filemap, fsize);
  527                     free(obuf);
  528                     deinit_archive(ar_archive);
  529                     return 1;
  530                 }
  531                 
  532                 tar_archive = init_archive(AT_TAR);
  533                 do {
  534                     if (tar_archive->stage == AS_NEWFILE) {
  535                         free(curpath);
  536                         curpath = absolutizestr(tar_archive->name, pdef.destdir);
  537                         // Create relevant files
  538                         switch (tar_archive->ftype) {
  539                             case AF_REGULAR:
  540                                     if (fpout != NULL) { 
  541                                         fclose(fpout);
  542                                     }
  543                                     if ((fpout = fopen(curpath, "w")) == NULL) {
  544                                         free(curpath);
  545                                         free(obuf);
  546                                         decompression_cleanup(&cstream);
  547                                         munmap(filemap, fsize);
  548                                         deinit_archive(tar_archive);
  549                                         deinit_archive(ar_archive);
  550                                         return 2;
  551                                     }
  552                                     
  553                                     FCHOWNMOD(fileno(fpout), tar_archive->mode, tar_archive->uid, tar_archive->gid);
  554                                     
  555                                     if (tar_archive->filesize == 0) {
  556                                         // Nothing to write. We just created it.
  557                                         fclose(fpout);
  558                                         fpout = NULL;
  559                                         
  560                                         // For SUID and SGID; fchown + file open for writing + suid/sgid = suid/sgid may be ignored
  561                                         CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
  562                                     }
  563                                 break;
  564                             case AF_SYMLINK:
  565                                     symlink(tar_archive->linktarget, curpath);
  566                                     CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
  567                                 break;
  568                             case AF_DEVNODE:
  569                                     mknod(curpath, tar_archive->mode, makedev(tar_archive->dmajor, tar_archive->dminor));
  570                                     CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
  571                                 break;
  572                             case AF_FIFOBUF:
  573                                     mkfifo(curpath, tar_archive->mode);
  574                                     CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
  575                                 break;
  576                             case AF_DIRECTORY:
  577                                     if (stat(curpath, &statbuf)) {
  578                                         mkdir(curpath, tar_archive->mode);
  579                                         CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
  580                                     }
  581                                 break;
  582                         }
  583                     }
  584                     
  585                     update_nextblock(tar_archive);
  586                     if (tar_archive->nextblock > obuflen) {
  587                         obuflen = tar_archive->nextblock;
  588                         obuf = realloc(obuf, obuflen);
  589                     }
  590                     
  591                     if (decompression_decompress(&cstream, tar_archive->nextblock, obuf) != CE_OK)
  592                         break;
  593                     
  594                     if (decompression_ammount_not_processed(&cstream) > 0)
  595                         break;
  596                     
  597                     update_stage(tar_archive);
  598                     
  599                     switch (tar_archive->stage) {
  600                         case AS_DATA:
  601                             // Feed data...
  602                             if (tar_archive->ftype == AF_REGULAR) {
  603                                 if (fpout != NULL) {
  604                                     fwrite(obuf, ((tar_archive->filesize - tar_archive->upfilesize) > tar_archive->nextblock) ? tar_archive->nextblock : tar_archive->filesize - tar_archive->upfilesize, 1, fpout);
  605                                 }
  606                             }
  607                             
  608                             update_upfilesize(tar_archive);
  609                             break;
  610                         case AS_HEADER:
  611                             // Clear up...
  612                             if (tar_archive->ftype == AF_REGULAR) {
  613                                 if (fpout != NULL) {
  614                                     fsync(fileno(fpout));
  615                                     fclose(fpout);
  616                                     fpout = NULL;
  617                                     
  618                                     // For SUID and SGID; fchown + file open for writing + suid/sgid = suid/sgid may be ignored
  619                                     CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
  620                                 }
  621                             }
  622                             clear_archive_member(tar_archive);
  623                             break;
  624                     }
  625                     
  626                     err = parse_block(tar_archive, obuf);
  627                     
  628                     if (err)
  629                         break;
  630                 } while (decompression_ammount_left(&cstream, 0));
  631                 deinit_archive(tar_archive);
  632                 
  633                 decompression_cleanup(&cstream);
  634                 free(curpath);
  635                 free(obuf);         
  636                 break;
  637         }   
  638         
  639         offset += ar_archive->filesize;
  640     } while (offset < fsize - 1);
  641     deinit_archive(ar_archive);
  642     munmap(filemap, fsize);
  643     
  644     return 0;
  645 }