rpm.c
changeset 211 cf0ca962262b
parent 202 e8594c82dffc
child 212 e8f493d8ff9a
     1.1 --- a/rpm.c	Mon Apr 07 11:56:48 2008 -0400
     1.2 +++ b/rpm.c	Wed Apr 09 02:41:03 2008 -0400
     1.3 @@ -246,13 +246,13 @@
     1.4  	size_t length;
     1.5  	int err;
     1.6  
     1.7 -	if (ALIGN(installer->rest, 4) > sizeof installer->buffer)
     1.8 +	if (installer->rest > sizeof installer->buffer)
     1.9  		length = sizeof installer->buffer;
    1.10  	else
    1.11  		length = installer->rest;
    1.12  
    1.13  	installer->stream.next_out = installer->buffer;
    1.14 -	installer->stream.avail_out = ALIGN(length, 4);
    1.15 +	installer->stream.avail_out = length;
    1.16  	err = inflate(&installer->stream, Z_SYNC_FLUSH);
    1.17  	if (err != Z_OK && err != Z_STREAM_END) {
    1.18  		fprintf(stderr, "inflate error: %d (%m)\n", err);
    1.19 @@ -266,8 +266,29 @@
    1.20  }
    1.21  
    1.22  static int
    1.23 -create_path(struct installer *installer,
    1.24 -	    const char *path, const char *name, unsigned int mode)
    1.25 +installer_align(struct installer *installer, size_t size)
    1.26 +{
    1.27 +	unsigned char buffer[4];
    1.28 +	int err;
    1.29 +
    1.30 +	installer->stream.next_out = buffer;
    1.31 +	installer->stream.avail_out =
    1.32 +		(size - installer->stream.total_out) & (size - 1);
    1.33 +
    1.34 +	if (installer->stream.avail_out == 0)
    1.35 +		return 0;
    1.36 +
    1.37 +	err = inflate(&installer->stream, Z_SYNC_FLUSH);
    1.38 +	if (err != Z_OK && err != Z_STREAM_END) {
    1.39 +		fprintf(stderr, "inflate error: %d (%m)\n", err);
    1.40 +		return -1;
    1.41 +	}
    1.42 +
    1.43 +	return 0;
    1.44 +}
    1.45 +
    1.46 +static int
    1.47 +create_path(struct installer *installer, const char *path, unsigned int mode)
    1.48  {
    1.49  	char buffer[PATH_MAX];
    1.50  	struct stat buf;
    1.51 @@ -276,10 +297,7 @@
    1.52  	if (razor_create_dir(installer->root, path) < 0)
    1.53  		return -1;
    1.54  
    1.55 -	/* assertion: root doesn't end in a slash, path begins and end
    1.56 -	 * with a slash, name does not begin with a slash. */
    1.57 -	snprintf(buffer, sizeof buffer, "%s%s%s",
    1.58 -		 installer->root, path, name);
    1.59 +	snprintf(buffer, sizeof buffer, "%s%s", installer->root, path);
    1.60  
    1.61  	switch (mode >> 12) {
    1.62  	case REG:
    1.63 @@ -461,16 +479,31 @@
    1.64  	return 0;
    1.65  }
    1.66  
    1.67 +static unsigned long
    1.68 +fixed_hex_to_ulong(const char *hex, int length)
    1.69 +{
    1.70 +	long l;
    1.71 +	int i;
    1.72 +
    1.73 +	for (i = 0, l = 0; i < length; i++) {
    1.74 +		if (hex[i] < 'a')
    1.75 +			l = l * 16 + hex[i] - '0';
    1.76 +		else
    1.77 +			l = l * 16 + hex[i] - 'a' + 10;
    1.78 +	}
    1.79 +
    1.80 +	return l;
    1.81 +}
    1.82 +
    1.83  int
    1.84  razor_rpm_install(struct razor_rpm *rpm, const char *root)
    1.85  {
    1.86  	struct installer installer;
    1.87 -	unsigned int count, i, length;
    1.88  	struct cpio_file_header *header;
    1.89 -	const uint32_t *size, *index, *flags;
    1.90 -	const unsigned short *mode;
    1.91 -	const char *name, *dir;
    1.92  	struct stat buf;
    1.93 +	unsigned int mode;
    1.94 +	char *path;
    1.95 +	size_t filesize;
    1.96  
    1.97  	installer.rpm = rpm;
    1.98  	installer.root = root;
    1.99 @@ -488,34 +521,33 @@
   1.100  
   1.101  	run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN);
   1.102  
   1.103 -	name = razor_rpm_get_indirect(rpm, RPMTAG_BASENAMES, &count);
   1.104 -	size = razor_rpm_get_indirect(rpm, RPMTAG_FILESIZES, &count);
   1.105 -	index = razor_rpm_get_indirect(rpm, RPMTAG_DIRINDEXES, &count);
   1.106 -	mode = razor_rpm_get_indirect(rpm, RPMTAG_FILEMODES, &count);
   1.107 -	flags = razor_rpm_get_indirect(rpm, RPMTAG_FILEFLAGS, &count);
   1.108 +	while (installer.stream.avail_in > 0) {
   1.109 +		installer.rest = sizeof *header;
   1.110 +		if (installer_inflate(&installer))
   1.111 +			return -1;
   1.112 +		
   1.113 +		header = (struct cpio_file_header *) installer.buffer;
   1.114 +		mode = fixed_hex_to_ulong(header->mode, sizeof header->mode);
   1.115 +		filesize = fixed_hex_to_ulong(header->filesize,
   1.116 +					      sizeof header->filesize);
   1.117  
   1.118 -	for (i = 0; name && i < count; i++) {
   1.119 -		dir = rpm->dirs[ntohl(*index)];
   1.120 +		installer.rest = fixed_hex_to_ulong(header->namesize,
   1.121 +						    sizeof header->namesize);
   1.122  
   1.123 -		/* Skip past the cpio header block unless it's a ghost file,
   1.124 -		 * in which case doesn't appear in the cpio archive. */
   1.125 -		if (!(ntohl(*flags) & RPMFILE_GHOST)) {
   1.126 -			/* Plus two for the leading '.' and the terminating NUL. */
   1.127 -			length = sizeof *header + strlen(dir) + strlen(name) + 2;
   1.128 -			installer.rest = ALIGN(length, 4);
   1.129 -			if (installer_inflate(&installer))
   1.130 -				return -1;
   1.131 -		}
   1.132 -
   1.133 -		installer.rest = ntohl(*size);
   1.134 -		if (create_path(&installer, dir, name, ntohs(*mode)) < 0)
   1.135 +		if (installer_inflate(&installer) ||
   1.136 +		    installer_align(&installer, 4))
   1.137  			return -1;
   1.138  
   1.139 -		name += strlen(name) + 1;
   1.140 -		index++;
   1.141 -		size++;
   1.142 -		mode++;
   1.143 -		flags++;
   1.144 +		path = (char *) installer.buffer;
   1.145 +		/* This convention is so lame... */
   1.146 +		if (strcmp(path, "TRAILER!!!") == 0)
   1.147 +			break;
   1.148 +
   1.149 +		installer.rest = filesize;
   1.150 +		if (create_path(&installer, path + 1, mode) < 0)
   1.151 +			return -1;
   1.152 +		if (installer_align(&installer, 4))
   1.153 +			return -1;
   1.154  	}
   1.155  
   1.156  	if (installer_finish(&installer))