"Fossies" - the Fresh Open Source Software Archive

Member "unipkg-0.6.5/unipkglib/unipkg-arch.c" (16 Dec 2005, 13944 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.

    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 ///////////////////////////////////////////////////////////////////////////////
   37 //                                                                           //
   38 // B A S E   F U N C T I O N S                                               //
   39 //                                                                           //
   40 ///////////////////////////////////////////////////////////////////////////////
   41 
   42 // SWITCH_CONTROL_NAMES()
   43 //
   44 // Identifies the filename as a significant file.
   45 //
   46 // Parameters:
   47 //   the filename
   48 //
   49 // Return value:
   50 //   0 if .PKGINFO
   51 //   1 if .FILELIST
   52 //   2 if .INSTALL or ._install
   53 //   -1 if none of above (eg. md5sum)
   54 //   -2 if none of above, but matches "\.[A-Z]*"
   55 static int switch_control_names(char *fn) {
   56     char *bn;
   57     
   58     bn = basename(fn);
   59     if (!strcmp(basename(fn), ".PKGINFO")) { return 0; }
   60     if (!strcmp(basename(fn), ".FILELIST")) { return 1; }
   61     if ((!strcmp(basename(fn), ".INSTALL")) || (!strcmp(basename(fn), "._install"))) { return 2; }
   62     return -1;
   63 }
   64 
   65 // GETPKGINFOHDR()
   66 //
   67 // Gets a value from arch's pkginfo file
   68 //
   69 // Parameters:
   70 //   the whole control file
   71 //   the header we look for
   72 //   the size of the control file
   73 //
   74 // Return value:
   75 //   malloced string
   76 static char *getpkginfohdr(char *fullfile, char *hdr, off_t size) {
   77     char *start, *end, *tar;
   78     
   79     if ((start = pstrnstr(fullfile, hdr, size, 0)) == NULL) {
   80         return NULL;
   81     }
   82     if (start != fullfile) {    // Is it at the start of the file?
   83         if (*(start-1) != '\n') {   // No? And is it on a new line?
   84             return NULL;            // No? Baibai.
   85         }
   86     }
   87     start = start + strlen(hdr);
   88     
   89     while ((*start == ' ') && (start < fullfile+size)) { start++; } // Skip all spaces after the start, since there may be issues.
   90     if (start == fullfile + size) return NULL;
   91     if (*start == '=') start++;
   92     if (start == fullfile + size) return NULL;
   93     while ((*start == ' ') && (start < fullfile+size)) { start++; } // Skip all spaces after the equation
   94     
   95     if ((end = pstrnstr(start, "\n", size, 0)) == NULL) {
   96         return NULL;
   97     }
   98     tar = malloc((int)end - (int)start + 1);
   99     strncpy(tar, start, (int)end - (int)start);
  100     tar[(int)end - (int)start] = 0x0;
  101     return tar;
  102 }
  103 
  104 ///////////////////////////////////////////////////////////////////////////////
  105 //                                                                           //
  106 // A P I   F U N C T I O N S                                                 //
  107 //                                                                           //
  108 ///////////////////////////////////////////////////////////////////////////////
  109 
  110 int identify(packdef pdef) {
  111     c_compdata      cstream;
  112     comarchive      *tar_archive;
  113     struct stat     statbuf;
  114     void            *filemap;
  115     
  116     char            *obuf;
  117     unsigned long   obuflen;
  118     
  119     int                 err;
  120     
  121     fstat(fileno(pdef.filepointer), &statbuf);
  122     filemap = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fileno(pdef.filepointer), 0);
  123     if (filemap == MAP_FAILED) { return 2; }
  124     
  125     obuflen = 512;
  126     obuf = malloc(obuflen);
  127     
  128     err = decompression_setup(&cstream, filemap, 0, statbuf.st_size, obuf, obuflen, C_GZIP);
  129     if ((decompression_init(&cstream) != CE_OK) || (err != CE_OK)) {
  130         decompression_cleanup(&cstream);
  131         munmap(filemap, statbuf.st_size);
  132         free(obuf);
  133         return 2;
  134     }
  135     
  136     tar_archive = init_archive(AT_TAR);
  137     do {
  138         if (tar_archive->stage == AS_NEWFILE) {
  139             if (switch_control_names(tar_archive->name) == 0) {
  140                 deinit_archive(tar_archive);
  141                 decompression_cleanup(&cstream);
  142                 free(obuf);
  143                 munmap(filemap, statbuf.st_size);
  144                 
  145                 return 0;
  146             }
  147         }
  148         
  149         update_nextblock(tar_archive);
  150         if (tar_archive->nextblock > obuflen) {
  151             obuflen = tar_archive->nextblock;
  152             obuf = realloc(obuf, obuflen);
  153         }
  154         
  155         if (decompression_decompress(&cstream, tar_archive->nextblock, obuf) != CE_OK)
  156             break;
  157         
  158         if (decompression_ammount_not_processed(&cstream) > 0)
  159             break;
  160         
  161         update_stage(tar_archive);
  162         
  163         switch (tar_archive->stage) {
  164             case AS_DATA:
  165                 update_upfilesize(tar_archive);
  166                 break;
  167             case AS_HEADER:
  168                 clear_archive_member(tar_archive);
  169                 break;
  170         }
  171         
  172         err = parse_block(tar_archive, obuf);
  173         
  174         if (err)
  175             break;
  176     } while (decompression_ammount_left(&cstream, 0) > 0);
  177     deinit_archive(tar_archive);
  178     decompression_cleanup(&cstream);
  179     
  180     free(obuf);
  181     munmap(filemap, statbuf.st_size);
  182     
  183     return 1;
  184 }
  185 int pkgdetails(packdef pdef, pkginfo *pinfo) {
  186     c_compdata      cstream;
  187     comarchive      *tar_archive;
  188     struct stat     statbuf;
  189     void            *filemap;
  190     
  191     char            *obuf;
  192     unsigned long   obuflen;
  193     
  194     int                 err;
  195     
  196     char            *fullfile;
  197     
  198     fstat(fileno(pdef.filepointer), &statbuf);
  199     filemap = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fileno(pdef.filepointer), 0);
  200     if (filemap == MAP_FAILED) { return 1; }
  201     
  202     obuflen = 512;
  203     obuf = malloc(obuflen);
  204     
  205     err = decompression_setup(&cstream, filemap, 0, statbuf.st_size, obuf, obuflen, C_GZIP);
  206     if ((decompression_init(&cstream) != CE_OK) || (err != CE_OK)) {
  207         decompression_cleanup(&cstream);
  208         munmap(filemap, statbuf.st_size);
  209         free(obuf);
  210         return 1;
  211     }
  212     
  213     fullfile = NULL;
  214     
  215     tar_archive = init_archive(AT_TAR);
  216     do {
  217         if (tar_archive->stage == AS_NEWFILE) {
  218             switch (switch_control_names(tar_archive->name)) {
  219                 case 0:
  220                 case 2:
  221                     fullfile = malloc(tar_archive->filesize);
  222                     break;
  223                 
  224                 case -1:
  225                     addfile(pinfo, absolutizestr(tar_archive->name, "/"), (tar_archive->ftype == AF_DIRECTORY) ? F_DIRECTORY : F_REGULAR);
  226                     pinfo->pkgsize += tar_archive->filesize;
  227                     break;
  228             }
  229         }
  230         
  231         update_nextblock(tar_archive);
  232         if (tar_archive->nextblock > obuflen) {
  233             obuflen = tar_archive->nextblock;
  234             obuf = realloc(obuf, obuflen);
  235         }
  236         
  237         if (decompression_decompress(&cstream, tar_archive->nextblock, obuf) != CE_OK)
  238             break;
  239         
  240         if (decompression_ammount_not_processed(&cstream) > 0)
  241             break;
  242         
  243         update_stage(tar_archive);
  244         
  245         switch (tar_archive->stage) {
  246             case AS_DATA:
  247                 if (fullfile != NULL) {
  248                     memcpy(fullfile + tar_archive->upfilesize, obuf, ((tar_archive->filesize - tar_archive->upfilesize) > tar_archive->nextblock) ? tar_archive->nextblock : tar_archive->filesize - tar_archive->upfilesize);
  249                 }
  250             
  251                 update_upfilesize(tar_archive);
  252                 break;
  253             case AS_HEADER:
  254                 if (fullfile != NULL) {
  255                     switch (switch_control_names(tar_archive->name)) {
  256                         case 0:
  257                             pinfo->name = getpkginfohdr(fullfile, "pkgname", tar_archive->filesize);
  258                             pinfo->version = getpkginfohdr(fullfile, "pkgver", tar_archive->filesize);
  259                             pinfo->description = getpkginfohdr(fullfile, "pkgdesc", tar_archive->filesize);
  260                             break;
  261                         case 2:
  262                             // A hack; we copy the script to all possible places and alter arguments. Cool, innit?
  263                             pinfo->preinst.len = tar_archive->filesize;
  264                             pinfo->postinst.len = tar_archive->filesize;
  265                             pinfo->prerm.len = tar_archive->filesize;
  266                             pinfo->postrm.len = tar_archive->filesize;
  267                         
  268                             pinfo->preinst.data = malloc(pinfo->preinst.len);
  269                             pinfo->postinst.data = malloc(pinfo->postinst.len);
  270                             pinfo->prerm.data = malloc(pinfo->prerm.len);
  271                             pinfo->postrm.data = malloc(pinfo->postrm.len);
  272                         
  273                             memcpy(pinfo->preinst.data, fullfile, tar_archive->filesize);
  274                             memcpy(pinfo->postinst.data, fullfile, tar_archive->filesize);
  275                             memcpy(pinfo->prerm.data, fullfile, tar_archive->filesize);
  276                             memcpy(pinfo->postrm.data, fullfile, tar_archive->filesize);
  277                         
  278                             pinfo->preinst.parameters[A_IRRELEVANT] = strdup("pre_install");
  279                             pinfo->preinst.parameters[A_UPGRADE] = strdup("pre_upgrade");
  280                             pinfo->preinst.parameters[A_DOWNGRADE] = strdup("pre_upgrade");
  281                             pinfo->preinst.parameters[A_REINSTALL] = strdup("pre_upgrade");
  282                         
  283                             pinfo->postinst.parameters[A_IRRELEVANT] = strdup("post_install");
  284                             pinfo->postinst.parameters[A_UPGRADE] = strdup("post_upgrade");
  285                             pinfo->postinst.parameters[A_DOWNGRADE] = strdup("post_upgrade");
  286                             pinfo->postinst.parameters[A_REINSTALL] = strdup("post_upgrade");
  287                         
  288                             pinfo->prerm.parameters[A_IRRELEVANT] = strdup("pre_remove");
  289                             
  290                             pinfo->postrm.parameters[A_IRRELEVANT] = strdup("post_remove");
  291                             break;
  292                     }
  293                     free(fullfile);
  294                     fullfile = NULL;
  295                 }
  296                 clear_archive_member(tar_archive);
  297                 break;
  298         }
  299         
  300         err = parse_block(tar_archive, obuf);
  301         
  302         if (err)
  303             break;
  304     } while (decompression_ammount_left(&cstream, 0) > 0);
  305     deinit_archive(tar_archive);
  306     decompression_cleanup(&cstream);
  307     
  308     free(obuf);
  309     munmap(filemap, statbuf.st_size);
  310     
  311     if (pinfo->description == NULL) { pinfo->description = strdup("ArchLinux package, no description."); }
  312     if (pinfo->version == NULL) { pinfo->version = strdup("unknown"); }
  313     if (pinfo->name == NULL) { return 1; }
  314     
  315     return 0;
  316 }
  317 int pkginstall(packdef pdef) {
  318     c_compdata      cstream;
  319     comarchive      *tar_archive;
  320     struct stat     statbuf;
  321     void            *filemap;
  322     
  323     char            *obuf;
  324     unsigned long   obuflen;
  325     
  326     int                 err;
  327     FILE                *fpout;
  328     char            *curpath;
  329     
  330     fpout = NULL;
  331     curpath = NULL;
  332     
  333     fstat(fileno(pdef.filepointer), &statbuf);
  334     filemap = mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fileno(pdef.filepointer), 0);
  335     if (filemap == MAP_FAILED) { return 1; }
  336     
  337     obuflen = 512;
  338     obuf = malloc(obuflen);
  339     
  340     err = decompression_setup(&cstream, filemap, 0, statbuf.st_size, obuf, obuflen, C_GZIP);
  341     if ((decompression_init(&cstream) != CE_OK) || (err != CE_OK)) {
  342         decompression_cleanup(&cstream);
  343         munmap(filemap, statbuf.st_size);
  344         free(obuf);
  345         return 1;
  346     }
  347     
  348     tar_archive = init_archive(AT_TAR);
  349     do {
  350         if (tar_archive->stage == AS_NEWFILE) {
  351             free(curpath);
  352             curpath = absolutizestr(tar_archive->name, pdef.destdir);
  353             if (switch_control_names(tar_archive->name) == -1) {
  354                 switch (tar_archive->ftype) {
  355                     case AF_REGULAR:
  356                             if (fpout != NULL) { 
  357                                 fclose(fpout);
  358                             }
  359                             if ((fpout = fopen(curpath, "w")) == NULL) {
  360                                 free(curpath);
  361                                 free(obuf);
  362                                 decompression_cleanup(&cstream);
  363                                 munmap(filemap, statbuf.st_size);
  364                                 deinit_archive(tar_archive);
  365                                 return 1;
  366                             }
  367                             
  368                             FCHOWNMOD(fileno(fpout), tar_archive->mode, tar_archive->uid, tar_archive->gid);
  369                             
  370                             if (tar_archive->filesize == 0) {
  371                                 // Nothing to write. We just created it.
  372                                 fclose(fpout);
  373                                 fpout = NULL;
  374                                 
  375                                 // For SUID and SGID; fchown + file open for writing + suid/sgid = suid/sgid may be ignored
  376                                 CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
  377                             }
  378                         break;
  379                     case AF_SYMLINK:
  380                             symlink(tar_archive->linktarget, curpath);
  381                             CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
  382                         break;
  383                     case AF_DEVNODE:
  384                             mknod(curpath, tar_archive->mode, makedev(tar_archive->dmajor, tar_archive->dminor));
  385                             CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
  386                         break;
  387                     case AF_FIFOBUF:
  388                             mkfifo(curpath, tar_archive->mode);
  389                             CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
  390                         break;
  391                     case AF_DIRECTORY:
  392                             if (stat(curpath, &statbuf)) {
  393                                 mkdir(curpath, tar_archive->mode);
  394                                 CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
  395                             }
  396                         break;
  397                 }
  398             }
  399         }
  400         
  401         update_nextblock(tar_archive);
  402         if (tar_archive->nextblock > obuflen) {
  403             obuflen = tar_archive->nextblock;
  404             obuf = realloc(obuf, obuflen);
  405         }
  406         
  407         if (decompression_decompress(&cstream, tar_archive->nextblock, obuf) != CE_OK)
  408             break;
  409         
  410         if (decompression_ammount_not_processed(&cstream) > 0)
  411             break;
  412         
  413         update_stage(tar_archive);
  414         
  415         switch (tar_archive->stage) {
  416             case AS_DATA:
  417                 if (tar_archive->ftype == AF_REGULAR) {
  418                     if (fpout != NULL) {
  419                         fwrite(obuf, ((tar_archive->filesize - tar_archive->upfilesize) > tar_archive->nextblock) ? tar_archive->nextblock : tar_archive->filesize - tar_archive->upfilesize, 1, fpout);
  420                     }
  421                 }
  422             
  423                 update_upfilesize(tar_archive);
  424                 break;
  425             case AS_HEADER:
  426                 if (tar_archive->ftype == AF_REGULAR) {
  427                     if (fpout != NULL) {
  428                         fsync(fileno(fpout));
  429                         fclose(fpout);
  430                         fpout = NULL;
  431                         
  432                         // For SUID and SGID; fchown + file open for writing + suid/sgid = suid/sgid may be ignored
  433                         CHOWNMOD(curpath, tar_archive->mode, tar_archive->uid, tar_archive->gid);
  434                     }
  435                 }
  436                 clear_archive_member(tar_archive);
  437                 break;
  438         }
  439         
  440         err = parse_block(tar_archive, obuf);
  441         
  442         if (err)
  443             break;
  444     } while (decompression_ammount_left(&cstream, 0) > 0);
  445     deinit_archive(tar_archive);
  446     decompression_cleanup(&cstream);
  447     free(curpath);
  448     free(obuf);
  449     munmap(filemap, statbuf.st_size);
  450     return 0;
  451 }