rpm.c
author Kristian H?gsberg <krh@redhat.com>
Wed Nov 07 00:33:56 2007 -0500 (2007-11-07)
changeset 74 f23a93d41f32
child 75 93278d8ec39c
permissions -rw-r--r--
Add the first bits of rpm file parser.
     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <sys/stat.h>
     4 #include <sys/mman.h>
     5 #include <fcntl.h>
     6 #include <unistd.h>
     7 #include <arpa/inet.h>
     8 #include <rpm/rpmlib.h>
     9 
    10 #define	RPM_LEAD_SIZE 96
    11 
    12 struct rpm_lead {
    13 	unsigned char magic[4];
    14 	unsigned char major;
    15 	unsigned char minor;
    16 	short type;
    17 	short archnum;
    18 	char name[66];
    19 	short osnum;
    20 	short signature_type;
    21 	char reserved[16];
    22 };
    23 
    24 struct rpm_header {
    25 	unsigned char magic[4];
    26 	unsigned char reserved[4];
    27 	int nindex;
    28 	int hsize;
    29 };
    30 
    31 struct rpm_header_index {
    32 	int tag;
    33 	int type;
    34 	int offset;
    35 	int count;
    36 };
    37 
    38 #define ALIGN(value, base) (((value) + (base - 1)) & ~((base) - 1))
    39 
    40 static void dump_header(struct rpm_header *header)
    41 {
    42 	struct rpm_header_index *base, *index;
    43 	int i, j, nindex, tag, offset, type, count;
    44 	char *pool, *name;
    45 
    46 	nindex = ntohl(header->nindex);
    47 	printf("header index records: %d\n", nindex);
    48 	printf("header storage size: %d\n", ntohl(header->hsize));
    49 	base = (struct rpm_header_index *) (header + 1);
    50 	pool = (void *) (header + 1) + nindex * sizeof *index;
    51 
    52 	printf("headers:\n");
    53 	for (i = 0; i < nindex; i++) {
    54 		index = base + i;
    55 		tag = ntohl(index->tag);
    56 		offset = ntohl(index->offset);
    57 		type = ntohl(index->type);
    58 		count = ntohl(index->count);
    59 		printf("  0x%08x 0x%08x 0x%08x 0x%08x\n",
    60 		       tag, type, offset, count);
    61 
    62 		switch (tag) {
    63 		case RPMTAG_NAME:
    64 			name = "name";
    65 			break;
    66 		case RPMTAG_VERSION:
    67 			name = "version";
    68 			break;
    69 		case RPMTAG_RELEASE:
    70 			name = "release";
    71 			break;
    72 		case RPMTAG_REQUIRENAME:
    73 			name = "requires";
    74 			break;
    75 		default:
    76 			name = "unknown";
    77 			break;
    78 		}
    79 
    80 		switch (type) {
    81 		case RPM_STRING_TYPE:
    82 			printf("    (%s %s)\n", name, pool + offset);
    83 			break;
    84 		case RPM_STRING_ARRAY_TYPE:
    85 			printf("    (%s", name);
    86 			for (j = 0; j < count; j++) {
    87 				printf(" %s", pool + offset);
    88 				offset += strlen(pool + offset) + 1;
    89 			}
    90 			printf(")\n");
    91 			break;
    92 		}
    93 	}
    94 }
    95 
    96 void
    97 razor_rpm_dump(const char *filename)
    98 {
    99 	struct stat buf;
   100 	void *p;
   101 	int fd, nindex, hsize;
   102 	struct rpm_header *signature, *header;
   103 	struct rpm_header_index *index;
   104 
   105 	if (stat(filename, &buf) < 0) {
   106 		fprintf(stderr, "no such file %s\n", filename);
   107 		return;
   108 	}
   109 
   110 	fd = open(filename, O_RDONLY);
   111 	p = mmap(NULL, buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
   112 	close(fd);
   113 
   114 	printf("%s: %ldkB\n", filename, buf.st_size / 1024);
   115 	signature = p + RPM_LEAD_SIZE;
   116 
   117 	nindex = ntohl(signature->nindex);
   118 	hsize = ntohl(signature->hsize);
   119 	header = (void *) (signature + 1) +
   120 		ALIGN(nindex * sizeof *index + hsize, 8);
   121 
   122 	dump_header(signature);
   123 	dump_header(header);
   124 
   125 	munmap(p, buf.st_size);
   126 }