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))