Use the cpio headers instead of the rpm headers when unpacking.
authorKristian H?gsberg <krh@jiraiya.boston.redhat.com>
Wed Apr 09 02:41:03 2008 -0400 (2008-04-09)
changeset 211cf0ca962262b
parent 210 c78f677d96b8
child 212 e8f493d8ff9a
Use the cpio headers instead of the rpm headers when unpacking.

The files in the cpio payload doesn't actually follow the file order
in the rpm headers, so we need to decode the cpio header and use the
information there.
main.c
rpm.c
util.c
     1.1 --- a/main.c	Tue Apr 08 23:53:57 2008 -0400
     1.2 +++ b/main.c	Wed Apr 09 02:41:03 2008 -0400
     1.3 @@ -728,7 +728,9 @@
     1.4  		return -1;
     1.5  	}
     1.6  
     1.7 -	if (razor_create_dir(root, razor_root_path) < 0) {
     1.8 +	snprintf(path, sizeof path, "%s/%s",
     1.9 +		 razor_root_path, system_repo_filename);
    1.10 +	if (razor_create_dir(root, path) < 0) {
    1.11  		fprintf(stderr, "could not create %s%s\n",
    1.12  			root, razor_root_path);
    1.13  		return -1;
     2.1 --- a/rpm.c	Tue Apr 08 23:53:57 2008 -0400
     2.2 +++ b/rpm.c	Wed Apr 09 02:41:03 2008 -0400
     2.3 @@ -246,13 +246,13 @@
     2.4  	size_t length;
     2.5  	int err;
     2.6  
     2.7 -	if (ALIGN(installer->rest, 4) > sizeof installer->buffer)
     2.8 +	if (installer->rest > sizeof installer->buffer)
     2.9  		length = sizeof installer->buffer;
    2.10  	else
    2.11  		length = installer->rest;
    2.12  
    2.13  	installer->stream.next_out = installer->buffer;
    2.14 -	installer->stream.avail_out = ALIGN(length, 4);
    2.15 +	installer->stream.avail_out = length;
    2.16  	err = inflate(&installer->stream, Z_SYNC_FLUSH);
    2.17  	if (err != Z_OK && err != Z_STREAM_END) {
    2.18  		fprintf(stderr, "inflate error: %d (%m)\n", err);
    2.19 @@ -266,8 +266,29 @@
    2.20  }
    2.21  
    2.22  static int
    2.23 -create_path(struct installer *installer,
    2.24 -	    const char *path, const char *name, unsigned int mode)
    2.25 +installer_align(struct installer *installer, size_t size)
    2.26 +{
    2.27 +	unsigned char buffer[4];
    2.28 +	int err;
    2.29 +
    2.30 +	installer->stream.next_out = buffer;
    2.31 +	installer->stream.avail_out =
    2.32 +		(size - installer->stream.total_out) & (size - 1);
    2.33 +
    2.34 +	if (installer->stream.avail_out == 0)
    2.35 +		return 0;
    2.36 +
    2.37 +	err = inflate(&installer->stream, Z_SYNC_FLUSH);
    2.38 +	if (err != Z_OK && err != Z_STREAM_END) {
    2.39 +		fprintf(stderr, "inflate error: %d (%m)\n", err);
    2.40 +		return -1;
    2.41 +	}
    2.42 +
    2.43 +	return 0;
    2.44 +}
    2.45 +
    2.46 +static int
    2.47 +create_path(struct installer *installer, const char *path, unsigned int mode)
    2.48  {
    2.49  	char buffer[PATH_MAX];
    2.50  	struct stat buf;
    2.51 @@ -276,10 +297,7 @@
    2.52  	if (razor_create_dir(installer->root, path) < 0)
    2.53  		return -1;
    2.54  
    2.55 -	/* assertion: root doesn't end in a slash, path begins and end
    2.56 -	 * with a slash, name does not begin with a slash. */
    2.57 -	snprintf(buffer, sizeof buffer, "%s%s%s",
    2.58 -		 installer->root, path, name);
    2.59 +	snprintf(buffer, sizeof buffer, "%s%s", installer->root, path);
    2.60  
    2.61  	switch (mode >> 12) {
    2.62  	case REG:
    2.63 @@ -461,16 +479,31 @@
    2.64  	return 0;
    2.65  }
    2.66  
    2.67 +static unsigned long
    2.68 +fixed_hex_to_ulong(const char *hex, int length)
    2.69 +{
    2.70 +	long l;
    2.71 +	int i;
    2.72 +
    2.73 +	for (i = 0, l = 0; i < length; i++) {
    2.74 +		if (hex[i] < 'a')
    2.75 +			l = l * 16 + hex[i] - '0';
    2.76 +		else
    2.77 +			l = l * 16 + hex[i] - 'a' + 10;
    2.78 +	}
    2.79 +
    2.80 +	return l;
    2.81 +}
    2.82 +
    2.83  int
    2.84  razor_rpm_install(struct razor_rpm *rpm, const char *root)
    2.85  {
    2.86  	struct installer installer;
    2.87 -	unsigned int count, i, length;
    2.88  	struct cpio_file_header *header;
    2.89 -	const uint32_t *size, *index, *flags;
    2.90 -	const unsigned short *mode;
    2.91 -	const char *name, *dir;
    2.92  	struct stat buf;
    2.93 +	unsigned int mode;
    2.94 +	char *path;
    2.95 +	size_t filesize;
    2.96  
    2.97  	installer.rpm = rpm;
    2.98  	installer.root = root;
    2.99 @@ -488,34 +521,33 @@
   2.100  
   2.101  	run_script(&installer, RPMTAG_PREINPROG, RPMTAG_PREIN);
   2.102  
   2.103 -	name = razor_rpm_get_indirect(rpm, RPMTAG_BASENAMES, &count);
   2.104 -	size = razor_rpm_get_indirect(rpm, RPMTAG_FILESIZES, &count);
   2.105 -	index = razor_rpm_get_indirect(rpm, RPMTAG_DIRINDEXES, &count);
   2.106 -	mode = razor_rpm_get_indirect(rpm, RPMTAG_FILEMODES, &count);
   2.107 -	flags = razor_rpm_get_indirect(rpm, RPMTAG_FILEFLAGS, &count);
   2.108 +	while (installer.stream.avail_in > 0) {
   2.109 +		installer.rest = sizeof *header;
   2.110 +		if (installer_inflate(&installer))
   2.111 +			return -1;
   2.112 +		
   2.113 +		header = (struct cpio_file_header *) installer.buffer;
   2.114 +		mode = fixed_hex_to_ulong(header->mode, sizeof header->mode);
   2.115 +		filesize = fixed_hex_to_ulong(header->filesize,
   2.116 +					      sizeof header->filesize);
   2.117  
   2.118 -	for (i = 0; name && i < count; i++) {
   2.119 -		dir = rpm->dirs[ntohl(*index)];
   2.120 +		installer.rest = fixed_hex_to_ulong(header->namesize,
   2.121 +						    sizeof header->namesize);
   2.122  
   2.123 -		/* Skip past the cpio header block unless it's a ghost file,
   2.124 -		 * in which case doesn't appear in the cpio archive. */
   2.125 -		if (!(ntohl(*flags) & RPMFILE_GHOST)) {
   2.126 -			/* Plus two for the leading '.' and the terminating NUL. */
   2.127 -			length = sizeof *header + strlen(dir) + strlen(name) + 2;
   2.128 -			installer.rest = ALIGN(length, 4);
   2.129 -			if (installer_inflate(&installer))
   2.130 -				return -1;
   2.131 -		}
   2.132 -
   2.133 -		installer.rest = ntohl(*size);
   2.134 -		if (create_path(&installer, dir, name, ntohs(*mode)) < 0)
   2.135 +		if (installer_inflate(&installer) ||
   2.136 +		    installer_align(&installer, 4))
   2.137  			return -1;
   2.138  
   2.139 -		name += strlen(name) + 1;
   2.140 -		index++;
   2.141 -		size++;
   2.142 -		mode++;
   2.143 -		flags++;
   2.144 +		path = (char *) installer.buffer;
   2.145 +		/* This convention is so lame... */
   2.146 +		if (strcmp(path, "TRAILER!!!") == 0)
   2.147 +			break;
   2.148 +
   2.149 +		installer.rest = filesize;
   2.150 +		if (create_path(&installer, path + 1, mode) < 0)
   2.151 +			return -1;
   2.152 +		if (installer_align(&installer, 4))
   2.153 +			return -1;
   2.154  	}
   2.155  
   2.156  	if (installer_finish(&installer))
     3.1 --- a/util.c	Tue Apr 08 23:53:57 2008 -0400
     3.2 +++ b/util.c	Wed Apr 09 02:41:03 2008 -0400
     3.3 @@ -15,9 +15,9 @@
     3.4  	const char *slash, *next;
     3.5  	struct stat buf;
     3.6  
     3.7 -	/* Create all sub-directories in dir and then create name. We
     3.8 -	 * know root exists and is a dir, root does not end in a '/',
     3.9 -	 * and path has a leading '/'. */
    3.10 +	/* Create all sub-directories in dir. We know root exists and
    3.11 +	 * is a dir, root does not end in a '/', and path has a
    3.12 +	 * leading '/'. */
    3.13  
    3.14  	strcpy(buffer, root);
    3.15  	p = buffer + strlen(buffer);
    3.16 @@ -25,7 +25,7 @@
    3.17  	for (slash = path; *slash != '\0'; slash = next) {
    3.18  		next = strchr(slash + 1, '/');
    3.19  		if (next == NULL)
    3.20 -			next = slash + strlen(slash);
    3.21 +			break;
    3.22  
    3.23  		memcpy(p, slash, next - slash);
    3.24  		p += next - slash;