Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 1 | Upstream-Status: Inappropriate [embedded specific] |
| 2 | |
| 3 | Do data input/output handling according to endien-ness of the library file. That |
| 4 | enables use of ldconfig in the cross fashion for any architecture. |
| 5 | |
| 6 | 2011/04/04 |
| 7 | Richard Purdie <richard.purdie@linuxfoundation.org> |
| 8 | Nitin Kamble <nitin.a.kamble@intel.com> |
| 9 | |
| 10 | Index: ldconfig-native-2.12.1/readelflib.c |
| 11 | =================================================================== |
| 12 | --- ldconfig-native-2.12.1.orig/readelflib.c |
| 13 | +++ ldconfig-native-2.12.1/readelflib.c |
| 14 | @@ -38,6 +38,28 @@ do \ |
| 15 | } \ |
| 16 | while (0); |
| 17 | |
| 18 | +int be; |
| 19 | +static uint16_t read16(uint16_t x, int be) |
| 20 | +{ |
| 21 | + if (be) |
| 22 | + return be16toh(x); |
| 23 | + return le16toh(x); |
| 24 | +} |
| 25 | + |
| 26 | +static uint32_t read32(uint32_t x, int be) |
| 27 | +{ |
| 28 | + if (be) |
| 29 | + return be32toh(x); |
| 30 | + return le32toh(x); |
| 31 | +} |
| 32 | + |
| 33 | +static uint64_t read64(uint64_t x, int be) |
| 34 | +{ |
| 35 | + if (be) |
| 36 | + return be64toh(x); |
| 37 | + return le64toh(x); |
| 38 | +} |
| 39 | + |
| 40 | /* Returns 0 if everything is ok, != 0 in case of error. */ |
| 41 | int |
| 42 | process_elf_file32 (const char *file_name, const char *lib, int *flag, |
| 43 | @@ -59,15 +81,17 @@ process_elf_file32 (const char *file_nam |
| 44 | elf_header = (Elf32_Ehdr *) file_contents; |
| 45 | *osversion = 0; |
| 46 | |
| 47 | - if (elf_header->e_type != ET_DYN) |
| 48 | + be = (elf_header->e_ident[EI_DATA] == ELFDATA2MSB); |
| 49 | + |
| 50 | + if (read16(elf_header->e_type, be) != ET_DYN) |
| 51 | { |
| 52 | error (0, 0, _("%s is not a shared object file (Type: %d).\n"), file_name, |
| 53 | - elf_header->e_type); |
| 54 | + read16(elf_header->e_type, be)); |
| 55 | return 1; |
| 56 | } |
| 57 | |
| 58 | /* Get information from elf program header. */ |
| 59 | - elf_pheader = (Elf32_Phdr *) (elf_header->e_phoff + file_contents); |
| 60 | + elf_pheader = (Elf32_Phdr *) (read32(elf_header->e_phoff, be) + file_contents); |
| 61 | check_ptr (elf_pheader); |
| 62 | |
| 63 | /* The library is an elf library, now search for soname and |
| 64 | @@ -79,27 +103,27 @@ process_elf_file32 (const char *file_nam |
| 65 | dynamic_size = 0; |
| 66 | program_interpreter = NULL; |
| 67 | for (i = 0, segment = elf_pheader; |
| 68 | - i < elf_header->e_phnum; i++, segment++) |
| 69 | + i < read16(elf_header->e_phnum, be); i++, segment++) |
| 70 | { |
| 71 | check_ptr (segment); |
| 72 | |
| 73 | - switch (segment->p_type) |
| 74 | + switch (read32(segment->p_type, be)) |
| 75 | { |
| 76 | case PT_LOAD: |
| 77 | if (loadaddr == (Elf32_Addr) -1) |
| 78 | - loadaddr = segment->p_vaddr - segment->p_offset; |
| 79 | + loadaddr = read32(segment->p_vaddr, be) - read32(segment->p_offset, be); |
| 80 | break; |
| 81 | |
| 82 | case PT_DYNAMIC: |
| 83 | if (dynamic_addr) |
| 84 | error (0, 0, _("more than one dynamic segment\n")); |
| 85 | |
| 86 | - dynamic_addr = segment->p_offset; |
| 87 | - dynamic_size = segment->p_filesz; |
| 88 | + dynamic_addr = read32(segment->p_offset, be); |
| 89 | + dynamic_size = read32(segment->p_filesz, be); |
| 90 | break; |
| 91 | |
| 92 | case PT_INTERP: |
| 93 | - program_interpreter = (char *) (file_contents + segment->p_offset); |
| 94 | + program_interpreter = (char *) (file_contents + read32(segment->p_offset, be)); |
| 95 | check_ptr (program_interpreter); |
| 96 | |
| 97 | /* Check if this is enough to classify the binary. */ |
| 98 | @@ -113,20 +137,20 @@ process_elf_file32 (const char *file_nam |
| 99 | break; |
| 100 | |
| 101 | case PT_NOTE: |
| 102 | - if (!*osversion && segment->p_filesz >= 32 && segment->p_align >= 4) |
| 103 | + if (!*osversion && read32(segment->p_filesz, be) >= 32 && segment->p_align >= 4) |
| 104 | { |
| 105 | Elf32_Word *abi_note = (Elf32_Word *) (file_contents |
| 106 | - + segment->p_offset); |
| 107 | - Elf32_Addr size = segment->p_filesz; |
| 108 | + + read32(segment->p_offset, be)); |
| 109 | + Elf32_Addr size = read32(segment->p_filesz, be); |
| 110 | |
| 111 | - while (abi_note [0] != 4 || abi_note [1] != 16 |
| 112 | - || abi_note [2] != 1 |
| 113 | + while (read32(abi_note [0], be) != 4 || read32(abi_note [1], be) != 16 |
| 114 | + || read32(abi_note [2], be) != 1 |
| 115 | || memcmp (abi_note + 3, "GNU", 4) != 0) |
| 116 | { |
| 117 | -#define ROUND(len) (((len) + sizeof (Elf32_Word)) - 1) & -sizeof (Elf32_Word))) |
| 118 | - Elf32_Addr) note_size = 3 * sizeof (Elf32_Word)) |
| 119 | - + ROUND (abi_note[0]) |
| 120 | - + ROUND (abi_note[1]); |
| 121 | +#define ROUND(len) (((len) + sizeof (Elf32_Word) - 1) & -sizeof (Elf32_Word)) |
| 122 | + Elf32_Addr note_size = 3 * sizeof (Elf32_Word) |
| 123 | + + ROUND (read32(abi_note[0], be)) |
| 124 | + + ROUND (read32(abi_note[1], be)); |
| 125 | |
| 126 | if (size - 32 < note_size || note_size == 0) |
| 127 | { |
| 128 | @@ -140,10 +164,10 @@ process_elf_file32 (const char *file_nam |
| 129 | if (size == 0) |
| 130 | break; |
| 131 | |
| 132 | - *osversion = (abi_note [4] << 24) | |
| 133 | - ((abi_note [5] & 0xff) << 16) | |
| 134 | - ((abi_note [6] & 0xff) << 8) | |
| 135 | - (abi_note [7] & 0xff); |
| 136 | + *osversion = (read32(abi_note [4], be) << 24) | |
| 137 | + ((read32(abi_note [5], be) & 0xff) << 16) | |
| 138 | + ((read32(abi_note [6], be) & 0xff) << 8) | |
| 139 | + (read32(abi_note [7], be) & 0xff); |
| 140 | } |
| 141 | break; |
| 142 | |
| 143 | @@ -167,13 +191,13 @@ process_elf_file32 (const char *file_nam |
| 144 | |
| 145 | /* Find the string table. */ |
| 146 | dynamic_strings = NULL; |
| 147 | - for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL; |
| 148 | + for (dyn_entry = dynamic_segment; read32(dyn_entry->d_tag, be) != DT_NULL; |
| 149 | ++dyn_entry) |
| 150 | { |
| 151 | check_ptr (dyn_entry); |
| 152 | - if (dyn_entry->d_tag == DT_STRTAB) |
| 153 | + if (read32(dyn_entry->d_tag, be) == DT_STRTAB) |
| 154 | { |
| 155 | - dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr); |
| 156 | + dynamic_strings = (char *) (file_contents + read32(dyn_entry->d_un.d_val, be) - loadaddr); |
| 157 | check_ptr (dynamic_strings); |
| 158 | break; |
| 159 | } |
| 160 | @@ -183,15 +207,15 @@ process_elf_file32 (const char *file_nam |
| 161 | return 1; |
| 162 | |
| 163 | /* Now read the DT_NEEDED and DT_SONAME entries. */ |
| 164 | - for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL; |
| 165 | + for (dyn_entry = dynamic_segment; read32(dyn_entry->d_tag, be) != DT_NULL; |
| 166 | ++dyn_entry) |
| 167 | { |
| 168 | - if (dyn_entry->d_tag == DT_NEEDED || dyn_entry->d_tag == DT_SONAME) |
| 169 | + if (read32(dyn_entry->d_tag, be) == DT_NEEDED || read32(dyn_entry->d_tag, be) == DT_SONAME) |
| 170 | { |
| 171 | - char *name = dynamic_strings + dyn_entry->d_un.d_val; |
| 172 | + char *name = dynamic_strings + read32(dyn_entry->d_un.d_val, be); |
| 173 | check_ptr (name); |
| 174 | |
| 175 | - if (dyn_entry->d_tag == DT_NEEDED) |
| 176 | + if (read32(dyn_entry->d_tag, be) == DT_NEEDED) |
| 177 | { |
| 178 | |
| 179 | if (*flag == FLAG_ELF) |
| 180 | @@ -208,7 +232,7 @@ process_elf_file32 (const char *file_nam |
| 181 | } |
| 182 | } |
| 183 | |
| 184 | - else if (dyn_entry->d_tag == DT_SONAME) |
| 185 | + else if (read32(dyn_entry->d_tag, be) == DT_SONAME) |
| 186 | *soname = xstrdup (name); |
| 187 | |
| 188 | /* Do we have everything we need? */ |
| 189 | @@ -246,15 +270,17 @@ process_elf_file64 (const char *file_nam |
| 190 | elf_header = (Elf64_Ehdr *) file_contents; |
| 191 | *osversion = 0; |
| 192 | |
| 193 | - if (elf_header->e_type != ET_DYN) |
| 194 | + be = (elf_header->e_ident[EI_DATA] == ELFDATA2MSB); |
| 195 | + |
| 196 | + if (read16(elf_header->e_type, be) != ET_DYN) |
| 197 | { |
| 198 | error (0, 0, _("%s is not a shared object file (Type: %d).\n"), file_name, |
| 199 | - elf_header->e_type); |
| 200 | + read16(elf_header->e_type, be)); |
| 201 | return 1; |
| 202 | } |
| 203 | |
| 204 | /* Get information from elf program header. */ |
| 205 | - elf_pheader = (Elf64_Phdr *) (elf_header->e_phoff + file_contents); |
| 206 | + elf_pheader = (Elf64_Phdr *) (read64(elf_header->e_phoff, be) + file_contents); |
| 207 | check_ptr (elf_pheader); |
| 208 | |
| 209 | /* The library is an elf library, now search for soname and |
| 210 | @@ -266,27 +292,27 @@ process_elf_file64 (const char *file_nam |
| 211 | dynamic_size = 0; |
| 212 | program_interpreter = NULL; |
| 213 | for (i = 0, segment = elf_pheader; |
| 214 | - i < elf_header->e_phnum; i++, segment++) |
| 215 | + i < read16(elf_header->e_phnum, be); i++, segment++) |
| 216 | { |
| 217 | check_ptr (segment); |
| 218 | |
| 219 | - switch (segment->p_type) |
| 220 | + switch (read32(segment->p_type, be)) |
| 221 | { |
| 222 | case PT_LOAD: |
| 223 | if (loadaddr == (Elf64_Addr) -1) |
| 224 | - loadaddr = segment->p_vaddr - segment->p_offset; |
| 225 | + loadaddr = read64(segment->p_vaddr, be) - read64(segment->p_offset, be); |
| 226 | break; |
| 227 | |
| 228 | case PT_DYNAMIC: |
| 229 | if (dynamic_addr) |
| 230 | error (0, 0, _("more than one dynamic segment\n")); |
| 231 | |
| 232 | - dynamic_addr = segment->p_offset; |
| 233 | - dynamic_size = segment->p_filesz; |
| 234 | + dynamic_addr = read64(segment->p_offset, be); |
| 235 | + dynamic_size = read32(segment->p_filesz, be); |
| 236 | break; |
| 237 | |
| 238 | case PT_INTERP: |
| 239 | - program_interpreter = (char *) (file_contents + segment->p_offset); |
| 240 | + program_interpreter = (char *) (file_contents + read64(segment->p_offset, be)); |
| 241 | check_ptr (program_interpreter); |
| 242 | |
| 243 | /* Check if this is enough to classify the binary. */ |
| 244 | @@ -300,20 +326,21 @@ process_elf_file64 (const char *file_nam |
| 245 | break; |
| 246 | |
| 247 | case PT_NOTE: |
| 248 | - if (!*osversion && segment->p_filesz >= 32 && segment->p_align >= 4) |
| 249 | + if (!*osversion && read32(segment->p_filesz, be) >= 32 && read32(segment->p_align, be) >= 4) |
| 250 | { |
| 251 | Elf64_Word *abi_note = (Elf64_Word *) (file_contents |
| 252 | - + segment->p_offset); |
| 253 | - Elf64_Addr size = segment->p_filesz; |
| 254 | + + read64(segment->p_offset, be)); |
| 255 | + Elf64_Addr size = read32(segment->p_filesz, be); |
| 256 | |
| 257 | - while (abi_note [0] != 4 || abi_note [1] != 16 |
| 258 | - || abi_note [2] != 1 |
| 259 | + while (read32(abi_note [0], be) != 4 || read32(abi_note [1], be) != 16 |
| 260 | + || read32(abi_note [2], be) != 1 |
| 261 | || memcmp (abi_note + 3, "GNU", 4) != 0) |
| 262 | { |
| 263 | +#undef ROUND |
| 264 | #define ROUND(len) (((len) + sizeof (Elf64_Word) - 1) & -sizeof (Elf64_Word)) |
| 265 | Elf64_Addr note_size = 3 * sizeof (Elf64_Word) |
| 266 | - + ROUND (abi_note[0]) |
| 267 | - + ROUND (abi_note[1]); |
| 268 | + + ROUND (read32(abi_note[0], be)) |
| 269 | + + ROUND (read32(abi_note[1], be)); |
| 270 | |
| 271 | if (size - 32 < note_size || note_size == 0) |
| 272 | { |
| 273 | @@ -327,10 +354,10 @@ process_elf_file64 (const char *file_nam |
| 274 | if (size == 0) |
| 275 | break; |
| 276 | |
| 277 | - *osversion = (abi_note [4] << 24) | |
| 278 | - ((abi_note [5] & 0xff) << 16) | |
| 279 | - ((abi_note [6] & 0xff) << 8) | |
| 280 | - (abi_note [7] & 0xff); |
| 281 | + *osversion = (read32(abi_note [4], be) << 24) | |
| 282 | + ((read32(abi_note [5], be) & 0xff) << 16) | |
| 283 | + ((read32(abi_note [6], be) & 0xff) << 8) | |
| 284 | + (read32(abi_note [7], be) & 0xff); |
| 285 | } |
| 286 | break; |
| 287 | |
| 288 | @@ -354,13 +381,13 @@ process_elf_file64 (const char *file_nam |
| 289 | |
| 290 | /* Find the string table. */ |
| 291 | dynamic_strings = NULL; |
| 292 | - for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL; |
| 293 | + for (dyn_entry = dynamic_segment; read64(dyn_entry->d_tag, be) != DT_NULL; |
| 294 | ++dyn_entry) |
| 295 | { |
| 296 | check_ptr (dyn_entry); |
| 297 | - if (dyn_entry->d_tag == DT_STRTAB) |
| 298 | + if (read64(dyn_entry->d_tag, be) == DT_STRTAB) |
| 299 | { |
| 300 | - dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr); |
| 301 | + dynamic_strings = (char *) (file_contents + read64(dyn_entry->d_un.d_val, be) - loadaddr); |
| 302 | check_ptr (dynamic_strings); |
| 303 | break; |
| 304 | } |
| 305 | @@ -370,15 +397,15 @@ process_elf_file64 (const char *file_nam |
| 306 | return 1; |
| 307 | |
| 308 | /* Now read the DT_NEEDED and DT_SONAME entries. */ |
| 309 | - for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL; |
| 310 | + for (dyn_entry = dynamic_segment; read64(dyn_entry->d_tag, be) != DT_NULL; |
| 311 | ++dyn_entry) |
| 312 | { |
| 313 | - if (dyn_entry->d_tag == DT_NEEDED || dyn_entry->d_tag == DT_SONAME) |
| 314 | + if (read64(dyn_entry->d_tag, be) == DT_NEEDED || read64(dyn_entry->d_tag, be) == DT_SONAME) |
| 315 | { |
| 316 | - char *name = dynamic_strings + dyn_entry->d_un.d_val; |
| 317 | + char *name = dynamic_strings + read64(dyn_entry->d_un.d_val, be); |
| 318 | check_ptr (name); |
| 319 | |
| 320 | - if (dyn_entry->d_tag == DT_NEEDED) |
| 321 | + if (read64(dyn_entry->d_tag, be) == DT_NEEDED) |
| 322 | { |
| 323 | |
| 324 | if (*flag == FLAG_ELF) |
| 325 | @@ -395,7 +422,7 @@ process_elf_file64 (const char *file_nam |
| 326 | } |
| 327 | } |
| 328 | |
| 329 | - else if (dyn_entry->d_tag == DT_SONAME) |
| 330 | + else if (read64(dyn_entry->d_tag, be) == DT_SONAME) |
| 331 | *soname = xstrdup (name); |
| 332 | |
| 333 | /* Do we have everything we need? */ |
| 334 | Index: ldconfig-native-2.12.1/readlib.c |
| 335 | =================================================================== |
| 336 | --- ldconfig-native-2.12.1.orig/readlib.c |
| 337 | +++ ldconfig-native-2.12.1/readlib.c |
| 338 | @@ -169,7 +169,8 @@ process_file (const char *real_file_name |
| 339 | ret = 1; |
| 340 | } |
| 341 | /* Libraries have to be shared object files. */ |
| 342 | - else if (elf_header->e_type != ET_DYN) |
| 343 | + else if ((elf_header->e_ident[EI_DATA] == ELFDATA2MSB && be16toh(elf_header->e_type) != ET_DYN) || |
| 344 | + (elf_header->e_ident[EI_DATA] == ELFDATA2LSB && le16toh(elf_header->e_type) != ET_DYN)) |
| 345 | ret = 1; |
| 346 | else if (process_elf_file (file_name, lib, flag, osversion, soname, |
| 347 | file_contents, statbuf.st_size)) |
| 348 | Index: ldconfig-native-2.12.1/cache.c |
| 349 | =================================================================== |
| 350 | --- ldconfig-native-2.12.1.orig/cache.c |
| 351 | +++ ldconfig-native-2.12.1/cache.c |
| 352 | @@ -39,6 +39,29 @@ |
| 353 | # define N_(msgid) msgid |
| 354 | #define _(msg) msg |
| 355 | |
| 356 | +extern int be; |
| 357 | + |
| 358 | +static uint16_t write16(uint16_t x, int be) |
| 359 | +{ |
| 360 | + if (be) |
| 361 | + return htobe16(x); |
| 362 | + return htole16(x); |
| 363 | +} |
| 364 | + |
| 365 | +static uint32_t write32(uint32_t x, int be) |
| 366 | +{ |
| 367 | + if (be) |
| 368 | + return htobe32(x); |
| 369 | + return htole32(x); |
| 370 | +} |
| 371 | + |
| 372 | +static uint64_t write64(uint64_t x, int be) |
| 373 | +{ |
| 374 | + if (be) |
| 375 | + return htobe64(x); |
| 376 | + return htole64(x); |
| 377 | +} |
| 378 | + |
| 379 | struct cache_entry |
| 380 | { |
| 381 | char *lib; /* Library name. */ |
| 382 | @@ -279,7 +302,12 @@ save_cache (const char *cache_name) |
| 383 | /* Number of normal cache entries. */ |
| 384 | int cache_entry_old_count = 0; |
| 385 | |
| 386 | - for (entry = entries; entry != NULL; entry = entry->next) |
| 387 | + if (be) |
| 388 | + printf("saving cache in big endian encoding\n"); |
| 389 | + else |
| 390 | + printf("saving cache in little endian encoding\n"); |
| 391 | + |
| 392 | + for (entry = entries; entry != NULL; entry = entry->next) |
| 393 | { |
| 394 | /* Account the final NULs. */ |
| 395 | total_strlen += strlen (entry->lib) + strlen (entry->path) + 2; |
| 396 | @@ -310,7 +338,7 @@ save_cache (const char *cache_name) |
| 397 | memset (file_entries, '\0', sizeof (struct cache_file)); |
| 398 | memcpy (file_entries->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1); |
| 399 | |
| 400 | - file_entries->nlibs = cache_entry_old_count; |
| 401 | + file_entries->nlibs = write32(cache_entry_old_count, be); |
| 402 | } |
| 403 | |
| 404 | struct cache_file_new *file_entries_new = NULL; |
| 405 | @@ -330,8 +358,8 @@ save_cache (const char *cache_name) |
| 406 | memcpy (file_entries_new->version, CACHE_VERSION, |
| 407 | sizeof CACHE_VERSION - 1); |
| 408 | |
| 409 | - file_entries_new->nlibs = cache_entry_count; |
| 410 | - file_entries_new->len_strings = total_strlen; |
| 411 | + file_entries_new->nlibs = write32(cache_entry_count, be); |
| 412 | + file_entries_new->len_strings = write32(total_strlen, be); |
| 413 | } |
| 414 | |
| 415 | /* Pad for alignment of cache_file_new. */ |
| 416 | @@ -358,9 +386,9 @@ save_cache (const char *cache_name) |
| 417 | /* First the library. */ |
| 418 | if (opt_format != 2 && entry->hwcap == 0) |
| 419 | { |
| 420 | - file_entries->libs[idx_old].flags = entry->flags; |
| 421 | + file_entries->libs[idx_old].flags = write32(entry->flags, be); |
| 422 | /* XXX: Actually we can optimize here and remove duplicates. */ |
| 423 | - file_entries->libs[idx_old].key = str_offset + pad; |
| 424 | + file_entries->libs[idx_old].key = write32(str_offset + pad, be); |
| 425 | } |
| 426 | if (opt_format != 0) |
| 427 | { |
| 428 | @@ -368,10 +396,10 @@ save_cache (const char *cache_name) |
| 429 | not doing so makes the code easier, the string table |
| 430 | always begins at the beginning of the the new cache |
| 431 | struct. */ |
| 432 | - file_entries_new->libs[idx_new].flags = entry->flags; |
| 433 | - file_entries_new->libs[idx_new].osversion = entry->osversion; |
| 434 | - file_entries_new->libs[idx_new].hwcap = entry->hwcap; |
| 435 | - file_entries_new->libs[idx_new].key = str_offset; |
| 436 | + file_entries_new->libs[idx_new].flags = write32(entry->flags, be); |
| 437 | + file_entries_new->libs[idx_new].osversion = write32(entry->osversion, be); |
| 438 | + file_entries_new->libs[idx_new].hwcap = write64(entry->hwcap, be); |
| 439 | + file_entries_new->libs[idx_new].key = write32(str_offset, be); |
| 440 | } |
| 441 | |
| 442 | size_t len = strlen (entry->lib) + 1; |
| 443 | @@ -379,9 +407,9 @@ save_cache (const char *cache_name) |
| 444 | str_offset += len; |
| 445 | /* Then the path. */ |
| 446 | if (opt_format != 2 && entry->hwcap == 0) |
| 447 | - file_entries->libs[idx_old].value = str_offset + pad; |
| 448 | + file_entries->libs[idx_old].value = write32(str_offset + pad, be); |
| 449 | if (opt_format != 0) |
| 450 | - file_entries_new->libs[idx_new].value = str_offset; |
| 451 | + file_entries_new->libs[idx_new].value = write32(str_offset, be); |
| 452 | len = strlen (entry->path) + 1; |
| 453 | str = mempcpy (str, entry->path, len); |
| 454 | str_offset += len; |