home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / misc / src / rpm / lib / oldheader.c < prev    next >
C/C++ Source or Header  |  1997-09-17  |  9KB  |  363 lines

  1. #include "config.h"
  2. #include "miscfn.h"
  3.  
  4. #include <errno.h>
  5. #include <fcntl.h>
  6. #include <netinet/in.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <sys/stat.h>
  10. #include <string.h>
  11. #include <unistd.h>
  12.  
  13. #include "misc.h"
  14. #include "oldheader.h"
  15. #include "rpmlib.h"
  16. #include "tread.h"
  17.  
  18. /* This *can't* read 1.0 headers -- it needs 1.1 (w/ group and icon fields)
  19.    or better. I'd be surprised if any 1.0 headers are left anywhere anyway.
  20.    Red Hat 2.0 shipped with 1.1 headers, but some old BETAs used 1.0. */
  21.  
  22. struct literalHeader {
  23.     unsigned char m1, m2, m3, m4;
  24.     unsigned char major, minor;
  25.  
  26.     unsigned short type, cpu;
  27.     char labelstr[66];
  28.     unsigned int specOffset;
  29.     unsigned int specLength;
  30.     unsigned int archiveOffset;
  31.     unsigned int size;
  32.     unsigned int os;
  33.     unsigned int groupLength;
  34.     unsigned int iconLength;
  35. } ;
  36.  
  37. /* this leaves the file pointer pointing at the data section */
  38.  
  39. char * oldhdrReadFromStream(int fd, struct oldrpmHeader * header) {
  40.     struct literalHeader lit;
  41.     char * chptr;
  42.     int bytesRead;
  43.     char ch;
  44.     unsigned int specOffset;
  45.     unsigned int archiveOffset;
  46.     unsigned int groupLength;
  47.  
  48.     if (timedRead(fd, &lit, sizeof(lit)) != sizeof(lit)) {
  49.     return strerror(errno);
  50.     }
  51.  
  52.     bytesRead = sizeof(lit);
  53.  
  54.     if (lit.m1 != 0xed || lit.m2 != 0xab || lit.m3 != 0xee ||
  55.     lit.m4 != 0xdb) {
  56.     return "bad magic for RPM package";
  57.     }
  58.  
  59.     specOffset = htonl(lit.specOffset);
  60.     header->specLength = htonl(lit.specLength);
  61.     archiveOffset = htonl(lit.archiveOffset);
  62.     header->size = htonl(lit.size);
  63.     header->os = htonl(lit.os);
  64.     groupLength = htonl(lit.groupLength);
  65.     header->iconLength = htonl(lit.iconLength);
  66.  
  67.     header->spec = malloc(header->specLength);
  68.     header->name = malloc(strlen(lit.labelstr) + 1);
  69.     if (!header->spec || !header->name) {
  70.     header->spec ? free(header->spec) : 0;
  71.     header->name ? free(header->name) : 0;
  72.     return "out of memory";
  73.     }
  74.  
  75.     strcpy(header->name, lit.labelstr);
  76.     chptr = header->name + strlen(header->name);
  77.     while (*chptr != '-') chptr--;
  78.     *chptr = '\0';
  79.     header->release = chptr + 1;
  80.     while (*chptr != '-') chptr--;
  81.     *chptr = '\0';
  82.     header->version = chptr + 1;
  83.  
  84.     if (groupLength) {
  85.         header->group = malloc(groupLength + 1);
  86.     if (!header->group) {
  87.         free(header->spec);
  88.         free(header->name);
  89.         return "out of memory";
  90.     }
  91.  
  92.     if (timedRead(fd, header->group, groupLength) != groupLength) {
  93.         oldhdrFree(header);
  94.         return strerror(errno);
  95.     }
  96.     header->group[groupLength] = '\0';
  97.     bytesRead += groupLength;
  98.     } else {
  99.     header->group = NULL;
  100.     }
  101.     
  102.     if (header->iconLength) {
  103.     header->icon = malloc(header->iconLength);
  104.     if (!header->icon) {
  105.         free(header->spec);
  106.         free(header->name);
  107.         free(header->icon);
  108.         return "out of memory";
  109.     }
  110.     if (timedRead(fd, header->icon, header->iconLength) != 
  111.             header->iconLength) {
  112.         oldhdrFree(header);
  113.         return strerror(errno);
  114.     }
  115.     bytesRead += header->iconLength;
  116.     } else {
  117.     header->icon = NULL;
  118.     }
  119.  
  120.     while (bytesRead < specOffset) {
  121.     if (timedRead(fd, &ch, 1) != 1) {
  122.         oldhdrFree(header);
  123.         return strerror(errno);
  124.     }
  125.     bytesRead++;
  126.     }
  127.  
  128.     if (timedRead(fd, header->spec, header->specLength) != header->specLength) {
  129.     oldhdrFree(header);
  130.     return strerror(errno);
  131.     }
  132.     bytesRead += header->specLength;
  133.  
  134.     while (bytesRead < archiveOffset) {
  135.     if (timedRead(fd, &ch, 1) != 1) {
  136.         oldhdrFree(header);
  137.         return strerror(errno);
  138.     }
  139.     bytesRead++;
  140.     }
  141.  
  142.     return NULL;
  143. }
  144.  
  145. char * oldhdrReadFromFile(char * filename, struct oldrpmHeader * header) {
  146.     char * rc;
  147.     int fd;
  148.  
  149.     fd = open(filename, O_RDONLY);
  150.     if (fd < 0) return strerror(errno);
  151.     
  152.     rc = oldhdrReadFromStream(fd, header);
  153.     close(fd);
  154.     
  155.     return rc;
  156. }
  157.  
  158. void oldhdrFree(struct oldrpmHeader * header) {
  159.     free(header->name);
  160.     free(header->spec);
  161.     header->group ? free(header->icon) : 0;
  162.     header->group ? free(header->group) : 0;
  163. }
  164.  
  165. void oldhdrSpecFree(struct oldrpmHeaderSpec * spec) {
  166.     free(spec->copyright);
  167.     free(spec->description);
  168.     free(spec->vendor);
  169.     free(spec->distribution);
  170.     free(spec->buildHost);
  171.     if (spec->postun) free(spec->postun);
  172.     if (spec->postin) free(spec->postin);
  173.     if (spec->preun) free(spec->preun);
  174.     if (spec->prein) free(spec->prein);
  175.  
  176.     while (spec->fileCount) {
  177.     spec->fileCount--;
  178.     oldrpmfileFree(spec->files + spec->fileCount);
  179.     }
  180.  
  181.     free(spec->files);
  182. }
  183.  
  184. char * oldhdrParseSpec(struct oldrpmHeader * header, struct oldrpmHeaderSpec * spec) {
  185.     char ** lines;
  186.     char ** strptr;
  187.     char ** files = NULL;
  188.     char ** str = NULL;
  189.     int strlength = 0;
  190.     int i;
  191.     enum { FILELIST, PREIN, POSTIN, PREUN, POSTUN, PREAMBLE } state = PREAMBLE;
  192.  
  193.     lines = splitString(header->spec, header->specLength, '\n');
  194.     if (!lines) {
  195.     return "out of memory";
  196.     }
  197.  
  198.     /* these are optional */
  199.     spec->distribution = NULL;
  200.     spec->vendor = NULL;
  201.     spec->description = NULL;
  202.     spec->copyright = NULL;
  203.     spec->prein = spec->postin = NULL;
  204.     spec->preun = spec->postun = NULL;
  205.  
  206.     spec->fileCount = 0;
  207.     for (strptr = lines; *strptr; strptr++) {
  208.     if (!strncmp("%speci", *strptr, 6)) {
  209.         state = FILELIST;
  210.         files = strptr + 1;
  211.     } else if (!strncmp("%postun", *strptr, 7)) {
  212.         state = POSTUN;
  213.         str = &spec->postun;
  214.     }
  215.     else if (!strncmp("%preun", *strptr, 6)) {
  216.         state = PREUN;
  217.         str = &spec->preun;
  218.     }
  219.     else if (!strncmp("%post", *strptr, 5)) {
  220.         state = POSTIN;
  221.         str = &spec->postin;
  222.     }
  223.     else if (!strncmp("%pre", *strptr, 4)) {
  224.         state = PREIN;
  225.         str = &spec->prein;
  226.     }
  227.     else {
  228.         switch (state) {
  229.           case FILELIST: 
  230.         if (**strptr) 
  231.             spec->fileCount++;
  232.         break;
  233.  
  234.           case PREAMBLE:
  235.         if (!strncmp("Description: ", *strptr, 13))
  236.             spec->description = strdup((*strptr) + 13);
  237.         else if (!strncmp("Distribution: ", *strptr, 14))
  238.             spec->distribution = strdup((*strptr) + 14);
  239.         else if (!strncmp("Vendor: ", *strptr, 8))
  240.             spec->vendor = strdup((*strptr) + 8);
  241.         else if (!strncmp("BuildHost: ", *strptr, 11))
  242.             spec->buildHost = strdup((*strptr) + 11);
  243.         else if (!strncmp("BuildDate: ", *strptr, 11))
  244.             spec->buildTime = atoi((*strptr) + 11);
  245.         else if (!strncmp("Copyright: ", *strptr, 11))
  246.             spec->copyright = strdup((*strptr) + 11);
  247.         break;
  248.  
  249.           case PREUN: case PREIN: case POSTIN: case POSTUN:
  250.         if (!*str)  {
  251.             *str = malloc(strlen(*strptr) + 2);
  252.             strlength = 0;
  253.             (*str)[0] = '\0';
  254.         }
  255.         else
  256.             *str = realloc(*str, strlength + strlen(*strptr) + 2);
  257.         strcat(*str, *strptr);
  258.         strcat(*str, "\n");
  259.         strlength += strlen(*strptr) + 1;
  260.         }
  261.         
  262.     }
  263.     }
  264.  
  265.     spec->files = malloc(sizeof(struct oldrpmFileInfo) * spec->fileCount);
  266.     if (!spec->files) {
  267.     freeSplitString(lines);
  268.     return "out of memory";
  269.     }
  270.  
  271.     for (strptr = files, i = 0; *strptr; strptr++, i++) {
  272.     if (**strptr) 
  273.         oldrpmfileFromSpecLine(*strptr, spec->files + i);
  274.     }
  275.  
  276.     freeSplitString(lines);
  277.  
  278.     if (!spec->vendor) spec->vendor = strdup("");
  279.     if (!spec->description) spec->description = strdup("");
  280.     if (!spec->distribution) spec->distribution = strdup("");
  281.     if (!spec->copyright) spec->copyright = strdup("");
  282.  
  283.     return NULL;
  284. }
  285.  
  286. static void infoFromFields(char ** fields, struct oldrpmFileInfo * fi);
  287.  
  288. void oldrpmfileFromInfoLine(char * path, char * state, char * str, 
  289.             struct oldrpmFileInfo * fi) {
  290.     char ** fields;
  291.  
  292.     fields = splitString(str, strlen(str), ' ');
  293.  
  294.     fi->path = strdup(path);
  295.     if (!strcmp(state, "normal"))
  296.     fi->state = RPMFILE_STATE_NORMAL;
  297.     else if (!strcmp(state, "replaced"))
  298.     fi->state = RPMFILE_STATE_REPLACED;
  299.     else 
  300.     rpmError(RPMERR_INTERNAL, "bad file state: ", state);
  301.  
  302.     infoFromFields(fields, fi);
  303.  
  304.     freeSplitString(fields);
  305. }
  306.  
  307. void oldrpmfileFromSpecLine(char * str, struct oldrpmFileInfo * fi) {
  308.     char ** fields;
  309.  
  310.     fields = splitString(str, strlen(str), ' ');
  311.  
  312.     fi->path = strdup(fields[0]);
  313.     fi->state = RPMFILE_STATE_NORMAL;
  314.  
  315.     infoFromFields(fields + 1, fi);
  316.  
  317.     freeSplitString(fields);
  318. }
  319.  
  320. void infoFromFields(char ** fields, struct oldrpmFileInfo * fi) {
  321.     fi->size = strtol(fields[0], NULL, 10);
  322.     fi->mtime = strtol(fields[1], NULL, 10);
  323.     strcpy(fi->md5, fields[2]);
  324.     fi->mode = strtol(fields[3], NULL, 8);
  325.     fi->uid = strtol(fields[4], NULL, 10);
  326.     fi->gid = strtol(fields[5], NULL, 10);
  327.     fi->isconf = fields[6][0] != '0';
  328.     fi->isdoc = fields[7][0] != '0';
  329.     fi->rdev = strtol(fields[8], NULL, 16);
  330.    
  331.     if (S_ISLNK(fi->mode)) {
  332.     fi->linkto = strdup(fields[9]);
  333.     } else {
  334.     fi->linkto = NULL;
  335.     }
  336. }
  337.  
  338. void oldrpmfileFree(struct oldrpmFileInfo * fi) {
  339.     free(fi->path);
  340.     fi->linkto ? free(fi->linkto) : 0;
  341. }
  342.  
  343. char * oldrpmfileToInfoStr(struct oldrpmFileInfo * fi) {
  344.     char * buf;
  345.  
  346.     if (fi->linkto) 
  347.     buf = malloc(strlen(fi->linkto) + 100);
  348.     else
  349.     buf = malloc(100);
  350.  
  351.     sprintf(buf, "%ld %ld %s %o %d %d %s %s %x ", fi->size, fi->mtime,
  352.         fi->md5, fi->mode, fi->uid, fi->gid,
  353.         fi->isconf ? "1" : "0", fi->isdoc ? "1" : "0",
  354.         fi->rdev);
  355.     
  356.     if (fi->linkto) 
  357.     strcat(buf, fi->linkto);
  358.     else
  359.     strcat(buf, "X");
  360.  
  361.     return buf;
  362. }
  363.