Blame libarchive/archive_read_support_format_rar.c

Packit Service 1d0348
/*-
Packit Service 1d0348
* Copyright (c) 2003-2007 Tim Kientzle
Packit Service 1d0348
* Copyright (c) 2011 Andres Mejia
Packit Service 1d0348
* All rights reserved.
Packit Service 1d0348
*
Packit Service 1d0348
* Redistribution and use in source and binary forms, with or without
Packit Service 1d0348
* modification, are permitted provided that the following conditions
Packit Service 1d0348
* are met:
Packit Service 1d0348
* 1. Redistributions of source code must retain the above copyright
Packit Service 1d0348
*    notice, this list of conditions and the following disclaimer.
Packit Service 1d0348
* 2. Redistributions in binary form must reproduce the above copyright
Packit Service 1d0348
*    notice, this list of conditions and the following disclaimer in the
Packit Service 1d0348
*    documentation and/or other materials provided with the distribution.
Packit Service 1d0348
*
Packit Service 1d0348
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
Packit Service 1d0348
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Packit Service 1d0348
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
Packit Service 1d0348
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
Packit Service 1d0348
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
Packit Service 1d0348
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit Service 1d0348
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit Service 1d0348
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit Service 1d0348
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
Packit Service 1d0348
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 1d0348
*/
Packit Service 1d0348
Packit Service 1d0348
#include "archive_platform.h"
Packit Service 1d0348
Packit Service 1d0348
#ifdef HAVE_ERRNO_H
Packit Service 1d0348
#include <errno.h>
Packit Service 1d0348
#endif
Packit Service 1d0348
#include <time.h>
Packit Service 1d0348
#include <limits.h>
Packit Service 1d0348
#ifdef HAVE_ZLIB_H
Packit Service 1d0348
#include <zlib.h> /* crc32 */
Packit Service 1d0348
#endif
Packit Service 1d0348
Packit Service 1d0348
#include "archive.h"
Packit Service 1d0348
#ifndef HAVE_ZLIB_H
Packit Service 1d0348
#include "archive_crc32.h"
Packit Service 1d0348
#endif
Packit Service 1d0348
#include "archive_endian.h"
Packit Service 1d0348
#include "archive_entry.h"
Packit Service 1d0348
#include "archive_entry_locale.h"
Packit Service 1d0348
#include "archive_ppmd7_private.h"
Packit Service 1d0348
#include "archive_private.h"
Packit Service 1d0348
#include "archive_read_private.h"
Packit Service 1d0348
Packit Service 1d0348
/* RAR signature, also known as the mark header */
Packit Service 1d0348
#define RAR_SIGNATURE "\x52\x61\x72\x21\x1A\x07\x00"
Packit Service 1d0348
Packit Service 1d0348
/* Header types */
Packit Service 1d0348
#define MARK_HEAD    0x72
Packit Service 1d0348
#define MAIN_HEAD    0x73
Packit Service 1d0348
#define FILE_HEAD    0x74
Packit Service 1d0348
#define COMM_HEAD    0x75
Packit Service 1d0348
#define AV_HEAD      0x76
Packit Service 1d0348
#define SUB_HEAD     0x77
Packit Service 1d0348
#define PROTECT_HEAD 0x78
Packit Service 1d0348
#define SIGN_HEAD    0x79
Packit Service 1d0348
#define NEWSUB_HEAD  0x7a
Packit Service 1d0348
#define ENDARC_HEAD  0x7b
Packit Service 1d0348
Packit Service 1d0348
/* Main Header Flags */
Packit Service 1d0348
#define MHD_VOLUME       0x0001
Packit Service 1d0348
#define MHD_COMMENT      0x0002
Packit Service 1d0348
#define MHD_LOCK         0x0004
Packit Service 1d0348
#define MHD_SOLID        0x0008
Packit Service 1d0348
#define MHD_NEWNUMBERING 0x0010
Packit Service 1d0348
#define MHD_AV           0x0020
Packit Service 1d0348
#define MHD_PROTECT      0x0040
Packit Service 1d0348
#define MHD_PASSWORD     0x0080
Packit Service 1d0348
#define MHD_FIRSTVOLUME  0x0100
Packit Service 1d0348
#define MHD_ENCRYPTVER   0x0200
Packit Service 1d0348
Packit Service 1d0348
/* Flags common to all headers */
Packit Service 1d0348
#define HD_MARKDELETION     0x4000
Packit Service 1d0348
#define HD_ADD_SIZE_PRESENT 0x8000
Packit Service 1d0348
Packit Service 1d0348
/* File Header Flags */
Packit Service 1d0348
#define FHD_SPLIT_BEFORE 0x0001
Packit Service 1d0348
#define FHD_SPLIT_AFTER  0x0002
Packit Service 1d0348
#define FHD_PASSWORD     0x0004
Packit Service 1d0348
#define FHD_COMMENT      0x0008
Packit Service 1d0348
#define FHD_SOLID        0x0010
Packit Service 1d0348
#define FHD_LARGE        0x0100
Packit Service 1d0348
#define FHD_UNICODE      0x0200
Packit Service 1d0348
#define FHD_SALT         0x0400
Packit Service 1d0348
#define FHD_VERSION      0x0800
Packit Service 1d0348
#define FHD_EXTTIME      0x1000
Packit Service 1d0348
#define FHD_EXTFLAGS     0x2000
Packit Service 1d0348
Packit Service 1d0348
/* File dictionary sizes */
Packit Service 1d0348
#define DICTIONARY_SIZE_64   0x00
Packit Service 1d0348
#define DICTIONARY_SIZE_128  0x20
Packit Service 1d0348
#define DICTIONARY_SIZE_256  0x40
Packit Service 1d0348
#define DICTIONARY_SIZE_512  0x60
Packit Service 1d0348
#define DICTIONARY_SIZE_1024 0x80
Packit Service 1d0348
#define DICTIONARY_SIZE_2048 0xA0
Packit Service 1d0348
#define DICTIONARY_SIZE_4096 0xC0
Packit Service 1d0348
#define FILE_IS_DIRECTORY    0xE0
Packit Service 1d0348
#define DICTIONARY_MASK      FILE_IS_DIRECTORY
Packit Service 1d0348
Packit Service 1d0348
/* OS Flags */
Packit Service 1d0348
#define OS_MSDOS  0
Packit Service 1d0348
#define OS_OS2    1
Packit Service 1d0348
#define OS_WIN32  2
Packit Service 1d0348
#define OS_UNIX   3
Packit Service 1d0348
#define OS_MAC_OS 4
Packit Service 1d0348
#define OS_BEOS   5
Packit Service 1d0348
Packit Service 1d0348
/* Compression Methods */
Packit Service 1d0348
#define COMPRESS_METHOD_STORE   0x30
Packit Service 1d0348
/* LZSS */
Packit Service 1d0348
#define COMPRESS_METHOD_FASTEST 0x31
Packit Service 1d0348
#define COMPRESS_METHOD_FAST    0x32
Packit Service 1d0348
#define COMPRESS_METHOD_NORMAL  0x33
Packit Service 1d0348
/* PPMd Variant H */
Packit Service 1d0348
#define COMPRESS_METHOD_GOOD    0x34
Packit Service 1d0348
#define COMPRESS_METHOD_BEST    0x35
Packit Service 1d0348
Packit Service 1d0348
#define CRC_POLYNOMIAL 0xEDB88320
Packit Service 1d0348
Packit Service 1d0348
#define NS_UNIT 10000000
Packit Service 1d0348
Packit Service 1d0348
#define DICTIONARY_MAX_SIZE 0x400000
Packit Service 1d0348
Packit Service 1d0348
#define MAINCODE_SIZE      299
Packit Service 1d0348
#define OFFSETCODE_SIZE    60
Packit Service 1d0348
#define LOWOFFSETCODE_SIZE 17
Packit Service 1d0348
#define LENGTHCODE_SIZE    28
Packit Service 1d0348
#define HUFFMAN_TABLE_SIZE \
Packit Service 1d0348
  MAINCODE_SIZE + OFFSETCODE_SIZE + LOWOFFSETCODE_SIZE + LENGTHCODE_SIZE
Packit Service 1d0348
Packit Service 1d0348
#define MAX_SYMBOL_LENGTH 0xF
Packit Service 1d0348
#define MAX_SYMBOLS       20
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * Considering L1,L2 cache miss and a calling of write system-call,
Packit Service 1d0348
 * the best size of the output buffer(uncompressed buffer) is 128K.
Packit Service 1d0348
 * If the structure of extracting process is changed, this value
Packit Service 1d0348
 * might be researched again.
Packit Service 1d0348
 */
Packit Service 1d0348
#define UNP_BUFFER_SIZE   (128 * 1024)
Packit Service 1d0348
Packit Service 1d0348
/* Define this here for non-Windows platforms */
Packit Service 1d0348
#if !((defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__))
Packit Service 1d0348
#define FILE_ATTRIBUTE_DIRECTORY 0x10
Packit Service 1d0348
#endif
Packit Service 1d0348
Packit Service 1d0348
/* Fields common to all headers */
Packit Service 1d0348
struct rar_header
Packit Service 1d0348
{
Packit Service 1d0348
  char crc[2];
Packit Service 1d0348
  char type;
Packit Service 1d0348
  char flags[2];
Packit Service 1d0348
  char size[2];
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
/* Fields common to all file headers */
Packit Service 1d0348
struct rar_file_header
Packit Service 1d0348
{
Packit Service 1d0348
  char pack_size[4];
Packit Service 1d0348
  char unp_size[4];
Packit Service 1d0348
  char host_os;
Packit Service 1d0348
  char file_crc[4];
Packit Service 1d0348
  char file_time[4];
Packit Service 1d0348
  char unp_ver;
Packit Service 1d0348
  char method;
Packit Service 1d0348
  char name_size[2];
Packit Service 1d0348
  char file_attr[4];
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
struct huffman_tree_node
Packit Service 1d0348
{
Packit Service 1d0348
  int branches[2];
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
struct huffman_table_entry
Packit Service 1d0348
{
Packit Service 1d0348
  unsigned int length;
Packit Service 1d0348
  int value;
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
struct huffman_code
Packit Service 1d0348
{
Packit Service 1d0348
  struct huffman_tree_node *tree;
Packit Service 1d0348
  int numentries;
Packit Service 1d0348
  int numallocatedentries;
Packit Service 1d0348
  int minlength;
Packit Service 1d0348
  int maxlength;
Packit Service 1d0348
  int tablesize;
Packit Service 1d0348
  struct huffman_table_entry *table;
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
struct lzss
Packit Service 1d0348
{
Packit Service 1d0348
  unsigned char *window;
Packit Service 1d0348
  int mask;
Packit Service 1d0348
  int64_t position;
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
struct data_block_offsets
Packit Service 1d0348
{
Packit Service 1d0348
  int64_t header_size;
Packit Service 1d0348
  int64_t start_offset;
Packit Service 1d0348
  int64_t end_offset;
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
struct rar
Packit Service 1d0348
{
Packit Service 1d0348
  /* Entries from main RAR header */
Packit Service 1d0348
  unsigned main_flags;
Packit Service 1d0348
  unsigned long file_crc;
Packit Service 1d0348
  char reserved1[2];
Packit Service 1d0348
  char reserved2[4];
Packit Service 1d0348
  char encryptver;
Packit Service 1d0348
Packit Service 1d0348
  /* File header entries */
Packit Service 1d0348
  char compression_method;
Packit Service 1d0348
  unsigned file_flags;
Packit Service 1d0348
  int64_t packed_size;
Packit Service 1d0348
  int64_t unp_size;
Packit Service 1d0348
  time_t mtime;
Packit Service 1d0348
  long mnsec;
Packit Service 1d0348
  mode_t mode;
Packit Service 1d0348
  char *filename;
Packit Service 1d0348
  char *filename_save;
Packit Service 1d0348
  size_t filename_save_size;
Packit Service 1d0348
  size_t filename_allocated;
Packit Service 1d0348
Packit Service 1d0348
  /* File header optional entries */
Packit Service 1d0348
  char salt[8];
Packit Service 1d0348
  time_t atime;
Packit Service 1d0348
  long ansec;
Packit Service 1d0348
  time_t ctime;
Packit Service 1d0348
  long cnsec;
Packit Service 1d0348
  time_t arctime;
Packit Service 1d0348
  long arcnsec;
Packit Service 1d0348
Packit Service 1d0348
  /* Fields to help with tracking decompression of files. */
Packit Service 1d0348
  int64_t bytes_unconsumed;
Packit Service 1d0348
  int64_t bytes_remaining;
Packit Service 1d0348
  int64_t bytes_uncopied;
Packit Service 1d0348
  int64_t offset;
Packit Service 1d0348
  int64_t offset_outgoing;
Packit Service 1d0348
  int64_t offset_seek;
Packit Service 1d0348
  char valid;
Packit Service 1d0348
  unsigned int unp_offset;
Packit Service 1d0348
  unsigned int unp_buffer_size;
Packit Service 1d0348
  unsigned char *unp_buffer;
Packit Service 1d0348
  unsigned int dictionary_size;
Packit Service 1d0348
  char start_new_block;
Packit Service 1d0348
  char entry_eof;
Packit Service 1d0348
  unsigned long crc_calculated;
Packit Service 1d0348
  int found_first_header;
Packit Service 1d0348
  char has_endarc_header;
Packit Service 1d0348
  struct data_block_offsets *dbo;
Packit Service 1d0348
  unsigned int cursor;
Packit Service 1d0348
  unsigned int nodes;
Packit Service 1d0348
Packit Service 1d0348
  /* LZSS members */
Packit Service 1d0348
  struct huffman_code maincode;
Packit Service 1d0348
  struct huffman_code offsetcode;
Packit Service 1d0348
  struct huffman_code lowoffsetcode;
Packit Service 1d0348
  struct huffman_code lengthcode;
Packit Service 1d0348
  unsigned char lengthtable[HUFFMAN_TABLE_SIZE];
Packit Service 1d0348
  struct lzss lzss;
Packit Service 1d0348
  char output_last_match;
Packit Service 1d0348
  unsigned int lastlength;
Packit Service 1d0348
  unsigned int lastoffset;
Packit Service 1d0348
  unsigned int oldoffset[4];
Packit Service 1d0348
  unsigned int lastlowoffset;
Packit Service 1d0348
  unsigned int numlowoffsetrepeats;
Packit Service 1d0348
  int64_t filterstart;
Packit Service 1d0348
  char start_new_table;
Packit Service 1d0348
Packit Service 1d0348
  /* PPMd Variant H members */
Packit Service 1d0348
  char ppmd_valid;
Packit Service 1d0348
  char ppmd_eod;
Packit Service 1d0348
  char is_ppmd_block;
Packit Service 1d0348
  int ppmd_escape;
Packit Service 1d0348
  CPpmd7 ppmd7_context;
Packit Service 1d0348
  CPpmd7z_RangeDec range_dec;
Packit Service 1d0348
  IByteIn bytein;
Packit Service 1d0348
Packit Service 1d0348
  /*
Packit Service 1d0348
   * String conversion object.
Packit Service 1d0348
   */
Packit Service 1d0348
  int init_default_conversion;
Packit Service 1d0348
  struct archive_string_conv *sconv_default;
Packit Service 1d0348
  struct archive_string_conv *opt_sconv;
Packit Service 1d0348
  struct archive_string_conv *sconv_utf8;
Packit Service 1d0348
  struct archive_string_conv *sconv_utf16be;
Packit Service 1d0348
Packit Service 1d0348
  /*
Packit Service 1d0348
   * Bit stream reader.
Packit Service 1d0348
   */
Packit Service 1d0348
  struct rar_br {
Packit Service 1d0348
#define CACHE_TYPE	uint64_t
Packit Service 1d0348
#define CACHE_BITS	(8 * sizeof(CACHE_TYPE))
Packit Service 1d0348
    /* Cache buffer. */
Packit Service 1d0348
    CACHE_TYPE		 cache_buffer;
Packit Service 1d0348
    /* Indicates how many bits avail in cache_buffer. */
Packit Service 1d0348
    int			 cache_avail;
Packit Service 1d0348
    ssize_t		 avail_in;
Packit Service 1d0348
    const unsigned char *next_in;
Packit Service 1d0348
  } br;
Packit Service 1d0348
Packit Service 1d0348
  /*
Packit Service 1d0348
   * Custom field to denote that this archive contains encrypted entries
Packit Service 1d0348
   */
Packit Service 1d0348
  int has_encrypted_entries;
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
static int archive_read_support_format_rar_capabilities(struct archive_read *);
Packit Service 1d0348
static int archive_read_format_rar_has_encrypted_entries(struct archive_read *);
Packit Service 1d0348
static int archive_read_format_rar_bid(struct archive_read *, int);
Packit Service 1d0348
static int archive_read_format_rar_options(struct archive_read *,
Packit Service 1d0348
    const char *, const char *);
Packit Service 1d0348
static int archive_read_format_rar_read_header(struct archive_read *,
Packit Service 1d0348
    struct archive_entry *);
Packit Service 1d0348
static int archive_read_format_rar_read_data(struct archive_read *,
Packit Service 1d0348
    const void **, size_t *, int64_t *);
Packit Service 1d0348
static int archive_read_format_rar_read_data_skip(struct archive_read *a);
Packit Service 1d0348
static int64_t archive_read_format_rar_seek_data(struct archive_read *, int64_t,
Packit Service 1d0348
    int);
Packit Service 1d0348
static int archive_read_format_rar_cleanup(struct archive_read *);
Packit Service 1d0348
Packit Service 1d0348
/* Support functions */
Packit Service 1d0348
static int read_header(struct archive_read *, struct archive_entry *, char);
Packit Service 1d0348
static time_t get_time(int);
Packit Service 1d0348
static int read_exttime(const char *, struct rar *, const char *);
Packit Service 1d0348
static int read_symlink_stored(struct archive_read *, struct archive_entry *,
Packit Service 1d0348
                               struct archive_string_conv *);
Packit Service 1d0348
static int read_data_stored(struct archive_read *, const void **, size_t *,
Packit Service 1d0348
                            int64_t *);
Packit Service 1d0348
static int read_data_compressed(struct archive_read *, const void **, size_t *,
Packit Service 1d0348
                          int64_t *);
Packit Service 1d0348
static int rar_br_preparation(struct archive_read *, struct rar_br *);
Packit Service 1d0348
static int parse_codes(struct archive_read *);
Packit Service 1d0348
static void free_codes(struct archive_read *);
Packit Service 1d0348
static int read_next_symbol(struct archive_read *, struct huffman_code *);
Packit Service 1d0348
static int create_code(struct archive_read *, struct huffman_code *,
Packit Service 1d0348
                        unsigned char *, int, char);
Packit Service 1d0348
static int add_value(struct archive_read *, struct huffman_code *, int, int,
Packit Service 1d0348
                     int);
Packit Service 1d0348
static int new_node(struct huffman_code *);
Packit Service 1d0348
static int make_table(struct archive_read *, struct huffman_code *);
Packit Service 1d0348
static int make_table_recurse(struct archive_read *, struct huffman_code *, int,
Packit Service 1d0348
                              struct huffman_table_entry *, int, int);
Packit Service 1d0348
static int64_t expand(struct archive_read *, int64_t);
Packit Service 1d0348
static int copy_from_lzss_window(struct archive_read *, const void **,
Packit Service 1d0348
                                   int64_t, int);
Packit Service 1d0348
static const void *rar_read_ahead(struct archive_read *, size_t, ssize_t *);
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * Bit stream reader.
Packit Service 1d0348
 */
Packit Service 1d0348
/* Check that the cache buffer has enough bits. */
Packit Service 1d0348
#define rar_br_has(br, n) ((br)->cache_avail >= n)
Packit Service 1d0348
/* Get compressed data by bit. */
Packit Service 1d0348
#define rar_br_bits(br, n)        \
Packit Service 1d0348
  (((uint32_t)((br)->cache_buffer >>    \
Packit Service 1d0348
    ((br)->cache_avail - (n)))) & cache_masks[n])
Packit Service 1d0348
#define rar_br_bits_forced(br, n)     \
Packit Service 1d0348
  (((uint32_t)((br)->cache_buffer <<    \
Packit Service 1d0348
    ((n) - (br)->cache_avail))) & cache_masks[n])
Packit Service 1d0348
/* Read ahead to make sure the cache buffer has enough compressed data we
Packit Service 1d0348
 * will use.
Packit Service 1d0348
 *  True  : completed, there is enough data in the cache buffer.
Packit Service 1d0348
 *  False : there is no data in the stream. */
Packit Service 1d0348
#define rar_br_read_ahead(a, br, n) \
Packit Service 1d0348
  ((rar_br_has(br, (n)) || rar_br_fillup(a, br)) || rar_br_has(br, (n)))
Packit Service 1d0348
/* Notify how many bits we consumed. */
Packit Service 1d0348
#define rar_br_consume(br, n) ((br)->cache_avail -= (n))
Packit Service 1d0348
#define rar_br_consume_unalined_bits(br) ((br)->cache_avail &= ~7)
Packit Service 1d0348
Packit Service 1d0348
static const uint32_t cache_masks[] = {
Packit Service 1d0348
  0x00000000, 0x00000001, 0x00000003, 0x00000007,
Packit Service 1d0348
  0x0000000F, 0x0000001F, 0x0000003F, 0x0000007F,
Packit Service 1d0348
  0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF,
Packit Service 1d0348
  0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF,
Packit Service 1d0348
  0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF,
Packit Service 1d0348
  0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF,
Packit Service 1d0348
  0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF,
Packit Service 1d0348
  0x0FFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF,
Packit Service 1d0348
  0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * Shift away used bits in the cache data and fill it up with following bits.
Packit Service 1d0348
 * Call this when cache buffer does not have enough bits you need.
Packit Service 1d0348
 *
Packit Service 1d0348
 * Returns 1 if the cache buffer is full.
Packit Service 1d0348
 * Returns 0 if the cache buffer is not full; input buffer is empty.
Packit Service 1d0348
 */
Packit Service 1d0348
static int
Packit Service 1d0348
rar_br_fillup(struct archive_read *a, struct rar_br *br)
Packit Service 1d0348
{
Packit Service 1d0348
  struct rar *rar = (struct rar *)(a->format->data);
Packit Service 1d0348
  int n = CACHE_BITS - br->cache_avail;
Packit Service 1d0348
Packit Service 1d0348
  for (;;) {
Packit Service 1d0348
    switch (n >> 3) {
Packit Service 1d0348
    case 8:
Packit Service 1d0348
      if (br->avail_in >= 8) {
Packit Service 1d0348
        br->cache_buffer =
Packit Service 1d0348
            ((uint64_t)br->next_in[0]) << 56 |
Packit Service 1d0348
            ((uint64_t)br->next_in[1]) << 48 |
Packit Service 1d0348
            ((uint64_t)br->next_in[2]) << 40 |
Packit Service 1d0348
            ((uint64_t)br->next_in[3]) << 32 |
Packit Service 1d0348
            ((uint32_t)br->next_in[4]) << 24 |
Packit Service 1d0348
            ((uint32_t)br->next_in[5]) << 16 |
Packit Service 1d0348
            ((uint32_t)br->next_in[6]) << 8 |
Packit Service 1d0348
             (uint32_t)br->next_in[7];
Packit Service 1d0348
        br->next_in += 8;
Packit Service 1d0348
        br->avail_in -= 8;
Packit Service 1d0348
        br->cache_avail += 8 * 8;
Packit Service 1d0348
        rar->bytes_unconsumed += 8;
Packit Service 1d0348
        rar->bytes_remaining -= 8;
Packit Service 1d0348
        return (1);
Packit Service 1d0348
      }
Packit Service 1d0348
      break;
Packit Service 1d0348
    case 7:
Packit Service 1d0348
      if (br->avail_in >= 7) {
Packit Service 1d0348
        br->cache_buffer =
Packit Service 1d0348
           (br->cache_buffer << 56) |
Packit Service 1d0348
            ((uint64_t)br->next_in[0]) << 48 |
Packit Service 1d0348
            ((uint64_t)br->next_in[1]) << 40 |
Packit Service 1d0348
            ((uint64_t)br->next_in[2]) << 32 |
Packit Service 1d0348
            ((uint32_t)br->next_in[3]) << 24 |
Packit Service 1d0348
            ((uint32_t)br->next_in[4]) << 16 |
Packit Service 1d0348
            ((uint32_t)br->next_in[5]) << 8 |
Packit Service 1d0348
             (uint32_t)br->next_in[6];
Packit Service 1d0348
        br->next_in += 7;
Packit Service 1d0348
        br->avail_in -= 7;
Packit Service 1d0348
        br->cache_avail += 7 * 8;
Packit Service 1d0348
        rar->bytes_unconsumed += 7;
Packit Service 1d0348
        rar->bytes_remaining -= 7;
Packit Service 1d0348
        return (1);
Packit Service 1d0348
      }
Packit Service 1d0348
      break;
Packit Service 1d0348
    case 6:
Packit Service 1d0348
      if (br->avail_in >= 6) {
Packit Service 1d0348
        br->cache_buffer =
Packit Service 1d0348
           (br->cache_buffer << 48) |
Packit Service 1d0348
            ((uint64_t)br->next_in[0]) << 40 |
Packit Service 1d0348
            ((uint64_t)br->next_in[1]) << 32 |
Packit Service 1d0348
            ((uint32_t)br->next_in[2]) << 24 |
Packit Service 1d0348
            ((uint32_t)br->next_in[3]) << 16 |
Packit Service 1d0348
            ((uint32_t)br->next_in[4]) << 8 |
Packit Service 1d0348
             (uint32_t)br->next_in[5];
Packit Service 1d0348
        br->next_in += 6;
Packit Service 1d0348
        br->avail_in -= 6;
Packit Service 1d0348
        br->cache_avail += 6 * 8;
Packit Service 1d0348
        rar->bytes_unconsumed += 6;
Packit Service 1d0348
        rar->bytes_remaining -= 6;
Packit Service 1d0348
        return (1);
Packit Service 1d0348
      }
Packit Service 1d0348
      break;
Packit Service 1d0348
    case 0:
Packit Service 1d0348
      /* We have enough compressed data in
Packit Service 1d0348
       * the cache buffer.*/
Packit Service 1d0348
      return (1);
Packit Service 1d0348
    default:
Packit Service 1d0348
      break;
Packit Service 1d0348
    }
Packit Service 1d0348
    if (br->avail_in <= 0) {
Packit Service 1d0348
Packit Service 1d0348
      if (rar->bytes_unconsumed > 0) {
Packit Service 1d0348
        /* Consume as much as the decompressor
Packit Service 1d0348
         * actually used. */
Packit Service 1d0348
        __archive_read_consume(a, rar->bytes_unconsumed);
Packit Service 1d0348
        rar->bytes_unconsumed = 0;
Packit Service 1d0348
      }
Packit Service 1d0348
      br->next_in = rar_read_ahead(a, 1, &(br->avail_in));
Packit Service 1d0348
      if (br->next_in == NULL)
Packit Service 1d0348
        return (0);
Packit Service 1d0348
      if (br->avail_in == 0)
Packit Service 1d0348
        return (0);
Packit Service 1d0348
    }
Packit Service 1d0348
    br->cache_buffer =
Packit Service 1d0348
       (br->cache_buffer << 8) | *br->next_in++;
Packit Service 1d0348
    br->avail_in--;
Packit Service 1d0348
    br->cache_avail += 8;
Packit Service 1d0348
    n -= 8;
Packit Service 1d0348
    rar->bytes_unconsumed++;
Packit Service 1d0348
    rar->bytes_remaining--;
Packit Service 1d0348
  }
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
rar_br_preparation(struct archive_read *a, struct rar_br *br)
Packit Service 1d0348
{
Packit Service 1d0348
  struct rar *rar = (struct rar *)(a->format->data);
Packit Service 1d0348
Packit Service 1d0348
  if (rar->bytes_remaining > 0) {
Packit Service 1d0348
    br->next_in = rar_read_ahead(a, 1, &(br->avail_in));
Packit Service 1d0348
    if (br->next_in == NULL) {
Packit Service 1d0348
      archive_set_error(&a->archive,
Packit Service 1d0348
          ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
          "Truncated RAR file data");
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
    }
Packit Service 1d0348
    if (br->cache_avail == 0)
Packit Service 1d0348
      (void)rar_br_fillup(a, br);
Packit Service 1d0348
  }
Packit Service 1d0348
  return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
/* Find last bit set */
Packit Service 1d0348
static inline int
Packit Service 1d0348
rar_fls(unsigned int word)
Packit Service 1d0348
{
Packit Service 1d0348
  word |= (word >>  1);
Packit Service 1d0348
  word |= (word >>  2);
Packit Service 1d0348
  word |= (word >>  4);
Packit Service 1d0348
  word |= (word >>  8);
Packit Service 1d0348
  word |= (word >> 16);
Packit Service 1d0348
  return word - (word >> 1);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
/* LZSS functions */
Packit Service 1d0348
static inline int64_t
Packit Service 1d0348
lzss_position(struct lzss *lzss)
Packit Service 1d0348
{
Packit Service 1d0348
  return lzss->position;
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static inline int
Packit Service 1d0348
lzss_mask(struct lzss *lzss)
Packit Service 1d0348
{
Packit Service 1d0348
  return lzss->mask;
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static inline int
Packit Service 1d0348
lzss_size(struct lzss *lzss)
Packit Service 1d0348
{
Packit Service 1d0348
  return lzss->mask + 1;
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static inline int
Packit Service 1d0348
lzss_offset_for_position(struct lzss *lzss, int64_t pos)
Packit Service 1d0348
{
Packit Service 1d0348
  return (int)(pos & lzss->mask);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static inline unsigned char *
Packit Service 1d0348
lzss_pointer_for_position(struct lzss *lzss, int64_t pos)
Packit Service 1d0348
{
Packit Service 1d0348
  return &lzss->window[lzss_offset_for_position(lzss, pos)];
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static inline int
Packit Service 1d0348
lzss_current_offset(struct lzss *lzss)
Packit Service 1d0348
{
Packit Service 1d0348
  return lzss_offset_for_position(lzss, lzss->position);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static inline uint8_t *
Packit Service 1d0348
lzss_current_pointer(struct lzss *lzss)
Packit Service 1d0348
{
Packit Service 1d0348
  return lzss_pointer_for_position(lzss, lzss->position);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static inline void
Packit Service 1d0348
lzss_emit_literal(struct rar *rar, uint8_t literal)
Packit Service 1d0348
{
Packit Service 1d0348
  *lzss_current_pointer(&rar->lzss) = literal;
Packit Service 1d0348
  rar->lzss.position++;
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static inline void
Packit Service 1d0348
lzss_emit_match(struct rar *rar, int offset, int length)
Packit Service 1d0348
{
Packit Service 1d0348
  int dstoffs = lzss_current_offset(&rar->lzss);
Packit Service 1d0348
  int srcoffs = (dstoffs - offset) & lzss_mask(&rar->lzss);
Packit Service 1d0348
  int l, li, remaining;
Packit Service 1d0348
  unsigned char *d, *s;
Packit Service 1d0348
Packit Service 1d0348
  remaining = length;
Packit Service 1d0348
  while (remaining > 0) {
Packit Service 1d0348
    l = remaining;
Packit Service 1d0348
    if (dstoffs > srcoffs) {
Packit Service 1d0348
      if (l > lzss_size(&rar->lzss) - dstoffs)
Packit Service 1d0348
        l = lzss_size(&rar->lzss) - dstoffs;
Packit Service 1d0348
    } else {
Packit Service 1d0348
      if (l > lzss_size(&rar->lzss) - srcoffs)
Packit Service 1d0348
        l = lzss_size(&rar->lzss) - srcoffs;
Packit Service 1d0348
    }
Packit Service 1d0348
    d = &(rar->lzss.window[dstoffs]);
Packit Service 1d0348
    s = &(rar->lzss.window[srcoffs]);
Packit Service 1d0348
    if ((dstoffs + l < srcoffs) || (srcoffs + l < dstoffs))
Packit Service 1d0348
      memcpy(d, s, l);
Packit Service 1d0348
    else {
Packit Service 1d0348
      for (li = 0; li < l; li++)
Packit Service 1d0348
        d[li] = s[li];
Packit Service 1d0348
    }
Packit Service 1d0348
    remaining -= l;
Packit Service 1d0348
    dstoffs = (dstoffs + l) & lzss_mask(&(rar->lzss));
Packit Service 1d0348
    srcoffs = (srcoffs + l) & lzss_mask(&(rar->lzss));
Packit Service 1d0348
  }
Packit Service 1d0348
  rar->lzss.position += length;
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static Byte
Packit Service 1d0348
ppmd_read(void *p)
Packit Service 1d0348
{
Packit Service 1d0348
  struct archive_read *a = ((IByteIn*)p)->a;
Packit Service 1d0348
  struct rar *rar = (struct rar *)(a->format->data);
Packit Service 1d0348
  struct rar_br *br = &(rar->br);
Packit Service 1d0348
  Byte b;
Packit Service 1d0348
  if (!rar_br_read_ahead(a, br, 8))
Packit Service 1d0348
  {
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                      "Truncated RAR file data");
Packit Service 1d0348
    rar->valid = 0;
Packit Service 1d0348
    return 0;
Packit Service 1d0348
  }
Packit Service 1d0348
  b = rar_br_bits(br, 8);
Packit Service 1d0348
  rar_br_consume(br, 8);
Packit Service 1d0348
  return b;
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
int
Packit Service 1d0348
archive_read_support_format_rar(struct archive *_a)
Packit Service 1d0348
{
Packit Service 1d0348
  struct archive_read *a = (struct archive_read *)_a;
Packit Service 1d0348
  struct rar *rar;
Packit Service 1d0348
  int r;
Packit Service 1d0348
Packit Service 1d0348
  archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW,
Packit Service 1d0348
                      "archive_read_support_format_rar");
Packit Service 1d0348
Packit Service 1d0348
  rar = (struct rar *)calloc(sizeof(*rar), 1);
Packit Service 1d0348
  if (rar == NULL)
Packit Service 1d0348
  {
Packit Service 1d0348
    archive_set_error(&a->archive, ENOMEM, "Can't allocate rar data");
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Until enough data has been read, we cannot tell about
Packit Service 1d0348
	 * any encrypted entries yet.
Packit Service 1d0348
	 */
Packit Service 1d0348
	rar->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
Packit Service 1d0348
Packit Service 1d0348
  r = __archive_read_register_format(a,
Packit Service 1d0348
                                     rar,
Packit Service 1d0348
                                     "rar",
Packit Service 1d0348
                                     archive_read_format_rar_bid,
Packit Service 1d0348
                                     archive_read_format_rar_options,
Packit Service 1d0348
                                     archive_read_format_rar_read_header,
Packit Service 1d0348
                                     archive_read_format_rar_read_data,
Packit Service 1d0348
                                     archive_read_format_rar_read_data_skip,
Packit Service 1d0348
                                     archive_read_format_rar_seek_data,
Packit Service 1d0348
                                     archive_read_format_rar_cleanup,
Packit Service 1d0348
                                     archive_read_support_format_rar_capabilities,
Packit Service 1d0348
                                     archive_read_format_rar_has_encrypted_entries);
Packit Service 1d0348
Packit Service 1d0348
  if (r != ARCHIVE_OK)
Packit Service 1d0348
    free(rar);
Packit Service 1d0348
  return (r);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
archive_read_support_format_rar_capabilities(struct archive_read * a)
Packit Service 1d0348
{
Packit Service 1d0348
	(void)a; /* UNUSED */
Packit Service 1d0348
	return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA
Packit Service 1d0348
			| ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
archive_read_format_rar_has_encrypted_entries(struct archive_read *_a)
Packit Service 1d0348
{
Packit Service 1d0348
	if (_a && _a->format) {
Packit Service 1d0348
		struct rar * rar = (struct rar *)_a->format->data;
Packit Service 1d0348
		if (rar) {
Packit Service 1d0348
			return rar->has_encrypted_entries;
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
	return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
archive_read_format_rar_bid(struct archive_read *a, int best_bid)
Packit Service 1d0348
{
Packit Service 1d0348
  const char *p;
Packit Service 1d0348
Packit Service 1d0348
  /* If there's already a bid > 30, we'll never win. */
Packit Service 1d0348
  if (best_bid > 30)
Packit Service 1d0348
	  return (-1);
Packit Service 1d0348
Packit Service 1d0348
  if ((p = __archive_read_ahead(a, 7, NULL)) == NULL)
Packit Service 1d0348
    return (-1);
Packit Service 1d0348
Packit Service 1d0348
  if (memcmp(p, RAR_SIGNATURE, 7) == 0)
Packit Service 1d0348
    return (30);
Packit Service 1d0348
Packit Service 1d0348
  if ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0) {
Packit Service 1d0348
    /* This is a PE file */
Packit Service 1d0348
    ssize_t offset = 0x10000;
Packit Service 1d0348
    ssize_t window = 4096;
Packit Service 1d0348
    ssize_t bytes_avail;
Packit Service 1d0348
    while (offset + window <= (1024 * 128)) {
Packit Service 1d0348
      const char *buff = __archive_read_ahead(a, offset + window, &bytes_avail);
Packit Service 1d0348
      if (buff == NULL) {
Packit Service 1d0348
        /* Remaining bytes are less than window. */
Packit Service 1d0348
        window >>= 1;
Packit Service 1d0348
        if (window < 0x40)
Packit Service 1d0348
          return (0);
Packit Service 1d0348
        continue;
Packit Service 1d0348
      }
Packit Service 1d0348
      p = buff + offset;
Packit Service 1d0348
      while (p + 7 < buff + bytes_avail) {
Packit Service 1d0348
        if (memcmp(p, RAR_SIGNATURE, 7) == 0)
Packit Service 1d0348
          return (30);
Packit Service 1d0348
        p += 0x10;
Packit Service 1d0348
      }
Packit Service 1d0348
      offset = p - buff;
Packit Service 1d0348
    }
Packit Service 1d0348
  }
Packit Service 1d0348
  return (0);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
skip_sfx(struct archive_read *a)
Packit Service 1d0348
{
Packit Service 1d0348
  const void *h;
Packit Service 1d0348
  const char *p, *q;
Packit Service 1d0348
  size_t skip, total;
Packit Service 1d0348
  ssize_t bytes, window;
Packit Service 1d0348
Packit Service 1d0348
  total = 0;
Packit Service 1d0348
  window = 4096;
Packit Service 1d0348
  while (total + window <= (1024 * 128)) {
Packit Service 1d0348
    h = __archive_read_ahead(a, window, &bytes);
Packit Service 1d0348
    if (h == NULL) {
Packit Service 1d0348
      /* Remaining bytes are less than window. */
Packit Service 1d0348
      window >>= 1;
Packit Service 1d0348
      if (window < 0x40)
Packit Service 1d0348
      	goto fatal;
Packit Service 1d0348
      continue;
Packit Service 1d0348
    }
Packit Service 1d0348
    if (bytes < 0x40)
Packit Service 1d0348
      goto fatal;
Packit Service 1d0348
    p = h;
Packit Service 1d0348
    q = p + bytes;
Packit Service 1d0348
Packit Service 1d0348
    /*
Packit Service 1d0348
     * Scan ahead until we find something that looks
Packit Service 1d0348
     * like the RAR header.
Packit Service 1d0348
     */
Packit Service 1d0348
    while (p + 7 < q) {
Packit Service 1d0348
      if (memcmp(p, RAR_SIGNATURE, 7) == 0) {
Packit Service 1d0348
      	skip = p - (const char *)h;
Packit Service 1d0348
      	__archive_read_consume(a, skip);
Packit Service 1d0348
      	return (ARCHIVE_OK);
Packit Service 1d0348
      }
Packit Service 1d0348
      p += 0x10;
Packit Service 1d0348
    }
Packit Service 1d0348
    skip = p - (const char *)h;
Packit Service 1d0348
    __archive_read_consume(a, skip);
Packit Service 1d0348
	total += skip;
Packit Service 1d0348
  }
Packit Service 1d0348
fatal:
Packit Service 1d0348
  archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
      "Couldn't find out RAR header");
Packit Service 1d0348
  return (ARCHIVE_FATAL);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
archive_read_format_rar_options(struct archive_read *a,
Packit Service 1d0348
    const char *key, const char *val)
Packit Service 1d0348
{
Packit Service 1d0348
  struct rar *rar;
Packit Service 1d0348
  int ret = ARCHIVE_FAILED;
Packit Service 1d0348
Packit Service 1d0348
  rar = (struct rar *)(a->format->data);
Packit Service 1d0348
  if (strcmp(key, "hdrcharset")  == 0) {
Packit Service 1d0348
    if (val == NULL || val[0] == 0)
Packit Service 1d0348
      archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
          "rar: hdrcharset option needs a character-set name");
Packit Service 1d0348
    else {
Packit Service 1d0348
      rar->opt_sconv =
Packit Service 1d0348
          archive_string_conversion_from_charset(
Packit Service 1d0348
              &a->archive, val, 0);
Packit Service 1d0348
      if (rar->opt_sconv != NULL)
Packit Service 1d0348
        ret = ARCHIVE_OK;
Packit Service 1d0348
      else
Packit Service 1d0348
        ret = ARCHIVE_FATAL;
Packit Service 1d0348
    }
Packit Service 1d0348
    return (ret);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  /* Note: The "warn" return is just to inform the options
Packit Service 1d0348
   * supervisor that we didn't handle it.  It will generate
Packit Service 1d0348
   * a suitable error if no one used this option. */
Packit Service 1d0348
  return (ARCHIVE_WARN);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
archive_read_format_rar_read_header(struct archive_read *a,
Packit Service 1d0348
                                    struct archive_entry *entry)
Packit Service 1d0348
{
Packit Service 1d0348
  const void *h;
Packit Service 1d0348
  const char *p;
Packit Service 1d0348
  struct rar *rar;
Packit Service 1d0348
  size_t skip;
Packit Service 1d0348
  char head_type;
Packit Service 1d0348
  int ret;
Packit Service 1d0348
  unsigned flags;
Packit Service 1d0348
  unsigned long crc32_expected;
Packit Service 1d0348
Packit Service 1d0348
  a->archive.archive_format = ARCHIVE_FORMAT_RAR;
Packit Service 1d0348
  if (a->archive.archive_format_name == NULL)
Packit Service 1d0348
    a->archive.archive_format_name = "RAR";
Packit Service 1d0348
Packit Service 1d0348
  rar = (struct rar *)(a->format->data);
Packit Service 1d0348
Packit Service 1d0348
  /*
Packit Service 1d0348
   * It should be sufficient to call archive_read_next_header() for
Packit Service 1d0348
   * a reader to determine if an entry is encrypted or not. If the
Packit Service 1d0348
   * encryption of an entry is only detectable when calling
Packit Service 1d0348
   * archive_read_data(), so be it. We'll do the same check there
Packit Service 1d0348
   * as well.
Packit Service 1d0348
   */
Packit Service 1d0348
  if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
Packit Service 1d0348
	  rar->has_encrypted_entries = 0;
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  /* RAR files can be generated without EOF headers, so return ARCHIVE_EOF if
Packit Service 1d0348
  * this fails.
Packit Service 1d0348
  */
Packit Service 1d0348
  if ((h = __archive_read_ahead(a, 7, NULL)) == NULL)
Packit Service 1d0348
    return (ARCHIVE_EOF);
Packit Service 1d0348
Packit Service 1d0348
  p = h;
Packit Service 1d0348
  if (rar->found_first_header == 0 &&
Packit Service 1d0348
     ((p[0] == 'M' && p[1] == 'Z') || memcmp(p, "\x7F\x45LF", 4) == 0)) {
Packit Service 1d0348
    /* This is an executable ? Must be self-extracting... */
Packit Service 1d0348
    ret = skip_sfx(a);
Packit Service 1d0348
    if (ret < ARCHIVE_WARN)
Packit Service 1d0348
      return (ret);
Packit Service 1d0348
  }
Packit Service 1d0348
  rar->found_first_header = 1;
Packit Service 1d0348
Packit Service 1d0348
  while (1)
Packit Service 1d0348
  {
Packit Service 1d0348
    unsigned long crc32_val;
Packit Service 1d0348
Packit Service 1d0348
    if ((h = __archive_read_ahead(a, 7, NULL)) == NULL)
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
    p = h;
Packit Service 1d0348
Packit Service 1d0348
    head_type = p[2];
Packit Service 1d0348
    switch(head_type)
Packit Service 1d0348
    {
Packit Service 1d0348
    case MARK_HEAD:
Packit Service 1d0348
      if (memcmp(p, RAR_SIGNATURE, 7) != 0) {
Packit Service 1d0348
        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
          "Invalid marker header");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      __archive_read_consume(a, 7);
Packit Service 1d0348
      break;
Packit Service 1d0348
Packit Service 1d0348
    case MAIN_HEAD:
Packit Service 1d0348
      rar->main_flags = archive_le16dec(p + 3);
Packit Service 1d0348
      skip = archive_le16dec(p + 5);
Packit Service 1d0348
      if (skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)) {
Packit Service 1d0348
        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
          "Invalid header size");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      if ((h = __archive_read_ahead(a, skip, NULL)) == NULL)
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      p = h;
Packit Service 1d0348
      memcpy(rar->reserved1, p + 7, sizeof(rar->reserved1));
Packit Service 1d0348
      memcpy(rar->reserved2, p + 7 + sizeof(rar->reserved1),
Packit Service 1d0348
             sizeof(rar->reserved2));
Packit Service 1d0348
      if (rar->main_flags & MHD_ENCRYPTVER) {
Packit Service 1d0348
        if (skip < 7 + sizeof(rar->reserved1) + sizeof(rar->reserved2)+1) {
Packit Service 1d0348
          archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
            "Invalid header size");
Packit Service 1d0348
          return (ARCHIVE_FATAL);
Packit Service 1d0348
        }
Packit Service 1d0348
        rar->encryptver = *(p + 7 + sizeof(rar->reserved1) +
Packit Service 1d0348
                            sizeof(rar->reserved2));
Packit Service 1d0348
      }
Packit Service 1d0348
Packit Service 1d0348
      /* Main header is password encrypted, so we cannot read any
Packit Service 1d0348
         file names or any other info about files from the header. */
Packit Service 1d0348
      if (rar->main_flags & MHD_PASSWORD)
Packit Service 1d0348
      {
Packit Service 1d0348
        archive_entry_set_is_metadata_encrypted(entry, 1);
Packit Service 1d0348
        archive_entry_set_is_data_encrypted(entry, 1);
Packit Service 1d0348
        rar->has_encrypted_entries = 1;
Packit Service 1d0348
         archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                          "RAR encryption support unavailable.");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
Packit Service 1d0348
      crc32_val = crc32(0, (const unsigned char *)p + 2, (unsigned)skip - 2);
Packit Service 1d0348
      if ((crc32_val & 0xffff) != archive_le16dec(p)) {
Packit Service 1d0348
        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
          "Header CRC error");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      __archive_read_consume(a, skip);
Packit Service 1d0348
      break;
Packit Service 1d0348
Packit Service 1d0348
    case FILE_HEAD:
Packit Service 1d0348
      return read_header(a, entry, head_type);
Packit Service 1d0348
Packit Service 1d0348
    case COMM_HEAD:
Packit Service 1d0348
    case AV_HEAD:
Packit Service 1d0348
    case SUB_HEAD:
Packit Service 1d0348
    case PROTECT_HEAD:
Packit Service 1d0348
    case SIGN_HEAD:
Packit Service 1d0348
    case ENDARC_HEAD:
Packit Service 1d0348
      flags = archive_le16dec(p + 3);
Packit Service 1d0348
      skip = archive_le16dec(p + 5);
Packit Service 1d0348
      if (skip < 7) {
Packit Service 1d0348
        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
          "Invalid header size too small");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      if (flags & HD_ADD_SIZE_PRESENT)
Packit Service 1d0348
      {
Packit Service 1d0348
        if (skip < 7 + 4) {
Packit Service 1d0348
          archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
            "Invalid header size too small");
Packit Service 1d0348
          return (ARCHIVE_FATAL);
Packit Service 1d0348
        }
Packit Service 1d0348
        if ((h = __archive_read_ahead(a, skip, NULL)) == NULL)
Packit Service 1d0348
          return (ARCHIVE_FATAL);
Packit Service 1d0348
        p = h;
Packit Service 1d0348
        skip += archive_le32dec(p + 7);
Packit Service 1d0348
      }
Packit Service 1d0348
Packit Service 1d0348
      /* Skip over the 2-byte CRC at the beginning of the header. */
Packit Service 1d0348
      crc32_expected = archive_le16dec(p);
Packit Service 1d0348
      __archive_read_consume(a, 2);
Packit Service 1d0348
      skip -= 2;
Packit Service 1d0348
Packit Service 1d0348
      /* Skim the entire header and compute the CRC. */
Packit Service 1d0348
      crc32_val = 0;
Packit Service 1d0348
      while (skip > 0) {
Packit Service 1d0348
	      size_t to_read = skip;
Packit Service 1d0348
	      ssize_t did_read;
Packit Service 1d0348
	      if (to_read > 32 * 1024) {
Packit Service 1d0348
		      to_read = 32 * 1024;
Packit Service 1d0348
	      }
Packit Service 1d0348
	      if ((h = __archive_read_ahead(a, to_read, &did_read)) == NULL) {
Packit Service 1d0348
		      return (ARCHIVE_FATAL);
Packit Service 1d0348
	      }
Packit Service 1d0348
	      p = h;
Packit Service 1d0348
	      crc32_val = crc32(crc32_val, (const unsigned char *)p, (unsigned)did_read);
Packit Service 1d0348
	      __archive_read_consume(a, did_read);
Packit Service 1d0348
	      skip -= did_read;
Packit Service 1d0348
      }
Packit Service 1d0348
      if ((crc32_val & 0xffff) != crc32_expected) {
Packit Service 1d0348
	      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
		  "Header CRC error");
Packit Service 1d0348
	      return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      if (head_type == ENDARC_HEAD)
Packit Service 1d0348
	      return (ARCHIVE_EOF);
Packit Service 1d0348
      break;
Packit Service 1d0348
Packit Service 1d0348
    case NEWSUB_HEAD:
Packit Service 1d0348
      if ((ret = read_header(a, entry, head_type)) < ARCHIVE_WARN)
Packit Service 1d0348
        return ret;
Packit Service 1d0348
      break;
Packit Service 1d0348
Packit Service 1d0348
    default:
Packit Service 1d0348
      archive_set_error(&a->archive,  ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                        "Bad RAR file");
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
    }
Packit Service 1d0348
  }
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
Packit Service 1d0348
                                  size_t *size, int64_t *offset)
Packit Service 1d0348
{
Packit Service 1d0348
  struct rar *rar = (struct rar *)(a->format->data);
Packit Service 1d0348
  int ret;
Packit Service 1d0348
Packit Service 1d0348
  if (rar->has_encrypted_entries == ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
Packit Service 1d0348
	  rar->has_encrypted_entries = 0;
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  if (rar->bytes_unconsumed > 0) {
Packit Service 1d0348
      /* Consume as much as the decompressor actually used. */
Packit Service 1d0348
      __archive_read_consume(a, rar->bytes_unconsumed);
Packit Service 1d0348
      rar->bytes_unconsumed = 0;
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  *buff = NULL;
Packit Service 1d0348
  if (rar->entry_eof || rar->offset_seek >= rar->unp_size) {
Packit Service 1d0348
    *size = 0;
Packit Service 1d0348
    *offset = rar->offset;
Packit Service 1d0348
    if (*offset < rar->unp_size)
Packit Service 1d0348
      *offset = rar->unp_size;
Packit Service 1d0348
    return (ARCHIVE_EOF);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  switch (rar->compression_method)
Packit Service 1d0348
  {
Packit Service 1d0348
  case COMPRESS_METHOD_STORE:
Packit Service 1d0348
    ret = read_data_stored(a, buff, size, offset);
Packit Service 1d0348
    break;
Packit Service 1d0348
Packit Service 1d0348
  case COMPRESS_METHOD_FASTEST:
Packit Service 1d0348
  case COMPRESS_METHOD_FAST:
Packit Service 1d0348
  case COMPRESS_METHOD_NORMAL:
Packit Service 1d0348
  case COMPRESS_METHOD_GOOD:
Packit Service 1d0348
  case COMPRESS_METHOD_BEST:
Packit Service 1d0348
    ret = read_data_compressed(a, buff, size, offset);
Packit Service 1d0348
    if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN)
Packit Service 1d0348
      __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
Packit Service 1d0348
    break;
Packit Service 1d0348
Packit Service 1d0348
  default:
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                      "Unsupported compression method for RAR file.");
Packit Service 1d0348
    ret = ARCHIVE_FATAL;
Packit Service 1d0348
    break;
Packit Service 1d0348
  }
Packit Service 1d0348
  return (ret);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
archive_read_format_rar_read_data_skip(struct archive_read *a)
Packit Service 1d0348
{
Packit Service 1d0348
  struct rar *rar;
Packit Service 1d0348
  int64_t bytes_skipped;
Packit Service 1d0348
  int ret;
Packit Service 1d0348
Packit Service 1d0348
  rar = (struct rar *)(a->format->data);
Packit Service 1d0348
Packit Service 1d0348
  if (rar->bytes_unconsumed > 0) {
Packit Service 1d0348
      /* Consume as much as the decompressor actually used. */
Packit Service 1d0348
      __archive_read_consume(a, rar->bytes_unconsumed);
Packit Service 1d0348
      rar->bytes_unconsumed = 0;
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  if (rar->bytes_remaining > 0) {
Packit Service 1d0348
    bytes_skipped = __archive_read_consume(a, rar->bytes_remaining);
Packit Service 1d0348
    if (bytes_skipped < 0)
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  /* Compressed data to skip must be read from each header in a multivolume
Packit Service 1d0348
   * archive.
Packit Service 1d0348
   */
Packit Service 1d0348
  if (rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER)
Packit Service 1d0348
  {
Packit Service 1d0348
    ret = archive_read_format_rar_read_header(a, a->entry);
Packit Service 1d0348
    if (ret == (ARCHIVE_EOF))
Packit Service 1d0348
      ret = archive_read_format_rar_read_header(a, a->entry);
Packit Service 1d0348
    if (ret != (ARCHIVE_OK))
Packit Service 1d0348
      return ret;
Packit Service 1d0348
    return archive_read_format_rar_read_data_skip(a);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int64_t
Packit Service 1d0348
archive_read_format_rar_seek_data(struct archive_read *a, int64_t offset,
Packit Service 1d0348
    int whence)
Packit Service 1d0348
{
Packit Service 1d0348
  int64_t client_offset, ret;
Packit Service 1d0348
  unsigned int i;
Packit Service 1d0348
  struct rar *rar = (struct rar *)(a->format->data);
Packit Service 1d0348
Packit Service 1d0348
  if (rar->compression_method == COMPRESS_METHOD_STORE)
Packit Service 1d0348
  {
Packit Service 1d0348
    /* Modify the offset for use with SEEK_SET */
Packit Service 1d0348
    switch (whence)
Packit Service 1d0348
    {
Packit Service 1d0348
      case SEEK_CUR:
Packit Service 1d0348
        client_offset = rar->offset_seek;
Packit Service 1d0348
        break;
Packit Service 1d0348
      case SEEK_END:
Packit Service 1d0348
        client_offset = rar->unp_size;
Packit Service 1d0348
        break;
Packit Service 1d0348
      case SEEK_SET:
Packit Service 1d0348
      default:
Packit Service 1d0348
        client_offset = 0;
Packit Service 1d0348
    }
Packit Service 1d0348
    client_offset += offset;
Packit Service 1d0348
    if (client_offset < 0)
Packit Service 1d0348
    {
Packit Service 1d0348
      /* Can't seek past beginning of data block */
Packit Service 1d0348
      return -1;
Packit Service 1d0348
    }
Packit Service 1d0348
    else if (client_offset > rar->unp_size)
Packit Service 1d0348
    {
Packit Service 1d0348
      /*
Packit Service 1d0348
       * Set the returned offset but only seek to the end of
Packit Service 1d0348
       * the data block.
Packit Service 1d0348
       */
Packit Service 1d0348
      rar->offset_seek = client_offset;
Packit Service 1d0348
      client_offset = rar->unp_size;
Packit Service 1d0348
    }
Packit Service 1d0348
Packit Service 1d0348
    client_offset += rar->dbo[0].start_offset;
Packit Service 1d0348
    i = 0;
Packit Service 1d0348
    while (i < rar->cursor)
Packit Service 1d0348
    {
Packit Service 1d0348
      i++;
Packit Service 1d0348
      client_offset += rar->dbo[i].start_offset - rar->dbo[i-1].end_offset;
Packit Service 1d0348
    }
Packit Service 1d0348
    if (rar->main_flags & MHD_VOLUME)
Packit Service 1d0348
    {
Packit Service 1d0348
      /* Find the appropriate offset among the multivolume archive */
Packit Service 1d0348
      while (1)
Packit Service 1d0348
      {
Packit Service 1d0348
        if (client_offset < rar->dbo[rar->cursor].start_offset &&
Packit Service 1d0348
          rar->file_flags & FHD_SPLIT_BEFORE)
Packit Service 1d0348
        {
Packit Service 1d0348
          /* Search backwards for the correct data block */
Packit Service 1d0348
          if (rar->cursor == 0)
Packit Service 1d0348
          {
Packit Service 1d0348
            archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
              "Attempt to seek past beginning of RAR data block");
Packit Service 1d0348
            return (ARCHIVE_FAILED);
Packit Service 1d0348
          }
Packit Service 1d0348
          rar->cursor--;
Packit Service 1d0348
          client_offset -= rar->dbo[rar->cursor+1].start_offset -
Packit Service 1d0348
            rar->dbo[rar->cursor].end_offset;
Packit Service 1d0348
          if (client_offset < rar->dbo[rar->cursor].start_offset)
Packit Service 1d0348
            continue;
Packit Service 1d0348
          ret = __archive_read_seek(a, rar->dbo[rar->cursor].start_offset -
Packit Service 1d0348
            rar->dbo[rar->cursor].header_size, SEEK_SET);
Packit Service 1d0348
          if (ret < (ARCHIVE_OK))
Packit Service 1d0348
            return ret;
Packit Service 1d0348
          ret = archive_read_format_rar_read_header(a, a->entry);
Packit Service 1d0348
          if (ret != (ARCHIVE_OK))
Packit Service 1d0348
          {
Packit Service 1d0348
            archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
              "Error during seek of RAR file");
Packit Service 1d0348
            return (ARCHIVE_FAILED);
Packit Service 1d0348
          }
Packit Service 1d0348
          rar->cursor--;
Packit Service 1d0348
          break;
Packit Service 1d0348
        }
Packit Service 1d0348
        else if (client_offset > rar->dbo[rar->cursor].end_offset &&
Packit Service 1d0348
          rar->file_flags & FHD_SPLIT_AFTER)
Packit Service 1d0348
        {
Packit Service 1d0348
          /* Search forward for the correct data block */
Packit Service 1d0348
          rar->cursor++;
Packit Service 1d0348
          if (rar->cursor < rar->nodes &&
Packit Service 1d0348
            client_offset > rar->dbo[rar->cursor].end_offset)
Packit Service 1d0348
          {
Packit Service 1d0348
            client_offset += rar->dbo[rar->cursor].start_offset -
Packit Service 1d0348
              rar->dbo[rar->cursor-1].end_offset;
Packit Service 1d0348
            continue;
Packit Service 1d0348
          }
Packit Service 1d0348
          rar->cursor--;
Packit Service 1d0348
          ret = __archive_read_seek(a, rar->dbo[rar->cursor].end_offset,
Packit Service 1d0348
                                    SEEK_SET);
Packit Service 1d0348
          if (ret < (ARCHIVE_OK))
Packit Service 1d0348
            return ret;
Packit Service 1d0348
          ret = archive_read_format_rar_read_header(a, a->entry);
Packit Service 1d0348
          if (ret == (ARCHIVE_EOF))
Packit Service 1d0348
          {
Packit Service 1d0348
            rar->has_endarc_header = 1;
Packit Service 1d0348
            ret = archive_read_format_rar_read_header(a, a->entry);
Packit Service 1d0348
          }
Packit Service 1d0348
          if (ret != (ARCHIVE_OK))
Packit Service 1d0348
          {
Packit Service 1d0348
            archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
              "Error during seek of RAR file");
Packit Service 1d0348
            return (ARCHIVE_FAILED);
Packit Service 1d0348
          }
Packit Service 1d0348
          client_offset += rar->dbo[rar->cursor].start_offset -
Packit Service 1d0348
            rar->dbo[rar->cursor-1].end_offset;
Packit Service 1d0348
          continue;
Packit Service 1d0348
        }
Packit Service 1d0348
        break;
Packit Service 1d0348
      }
Packit Service 1d0348
    }
Packit Service 1d0348
Packit Service 1d0348
    ret = __archive_read_seek(a, client_offset, SEEK_SET);
Packit Service 1d0348
    if (ret < (ARCHIVE_OK))
Packit Service 1d0348
      return ret;
Packit Service 1d0348
    rar->bytes_remaining = rar->dbo[rar->cursor].end_offset - ret;
Packit Service 1d0348
    i = rar->cursor;
Packit Service 1d0348
    while (i > 0)
Packit Service 1d0348
    {
Packit Service 1d0348
      i--;
Packit Service 1d0348
      ret -= rar->dbo[i+1].start_offset - rar->dbo[i].end_offset;
Packit Service 1d0348
    }
Packit Service 1d0348
    ret -= rar->dbo[0].start_offset;
Packit Service 1d0348
Packit Service 1d0348
    /* Always restart reading the file after a seek */
Packit Service 1d0348
    __archive_reset_read_data(&a->archive);
Packit Service 1d0348
Packit Service 1d0348
    rar->bytes_unconsumed = 0;
Packit Service 1d0348
    rar->offset = 0;
Packit Service 1d0348
Packit Service 1d0348
    /*
Packit Service 1d0348
     * If a seek past the end of file was requested, return the requested
Packit Service 1d0348
     * offset.
Packit Service 1d0348
     */
Packit Service 1d0348
    if (ret == rar->unp_size && rar->offset_seek > rar->unp_size)
Packit Service 1d0348
      return rar->offset_seek;
Packit Service 1d0348
Packit Service 1d0348
    /* Return the new offset */
Packit Service 1d0348
    rar->offset_seek = ret;
Packit Service 1d0348
    return rar->offset_seek;
Packit Service 1d0348
  }
Packit Service 1d0348
  else
Packit Service 1d0348
  {
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
      "Seeking of compressed RAR files is unsupported");
Packit Service 1d0348
  }
Packit Service 1d0348
  return (ARCHIVE_FAILED);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
archive_read_format_rar_cleanup(struct archive_read *a)
Packit Service 1d0348
{
Packit Service 1d0348
  struct rar *rar;
Packit Service 1d0348
Packit Service 1d0348
  rar = (struct rar *)(a->format->data);
Packit Service 1d0348
  free_codes(a);
Packit Service 1d0348
  free(rar->filename);
Packit Service 1d0348
  free(rar->filename_save);
Packit Service 1d0348
  free(rar->dbo);
Packit Service 1d0348
  free(rar->unp_buffer);
Packit Service 1d0348
  free(rar->lzss.window);
Packit Service 1d0348
  __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
Packit Service 1d0348
  free(rar);
Packit Service 1d0348
  (a->format->data) = NULL;
Packit Service 1d0348
  return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
read_header(struct archive_read *a, struct archive_entry *entry,
Packit Service 1d0348
            char head_type)
Packit Service 1d0348
{
Packit Service 1d0348
  const void *h;
Packit Service 1d0348
  const char *p, *endp;
Packit Service 1d0348
  struct rar *rar;
Packit Service 1d0348
  struct rar_header rar_header;
Packit Service 1d0348
  struct rar_file_header file_header;
Packit Service 1d0348
  int64_t header_size;
Packit Service 1d0348
  unsigned filename_size, end;
Packit Service 1d0348
  char *filename;
Packit Service 1d0348
  char *strp;
Packit Service 1d0348
  char packed_size[8];
Packit Service 1d0348
  char unp_size[8];
Packit Service 1d0348
  int ttime;
Packit Service 1d0348
  struct archive_string_conv *sconv, *fn_sconv;
Packit Service 1d0348
  unsigned long crc32_val;
Packit Service 1d0348
  int ret = (ARCHIVE_OK), ret2;
Packit Service 1d0348
Packit Service 1d0348
  rar = (struct rar *)(a->format->data);
Packit Service 1d0348
Packit Service 1d0348
  /* Setup a string conversion object for non-rar-unicode filenames. */
Packit Service 1d0348
  sconv = rar->opt_sconv;
Packit Service 1d0348
  if (sconv == NULL) {
Packit Service 1d0348
    if (!rar->init_default_conversion) {
Packit Service 1d0348
      rar->sconv_default =
Packit Service 1d0348
          archive_string_default_conversion_for_read(
Packit Service 1d0348
            &(a->archive));
Packit Service 1d0348
      rar->init_default_conversion = 1;
Packit Service 1d0348
    }
Packit Service 1d0348
    sconv = rar->sconv_default;
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
Packit Service 1d0348
  if ((h = __archive_read_ahead(a, 7, NULL)) == NULL)
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  p = h;
Packit Service 1d0348
  memcpy(&rar_header, p, sizeof(rar_header));
Packit Service 1d0348
  rar->file_flags = archive_le16dec(rar_header.flags);
Packit Service 1d0348
  header_size = archive_le16dec(rar_header.size);
Packit Service 1d0348
  if (header_size < (int64_t)sizeof(file_header) + 7) {
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
      "Invalid header size");
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
  crc32_val = crc32(0, (const unsigned char *)p + 2, 7 - 2);
Packit Service 1d0348
  __archive_read_consume(a, 7);
Packit Service 1d0348
Packit Service 1d0348
  if (!(rar->file_flags & FHD_SOLID))
Packit Service 1d0348
  {
Packit Service 1d0348
    rar->compression_method = 0;
Packit Service 1d0348
    rar->packed_size = 0;
Packit Service 1d0348
    rar->unp_size = 0;
Packit Service 1d0348
    rar->mtime = 0;
Packit Service 1d0348
    rar->ctime = 0;
Packit Service 1d0348
    rar->atime = 0;
Packit Service 1d0348
    rar->arctime = 0;
Packit Service 1d0348
    rar->mode = 0;
Packit Service 1d0348
    memset(&rar->salt, 0, sizeof(rar->salt));
Packit Service 1d0348
    rar->atime = 0;
Packit Service 1d0348
    rar->ansec = 0;
Packit Service 1d0348
    rar->ctime = 0;
Packit Service 1d0348
    rar->cnsec = 0;
Packit Service 1d0348
    rar->mtime = 0;
Packit Service 1d0348
    rar->mnsec = 0;
Packit Service 1d0348
    rar->arctime = 0;
Packit Service 1d0348
    rar->arcnsec = 0;
Packit Service 1d0348
  }
Packit Service 1d0348
  else
Packit Service 1d0348
  {
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                      "RAR solid archive support unavailable.");
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
Packit Service 1d0348
  /* File Header CRC check. */
Packit Service 1d0348
  crc32_val = crc32(crc32_val, h, (unsigned)(header_size - 7));
Packit Service 1d0348
  if ((crc32_val & 0xffff) != archive_le16dec(rar_header.crc)) {
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
      "Header CRC error");
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
  /* If no CRC error, Go on parsing File Header. */
Packit Service 1d0348
  p = h;
Packit Service 1d0348
  endp = p + header_size - 7;
Packit Service 1d0348
  memcpy(&file_header, p, sizeof(file_header));
Packit Service 1d0348
  p += sizeof(file_header);
Packit Service 1d0348
Packit Service 1d0348
  rar->compression_method = file_header.method;
Packit Service 1d0348
Packit Service 1d0348
  ttime = archive_le32dec(file_header.file_time);
Packit Service 1d0348
  rar->mtime = get_time(ttime);
Packit Service 1d0348
Packit Service 1d0348
  rar->file_crc = archive_le32dec(file_header.file_crc);
Packit Service 1d0348
Packit Service 1d0348
  if (rar->file_flags & FHD_PASSWORD)
Packit Service 1d0348
  {
Packit Service 1d0348
	archive_entry_set_is_data_encrypted(entry, 1);
Packit Service 1d0348
	rar->has_encrypted_entries = 1;
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                      "RAR encryption support unavailable.");
Packit Service 1d0348
    /* Since it is only the data part itself that is encrypted we can at least
Packit Service 1d0348
       extract information about the currently processed entry and don't need
Packit Service 1d0348
       to return ARCHIVE_FATAL here. */
Packit Service 1d0348
    /*return (ARCHIVE_FATAL);*/
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  if (rar->file_flags & FHD_LARGE)
Packit Service 1d0348
  {
Packit Service 1d0348
    memcpy(packed_size, file_header.pack_size, 4);
Packit Service 1d0348
    memcpy(packed_size + 4, p, 4); /* High pack size */
Packit Service 1d0348
    p += 4;
Packit Service 1d0348
    memcpy(unp_size, file_header.unp_size, 4);
Packit Service 1d0348
    memcpy(unp_size + 4, p, 4); /* High unpack size */
Packit Service 1d0348
    p += 4;
Packit Service 1d0348
    rar->packed_size = archive_le64dec(&packed_size);
Packit Service 1d0348
    rar->unp_size = archive_le64dec(&unp_size);
Packit Service 1d0348
  }
Packit Service 1d0348
  else
Packit Service 1d0348
  {
Packit Service 1d0348
    rar->packed_size = archive_le32dec(file_header.pack_size);
Packit Service 1d0348
    rar->unp_size = archive_le32dec(file_header.unp_size);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  if (rar->packed_size < 0 || rar->unp_size < 0)
Packit Service 1d0348
  {
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                      "Invalid sizes specified.");
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  rar->bytes_remaining = rar->packed_size;
Packit Service 1d0348
Packit Service 1d0348
  /* TODO: RARv3 subblocks contain comments. For now the complete block is
Packit Service 1d0348
   * consumed at the end.
Packit Service 1d0348
   */
Packit Service 1d0348
  if (head_type == NEWSUB_HEAD) {
Packit Service 1d0348
    size_t distance = p - (const char *)h;
Packit Service 1d0348
    header_size += rar->packed_size;
Packit Service 1d0348
    /* Make sure we have the extended data. */
Packit Service 1d0348
    if ((h = __archive_read_ahead(a, (size_t)header_size - 7, NULL)) == NULL)
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
    p = h;
Packit Service 1d0348
    endp = p + header_size - 7;
Packit Service 1d0348
    p += distance;
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  filename_size = archive_le16dec(file_header.name_size);
Packit Service 1d0348
  if (p + filename_size > endp) {
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
      "Invalid filename size");
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
  if (rar->filename_allocated < filename_size * 2 + 2) {
Packit Service 1d0348
    char *newptr;
Packit Service 1d0348
    size_t newsize = filename_size * 2 + 2;
Packit Service 1d0348
    newptr = realloc(rar->filename, newsize);
Packit Service 1d0348
    if (newptr == NULL) {
Packit Service 1d0348
      archive_set_error(&a->archive, ENOMEM,
Packit Service 1d0348
                        "Couldn't allocate memory.");
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
    }
Packit Service 1d0348
    rar->filename = newptr;
Packit Service 1d0348
    rar->filename_allocated = newsize;
Packit Service 1d0348
  }
Packit Service 1d0348
  filename = rar->filename;
Packit Service 1d0348
  memcpy(filename, p, filename_size);
Packit Service 1d0348
  filename[filename_size] = '\0';
Packit Service 1d0348
  if (rar->file_flags & FHD_UNICODE)
Packit Service 1d0348
  {
Packit Service 1d0348
    if (filename_size != strlen(filename))
Packit Service 1d0348
    {
Packit Service 1d0348
      unsigned char highbyte, flagbits, flagbyte;
Packit Service 1d0348
      unsigned fn_end, offset;
Packit Service 1d0348
Packit Service 1d0348
      end = filename_size;
Packit Service 1d0348
      fn_end = filename_size * 2;
Packit Service 1d0348
      filename_size = 0;
Packit Service 1d0348
      offset = (unsigned)strlen(filename) + 1;
Packit Service 1d0348
      highbyte = *(p + offset++);
Packit Service 1d0348
      flagbits = 0;
Packit Service 1d0348
      flagbyte = 0;
Packit Service 1d0348
      while (offset < end && filename_size < fn_end)
Packit Service 1d0348
      {
Packit Service 1d0348
        if (!flagbits)
Packit Service 1d0348
        {
Packit Service 1d0348
          flagbyte = *(p + offset++);
Packit Service 1d0348
          flagbits = 8;
Packit Service 1d0348
        }
Packit Service 1d0348
Packit Service 1d0348
        flagbits -= 2;
Packit Service 1d0348
        switch((flagbyte >> flagbits) & 3)
Packit Service 1d0348
        {
Packit Service 1d0348
          case 0:
Packit Service 1d0348
            filename[filename_size++] = '\0';
Packit Service 1d0348
            filename[filename_size++] = *(p + offset++);
Packit Service 1d0348
            break;
Packit Service 1d0348
          case 1:
Packit Service 1d0348
            filename[filename_size++] = highbyte;
Packit Service 1d0348
            filename[filename_size++] = *(p + offset++);
Packit Service 1d0348
            break;
Packit Service 1d0348
          case 2:
Packit Service 1d0348
            filename[filename_size++] = *(p + offset + 1);
Packit Service 1d0348
            filename[filename_size++] = *(p + offset);
Packit Service 1d0348
            offset += 2;
Packit Service 1d0348
            break;
Packit Service 1d0348
          case 3:
Packit Service 1d0348
          {
Packit Service 1d0348
            char extra, high;
Packit Service 1d0348
            uint8_t length = *(p + offset++);
Packit Service 1d0348
Packit Service 1d0348
            if (length & 0x80) {
Packit Service 1d0348
              extra = *(p + offset++);
Packit Service 1d0348
              high = (char)highbyte;
Packit Service 1d0348
            } else
Packit Service 1d0348
              extra = high = 0;
Packit Service 1d0348
            length = (length & 0x7f) + 2;
Packit Service 1d0348
            while (length && filename_size < fn_end) {
Packit Service 1d0348
              unsigned cp = filename_size >> 1;
Packit Service 1d0348
              filename[filename_size++] = high;
Packit Service 1d0348
              filename[filename_size++] = p[cp] + extra;
Packit Service 1d0348
              length--;
Packit Service 1d0348
            }
Packit Service 1d0348
          }
Packit Service 1d0348
          break;
Packit Service 1d0348
        }
Packit Service 1d0348
      }
Packit Service 1d0348
      if (filename_size > fn_end) {
Packit Service 1d0348
        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
          "Invalid filename");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      filename[filename_size++] = '\0';
Packit Service 1d0348
      /*
Packit Service 1d0348
       * Do not increment filename_size here as the computations below
Packit Service 1d0348
       * add the space for the terminating NUL explicitly.
Packit Service 1d0348
       */
Packit Service 1d0348
      filename[filename_size] = '\0';
Packit Service 1d0348
Packit Service 1d0348
      /* Decoded unicode form is UTF-16BE, so we have to update a string
Packit Service 1d0348
       * conversion object for it. */
Packit Service 1d0348
      if (rar->sconv_utf16be == NULL) {
Packit Service 1d0348
        rar->sconv_utf16be = archive_string_conversion_from_charset(
Packit Service 1d0348
           &a->archive, "UTF-16BE", 1);
Packit Service 1d0348
        if (rar->sconv_utf16be == NULL)
Packit Service 1d0348
          return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      fn_sconv = rar->sconv_utf16be;
Packit Service 1d0348
Packit Service 1d0348
      strp = filename;
Packit Service 1d0348
      while (memcmp(strp, "\x00\x00", 2))
Packit Service 1d0348
      {
Packit Service 1d0348
        if (!memcmp(strp, "\x00\\", 2))
Packit Service 1d0348
          *(strp + 1) = '/';
Packit Service 1d0348
        strp += 2;
Packit Service 1d0348
      }
Packit Service 1d0348
      p += offset;
Packit Service 1d0348
    } else {
Packit Service 1d0348
      /*
Packit Service 1d0348
       * If FHD_UNICODE is set but no unicode data, this file name form
Packit Service 1d0348
       * is UTF-8, so we have to update a string conversion object for
Packit Service 1d0348
       * it accordingly.
Packit Service 1d0348
       */
Packit Service 1d0348
      if (rar->sconv_utf8 == NULL) {
Packit Service 1d0348
        rar->sconv_utf8 = archive_string_conversion_from_charset(
Packit Service 1d0348
           &a->archive, "UTF-8", 1);
Packit Service 1d0348
        if (rar->sconv_utf8 == NULL)
Packit Service 1d0348
          return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      fn_sconv = rar->sconv_utf8;
Packit Service 1d0348
      while ((strp = strchr(filename, '\\')) != NULL)
Packit Service 1d0348
        *strp = '/';
Packit Service 1d0348
      p += filename_size;
Packit Service 1d0348
    }
Packit Service 1d0348
  }
Packit Service 1d0348
  else
Packit Service 1d0348
  {
Packit Service 1d0348
    fn_sconv = sconv;
Packit Service 1d0348
    while ((strp = strchr(filename, '\\')) != NULL)
Packit Service 1d0348
      *strp = '/';
Packit Service 1d0348
    p += filename_size;
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  /* Split file in multivolume RAR. No more need to process header. */
Packit Service 1d0348
  if (rar->filename_save &&
Packit Service 1d0348
    filename_size == rar->filename_save_size &&
Packit Service 1d0348
    !memcmp(rar->filename, rar->filename_save, filename_size + 1))
Packit Service 1d0348
  {
Packit Service 1d0348
    __archive_read_consume(a, header_size - 7);
Packit Service 1d0348
    rar->cursor++;
Packit Service 1d0348
    if (rar->cursor >= rar->nodes)
Packit Service 1d0348
    {
Packit Service 1d0348
      rar->nodes++;
Packit Service 1d0348
      if ((rar->dbo =
Packit Service 1d0348
        realloc(rar->dbo, sizeof(*rar->dbo) * rar->nodes)) == NULL)
Packit Service 1d0348
      {
Packit Service 1d0348
        archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory.");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      rar->dbo[rar->cursor].header_size = header_size;
Packit Service 1d0348
      rar->dbo[rar->cursor].start_offset = -1;
Packit Service 1d0348
      rar->dbo[rar->cursor].end_offset = -1;
Packit Service 1d0348
    }
Packit Service 1d0348
    if (rar->dbo[rar->cursor].start_offset < 0)
Packit Service 1d0348
    {
Packit Service 1d0348
      rar->dbo[rar->cursor].start_offset = a->filter->position;
Packit Service 1d0348
      rar->dbo[rar->cursor].end_offset = rar->dbo[rar->cursor].start_offset +
Packit Service 1d0348
        rar->packed_size;
Packit Service 1d0348
    }
Packit Service 1d0348
    return ret;
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  rar->filename_save = (char*)realloc(rar->filename_save,
Packit Service 1d0348
                                      filename_size + 1);
Packit Service 1d0348
  memcpy(rar->filename_save, rar->filename, filename_size + 1);
Packit Service 1d0348
  rar->filename_save_size = filename_size;
Packit Service 1d0348
Packit Service 1d0348
  /* Set info for seeking */
Packit Service 1d0348
  free(rar->dbo);
Packit Service 1d0348
  if ((rar->dbo = calloc(1, sizeof(*rar->dbo))) == NULL)
Packit Service 1d0348
  {
Packit Service 1d0348
    archive_set_error(&a->archive, ENOMEM, "Couldn't allocate memory.");
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
  rar->dbo[0].header_size = header_size;
Packit Service 1d0348
  rar->dbo[0].start_offset = -1;
Packit Service 1d0348
  rar->dbo[0].end_offset = -1;
Packit Service 1d0348
  rar->cursor = 0;
Packit Service 1d0348
  rar->nodes = 1;
Packit Service 1d0348
Packit Service 1d0348
  if (rar->file_flags & FHD_SALT)
Packit Service 1d0348
  {
Packit Service 1d0348
    if (p + 8 > endp) {
Packit Service 1d0348
      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
        "Invalid header size");
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
    }
Packit Service 1d0348
    memcpy(rar->salt, p, 8);
Packit Service 1d0348
    p += 8;
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  if (rar->file_flags & FHD_EXTTIME) {
Packit Service 1d0348
    if (read_exttime(p, rar, endp) < 0) {
Packit Service 1d0348
      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
        "Invalid header size");
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
    }
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  __archive_read_consume(a, header_size - 7);
Packit Service 1d0348
  rar->dbo[0].start_offset = a->filter->position;
Packit Service 1d0348
  rar->dbo[0].end_offset = rar->dbo[0].start_offset + rar->packed_size;
Packit Service 1d0348
Packit Service 1d0348
  switch(file_header.host_os)
Packit Service 1d0348
  {
Packit Service 1d0348
  case OS_MSDOS:
Packit Service 1d0348
  case OS_OS2:
Packit Service 1d0348
  case OS_WIN32:
Packit Service 1d0348
    rar->mode = archive_le32dec(file_header.file_attr);
Packit Service 1d0348
    if (rar->mode & FILE_ATTRIBUTE_DIRECTORY)
Packit Service 1d0348
      rar->mode = AE_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
Packit Service 1d0348
    else
Packit Service 1d0348
      rar->mode = AE_IFREG;
Packit Service 1d0348
    rar->mode |= S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
Packit Service 1d0348
    break;
Packit Service 1d0348
Packit Service 1d0348
  case OS_UNIX:
Packit Service 1d0348
  case OS_MAC_OS:
Packit Service 1d0348
  case OS_BEOS:
Packit Service 1d0348
    rar->mode = archive_le32dec(file_header.file_attr);
Packit Service 1d0348
    break;
Packit Service 1d0348
Packit Service 1d0348
  default:
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                      "Unknown file attributes from RAR file's host OS");
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  rar->bytes_uncopied = rar->bytes_unconsumed = 0;
Packit Service 1d0348
  rar->lzss.position = rar->offset = 0;
Packit Service 1d0348
  rar->offset_seek = 0;
Packit Service 1d0348
  rar->dictionary_size = 0;
Packit Service 1d0348
  rar->offset_outgoing = 0;
Packit Service 1d0348
  rar->br.cache_avail = 0;
Packit Service 1d0348
  rar->br.avail_in = 0;
Packit Service 1d0348
  rar->crc_calculated = 0;
Packit Service 1d0348
  rar->entry_eof = 0;
Packit Service 1d0348
  rar->valid = 1;
Packit Service 1d0348
  rar->is_ppmd_block = 0;
Packit Service 1d0348
  rar->start_new_table = 1;
Packit Service 1d0348
  free(rar->unp_buffer);
Packit Service 1d0348
  rar->unp_buffer = NULL;
Packit Service 1d0348
  rar->unp_offset = 0;
Packit Service 1d0348
  rar->unp_buffer_size = UNP_BUFFER_SIZE;
Packit Service 1d0348
  memset(rar->lengthtable, 0, sizeof(rar->lengthtable));
Packit Service 1d0348
  __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
Packit Service 1d0348
  rar->ppmd_valid = rar->ppmd_eod = 0;
Packit Service 1d0348
Packit Service 1d0348
  /* Don't set any archive entries for non-file header types */
Packit Service 1d0348
  if (head_type == NEWSUB_HEAD)
Packit Service 1d0348
    return ret;
Packit Service 1d0348
Packit Service 1d0348
  archive_entry_set_mtime(entry, rar->mtime, rar->mnsec);
Packit Service 1d0348
  archive_entry_set_ctime(entry, rar->ctime, rar->cnsec);
Packit Service 1d0348
  archive_entry_set_atime(entry, rar->atime, rar->ansec);
Packit Service 1d0348
  archive_entry_set_size(entry, rar->unp_size);
Packit Service 1d0348
  archive_entry_set_mode(entry, rar->mode);
Packit Service 1d0348
Packit Service 1d0348
  if (archive_entry_copy_pathname_l(entry, filename, filename_size, fn_sconv))
Packit Service 1d0348
  {
Packit Service 1d0348
    if (errno == ENOMEM)
Packit Service 1d0348
    {
Packit Service 1d0348
      archive_set_error(&a->archive, ENOMEM,
Packit Service 1d0348
                        "Can't allocate memory for Pathname");
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
    }
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                      "Pathname cannot be converted from %s to current locale.",
Packit Service 1d0348
                      archive_string_conversion_charset_name(fn_sconv));
Packit Service 1d0348
    ret = (ARCHIVE_WARN);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  if (((rar->mode) & AE_IFMT) == AE_IFLNK)
Packit Service 1d0348
  {
Packit Service 1d0348
    /* Make sure a symbolic-link file does not have its body. */
Packit Service 1d0348
    rar->bytes_remaining = 0;
Packit Service 1d0348
    archive_entry_set_size(entry, 0);
Packit Service 1d0348
Packit Service 1d0348
    /* Read a symbolic-link name. */
Packit Service 1d0348
    if ((ret2 = read_symlink_stored(a, entry, sconv)) < (ARCHIVE_WARN))
Packit Service 1d0348
      return ret2;
Packit Service 1d0348
    if (ret > ret2)
Packit Service 1d0348
      ret = ret2;
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  if (rar->bytes_remaining == 0)
Packit Service 1d0348
    rar->entry_eof = 1;
Packit Service 1d0348
Packit Service 1d0348
  return ret;
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static time_t
Packit Service 1d0348
get_time(int ttime)
Packit Service 1d0348
{
Packit Service 1d0348
  struct tm tm;
Packit Service 1d0348
  tm.tm_sec = 2 * (ttime & 0x1f);
Packit Service 1d0348
  tm.tm_min = (ttime >> 5) & 0x3f;
Packit Service 1d0348
  tm.tm_hour = (ttime >> 11) & 0x1f;
Packit Service 1d0348
  tm.tm_mday = (ttime >> 16) & 0x1f;
Packit Service 1d0348
  tm.tm_mon = ((ttime >> 21) & 0x0f) - 1;
Packit Service 1d0348
  tm.tm_year = ((ttime >> 25) & 0x7f) + 80;
Packit Service 1d0348
  tm.tm_isdst = -1;
Packit Service 1d0348
  return mktime(&tm;;
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
read_exttime(const char *p, struct rar *rar, const char *endp)
Packit Service 1d0348
{
Packit Service 1d0348
  unsigned rmode, flags, rem, j, count;
Packit Service 1d0348
  int ttime, i;
Packit Service 1d0348
  struct tm *tm;
Packit Service 1d0348
  time_t t;
Packit Service 1d0348
  long nsec;
Packit Service 1d0348
Packit Service 1d0348
  if (p + 2 > endp)
Packit Service 1d0348
    return (-1);
Packit Service 1d0348
  flags = archive_le16dec(p);
Packit Service 1d0348
  p += 2;
Packit Service 1d0348
Packit Service 1d0348
  for (i = 3; i >= 0; i--)
Packit Service 1d0348
  {
Packit Service 1d0348
    t = 0;
Packit Service 1d0348
    if (i == 3)
Packit Service 1d0348
      t = rar->mtime;
Packit Service 1d0348
    rmode = flags >> i * 4;
Packit Service 1d0348
    if (rmode & 8)
Packit Service 1d0348
    {
Packit Service 1d0348
      if (!t)
Packit Service 1d0348
      {
Packit Service 1d0348
        if (p + 4 > endp)
Packit Service 1d0348
          return (-1);
Packit Service 1d0348
        ttime = archive_le32dec(p);
Packit Service 1d0348
        t = get_time(ttime);
Packit Service 1d0348
        p += 4;
Packit Service 1d0348
      }
Packit Service 1d0348
      rem = 0;
Packit Service 1d0348
      count = rmode & 3;
Packit Service 1d0348
      if (p + count > endp)
Packit Service 1d0348
        return (-1);
Packit Service 1d0348
      for (j = 0; j < count; j++)
Packit Service 1d0348
      {
Packit Service 1d0348
        rem = (((unsigned)(unsigned char)*p) << 16) | (rem >> 8);
Packit Service 1d0348
        p++;
Packit Service 1d0348
      }
Packit Service 1d0348
      tm = localtime(&t);
Packit Service 1d0348
      nsec = tm->tm_sec + rem / NS_UNIT;
Packit Service 1d0348
      if (rmode & 4)
Packit Service 1d0348
      {
Packit Service 1d0348
        tm->tm_sec++;
Packit Service 1d0348
        t = mktime(tm);
Packit Service 1d0348
      }
Packit Service 1d0348
      if (i == 3)
Packit Service 1d0348
      {
Packit Service 1d0348
        rar->mtime = t;
Packit Service 1d0348
        rar->mnsec = nsec;
Packit Service 1d0348
      }
Packit Service 1d0348
      else if (i == 2)
Packit Service 1d0348
      {
Packit Service 1d0348
        rar->ctime = t;
Packit Service 1d0348
        rar->cnsec = nsec;
Packit Service 1d0348
      }
Packit Service 1d0348
      else if (i == 1)
Packit Service 1d0348
      {
Packit Service 1d0348
        rar->atime = t;
Packit Service 1d0348
        rar->ansec = nsec;
Packit Service 1d0348
      }
Packit Service 1d0348
      else
Packit Service 1d0348
      {
Packit Service 1d0348
        rar->arctime = t;
Packit Service 1d0348
        rar->arcnsec = nsec;
Packit Service 1d0348
      }
Packit Service 1d0348
    }
Packit Service 1d0348
  }
Packit Service 1d0348
  return (0);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
read_symlink_stored(struct archive_read *a, struct archive_entry *entry,
Packit Service 1d0348
                    struct archive_string_conv *sconv)
Packit Service 1d0348
{
Packit Service 1d0348
  const void *h;
Packit Service 1d0348
  const char *p;
Packit Service 1d0348
  struct rar *rar;
Packit Service 1d0348
  int ret = (ARCHIVE_OK);
Packit Service 1d0348
Packit Service 1d0348
  rar = (struct rar *)(a->format->data);
Packit Service 1d0348
  if ((h = rar_read_ahead(a, (size_t)rar->packed_size, NULL)) == NULL)
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  p = h;
Packit Service 1d0348
Packit Service 1d0348
  if (archive_entry_copy_symlink_l(entry,
Packit Service 1d0348
      p, (size_t)rar->packed_size, sconv))
Packit Service 1d0348
  {
Packit Service 1d0348
    if (errno == ENOMEM)
Packit Service 1d0348
    {
Packit Service 1d0348
      archive_set_error(&a->archive, ENOMEM,
Packit Service 1d0348
                        "Can't allocate memory for link");
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
    }
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                      "link cannot be converted from %s to current locale.",
Packit Service 1d0348
                      archive_string_conversion_charset_name(sconv));
Packit Service 1d0348
    ret = (ARCHIVE_WARN);
Packit Service 1d0348
  }
Packit Service 1d0348
  __archive_read_consume(a, rar->packed_size);
Packit Service 1d0348
  return ret;
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
read_data_stored(struct archive_read *a, const void **buff, size_t *size,
Packit Service 1d0348
                 int64_t *offset)
Packit Service 1d0348
{
Packit Service 1d0348
  struct rar *rar;
Packit Service 1d0348
  ssize_t bytes_avail;
Packit Service 1d0348
Packit Service 1d0348
  rar = (struct rar *)(a->format->data);
Packit Service 1d0348
  if (rar->bytes_remaining == 0 &&
Packit Service 1d0348
    !(rar->main_flags & MHD_VOLUME && rar->file_flags & FHD_SPLIT_AFTER))
Packit Service 1d0348
  {
Packit Service 1d0348
    *buff = NULL;
Packit Service 1d0348
    *size = 0;
Packit Service 1d0348
    *offset = rar->offset;
Packit Service 1d0348
    if (rar->file_crc != rar->crc_calculated) {
Packit Service 1d0348
      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                        "File CRC error");
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
    }
Packit Service 1d0348
    rar->entry_eof = 1;
Packit Service 1d0348
    return (ARCHIVE_EOF);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  *buff = rar_read_ahead(a, 1, &bytes_avail);
Packit Service 1d0348
  if (bytes_avail <= 0)
Packit Service 1d0348
  {
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                      "Truncated RAR file data");
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  *size = bytes_avail;
Packit Service 1d0348
  *offset = rar->offset;
Packit Service 1d0348
  rar->offset += bytes_avail;
Packit Service 1d0348
  rar->offset_seek += bytes_avail;
Packit Service 1d0348
  rar->bytes_remaining -= bytes_avail;
Packit Service 1d0348
  rar->bytes_unconsumed = bytes_avail;
Packit Service 1d0348
  /* Calculate File CRC. */
Packit Service 1d0348
  rar->crc_calculated = crc32(rar->crc_calculated, *buff,
Packit Service 1d0348
    (unsigned)bytes_avail);
Packit Service 1d0348
  return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
read_data_compressed(struct archive_read *a, const void **buff, size_t *size,
Packit Service 1d0348
               int64_t *offset)
Packit Service 1d0348
{
Packit Service 1d0348
  struct rar *rar;
Packit Service 1d0348
  int64_t start, end, actualend;
Packit Service 1d0348
  size_t bs;
Packit Service 1d0348
  int ret = (ARCHIVE_OK), sym, code, lzss_offset, length, i;
Packit Service 1d0348
Packit Service 1d0348
  rar = (struct rar *)(a->format->data);
Packit Service 1d0348
Packit Service 1d0348
  do {
Packit Service 1d0348
    if (!rar->valid)
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
    if (rar->ppmd_eod ||
Packit Service 1d0348
       (rar->dictionary_size && rar->offset >= rar->unp_size))
Packit Service 1d0348
    {
Packit Service 1d0348
      if (rar->unp_offset > 0) {
Packit Service 1d0348
        /*
Packit Service 1d0348
         * We have unprocessed extracted data. write it out.
Packit Service 1d0348
         */
Packit Service 1d0348
        *buff = rar->unp_buffer;
Packit Service 1d0348
        *size = rar->unp_offset;
Packit Service 1d0348
        *offset = rar->offset_outgoing;
Packit Service 1d0348
        rar->offset_outgoing += *size;
Packit Service 1d0348
        /* Calculate File CRC. */
Packit Service 1d0348
        rar->crc_calculated = crc32(rar->crc_calculated, *buff,
Packit Service 1d0348
          (unsigned)*size);
Packit Service 1d0348
        rar->unp_offset = 0;
Packit Service 1d0348
        return (ARCHIVE_OK);
Packit Service 1d0348
      }
Packit Service 1d0348
      *buff = NULL;
Packit Service 1d0348
      *size = 0;
Packit Service 1d0348
      *offset = rar->offset;
Packit Service 1d0348
      if (rar->file_crc != rar->crc_calculated) {
Packit Service 1d0348
        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                          "File CRC error");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      rar->entry_eof = 1;
Packit Service 1d0348
      return (ARCHIVE_EOF);
Packit Service 1d0348
    }
Packit Service 1d0348
Packit Service 1d0348
    if (!rar->is_ppmd_block && rar->dictionary_size && rar->bytes_uncopied > 0)
Packit Service 1d0348
    {
Packit Service 1d0348
      if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset))
Packit Service 1d0348
        bs = rar->unp_buffer_size - rar->unp_offset;
Packit Service 1d0348
      else
Packit Service 1d0348
        bs = (size_t)rar->bytes_uncopied;
Packit Service 1d0348
      ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs);
Packit Service 1d0348
      if (ret != ARCHIVE_OK)
Packit Service 1d0348
        return (ret);
Packit Service 1d0348
      rar->offset += bs;
Packit Service 1d0348
      rar->bytes_uncopied -= bs;
Packit Service 1d0348
      if (*buff != NULL) {
Packit Service 1d0348
        rar->unp_offset = 0;
Packit Service 1d0348
        *size = rar->unp_buffer_size;
Packit Service 1d0348
        *offset = rar->offset_outgoing;
Packit Service 1d0348
        rar->offset_outgoing += *size;
Packit Service 1d0348
        /* Calculate File CRC. */
Packit Service 1d0348
        rar->crc_calculated = crc32(rar->crc_calculated, *buff,
Packit Service 1d0348
          (unsigned)*size);
Packit Service 1d0348
        return (ret);
Packit Service 1d0348
      }
Packit Service 1d0348
      continue;
Packit Service 1d0348
    }
Packit Service 1d0348
Packit Service 1d0348
    if (!rar->br.next_in &&
Packit Service 1d0348
      (ret = rar_br_preparation(a, &(rar->br))) < ARCHIVE_WARN)
Packit Service 1d0348
      return (ret);
Packit Service 1d0348
    if (rar->start_new_table && ((ret = parse_codes(a)) < (ARCHIVE_WARN)))
Packit Service 1d0348
      return (ret);
Packit Service 1d0348
Packit Service 1d0348
    if (rar->is_ppmd_block)
Packit Service 1d0348
    {
Packit Service 1d0348
      if ((sym = __archive_ppmd7_functions.Ppmd7_DecodeSymbol(
Packit Service 1d0348
        &rar->ppmd7_context, &rar->range_dec.p)) < 0)
Packit Service 1d0348
      {
Packit Service 1d0348
        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                          "Invalid symbol");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      if(sym != rar->ppmd_escape)
Packit Service 1d0348
      {
Packit Service 1d0348
        lzss_emit_literal(rar, sym);
Packit Service 1d0348
        rar->bytes_uncopied++;
Packit Service 1d0348
      }
Packit Service 1d0348
      else
Packit Service 1d0348
      {
Packit Service 1d0348
        if ((code = __archive_ppmd7_functions.Ppmd7_DecodeSymbol(
Packit Service 1d0348
          &rar->ppmd7_context, &rar->range_dec.p)) < 0)
Packit Service 1d0348
        {
Packit Service 1d0348
          archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                            "Invalid symbol");
Packit Service 1d0348
          return (ARCHIVE_FATAL);
Packit Service 1d0348
        }
Packit Service 1d0348
Packit Service 1d0348
        switch(code)
Packit Service 1d0348
        {
Packit Service 1d0348
          case 0:
Packit Service 1d0348
            rar->start_new_table = 1;
Packit Service 1d0348
            return read_data_compressed(a, buff, size, offset);
Packit Service 1d0348
Packit Service 1d0348
          case 2:
Packit Service 1d0348
            rar->ppmd_eod = 1;/* End Of ppmd Data. */
Packit Service 1d0348
            continue;
Packit Service 1d0348
Packit Service 1d0348
          case 3:
Packit Service 1d0348
            archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
                              "Parsing filters is unsupported.");
Packit Service 1d0348
            return (ARCHIVE_FAILED);
Packit Service 1d0348
Packit Service 1d0348
          case 4:
Packit Service 1d0348
            lzss_offset = 0;
Packit Service 1d0348
            for (i = 2; i >= 0; i--)
Packit Service 1d0348
            {
Packit Service 1d0348
              if ((code = __archive_ppmd7_functions.Ppmd7_DecodeSymbol(
Packit Service 1d0348
                &rar->ppmd7_context, &rar->range_dec.p)) < 0)
Packit Service 1d0348
              {
Packit Service 1d0348
                archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                                  "Invalid symbol");
Packit Service 1d0348
                return (ARCHIVE_FATAL);
Packit Service 1d0348
              }
Packit Service 1d0348
              lzss_offset |= code << (i * 8);
Packit Service 1d0348
            }
Packit Service 1d0348
            if ((length = __archive_ppmd7_functions.Ppmd7_DecodeSymbol(
Packit Service 1d0348
              &rar->ppmd7_context, &rar->range_dec.p)) < 0)
Packit Service 1d0348
            {
Packit Service 1d0348
              archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                                "Invalid symbol");
Packit Service 1d0348
              return (ARCHIVE_FATAL);
Packit Service 1d0348
            }
Packit Service 1d0348
            lzss_emit_match(rar, lzss_offset + 2, length + 32);
Packit Service 1d0348
            rar->bytes_uncopied += length + 32;
Packit Service 1d0348
            break;
Packit Service 1d0348
Packit Service 1d0348
          case 5:
Packit Service 1d0348
            if ((length = __archive_ppmd7_functions.Ppmd7_DecodeSymbol(
Packit Service 1d0348
              &rar->ppmd7_context, &rar->range_dec.p)) < 0)
Packit Service 1d0348
            {
Packit Service 1d0348
              archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                                "Invalid symbol");
Packit Service 1d0348
              return (ARCHIVE_FATAL);
Packit Service 1d0348
            }
Packit Service 1d0348
            lzss_emit_match(rar, 1, length + 4);
Packit Service 1d0348
            rar->bytes_uncopied += length + 4;
Packit Service 1d0348
            break;
Packit Service 1d0348
Packit Service 1d0348
         default:
Packit Service 1d0348
           lzss_emit_literal(rar, sym);
Packit Service 1d0348
           rar->bytes_uncopied++;
Packit Service 1d0348
        }
Packit Service 1d0348
      }
Packit Service 1d0348
    }
Packit Service 1d0348
    else
Packit Service 1d0348
    {
Packit Service 1d0348
      start = rar->offset;
Packit Service 1d0348
      end = start + rar->dictionary_size;
Packit Service 1d0348
      rar->filterstart = INT64_MAX;
Packit Service 1d0348
Packit Service 1d0348
      if ((actualend = expand(a, end)) < 0)
Packit Service 1d0348
        return ((int)actualend);
Packit Service 1d0348
Packit Service 1d0348
      rar->bytes_uncopied = actualend - start;
Packit Service 1d0348
      if (rar->bytes_uncopied == 0) {
Packit Service 1d0348
          /* Broken RAR files cause this case.
Packit Service 1d0348
          * NOTE: If this case were possible on a normal RAR file
Packit Service 1d0348
          * we would find out where it was actually bad and
Packit Service 1d0348
          * what we would do to solve it. */
Packit Service 1d0348
          archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                            "Internal error extracting RAR file");
Packit Service 1d0348
          return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
    }
Packit Service 1d0348
    if (rar->bytes_uncopied > (rar->unp_buffer_size - rar->unp_offset))
Packit Service 1d0348
      bs = rar->unp_buffer_size - rar->unp_offset;
Packit Service 1d0348
    else
Packit Service 1d0348
      bs = (size_t)rar->bytes_uncopied;
Packit Service 1d0348
    ret = copy_from_lzss_window(a, buff, rar->offset, (int)bs);
Packit Service 1d0348
    if (ret != ARCHIVE_OK)
Packit Service 1d0348
      return (ret);
Packit Service 1d0348
    rar->offset += bs;
Packit Service 1d0348
    rar->bytes_uncopied -= bs;
Packit Service 1d0348
    /*
Packit Service 1d0348
     * If *buff is NULL, it means unp_buffer is not full.
Packit Service 1d0348
     * So we have to continue extracting a RAR file.
Packit Service 1d0348
     */
Packit Service 1d0348
  } while (*buff == NULL);
Packit Service 1d0348
Packit Service 1d0348
  rar->unp_offset = 0;
Packit Service 1d0348
  *size = rar->unp_buffer_size;
Packit Service 1d0348
  *offset = rar->offset_outgoing;
Packit Service 1d0348
  rar->offset_outgoing += *size;
Packit Service 1d0348
  /* Calculate File CRC. */
Packit Service 1d0348
  rar->crc_calculated = crc32(rar->crc_calculated, *buff, (unsigned)*size);
Packit Service 1d0348
  return ret;
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
parse_codes(struct archive_read *a)
Packit Service 1d0348
{
Packit Service 1d0348
  int i, j, val, n, r;
Packit Service 1d0348
  unsigned char bitlengths[MAX_SYMBOLS], zerocount, ppmd_flags;
Packit Service 1d0348
  unsigned int maxorder;
Packit Service 1d0348
  struct huffman_code precode;
Packit Service 1d0348
  struct rar *rar = (struct rar *)(a->format->data);
Packit Service 1d0348
  struct rar_br *br = &(rar->br);
Packit Service 1d0348
Packit Service 1d0348
  free_codes(a);
Packit Service 1d0348
Packit Service 1d0348
  /* Skip to the next byte */
Packit Service 1d0348
  rar_br_consume_unalined_bits(br);
Packit Service 1d0348
Packit Service 1d0348
  /* PPMd block flag */
Packit Service 1d0348
  if (!rar_br_read_ahead(a, br, 1))
Packit Service 1d0348
    goto truncated_data;
Packit Service 1d0348
  if ((rar->is_ppmd_block = rar_br_bits(br, 1)) != 0)
Packit Service 1d0348
  {
Packit Service 1d0348
    rar_br_consume(br, 1);
Packit Service 1d0348
    if (!rar_br_read_ahead(a, br, 7))
Packit Service 1d0348
      goto truncated_data;
Packit Service 1d0348
    ppmd_flags = rar_br_bits(br, 7);
Packit Service 1d0348
    rar_br_consume(br, 7);
Packit Service 1d0348
Packit Service 1d0348
    /* Memory is allocated in MB */
Packit Service 1d0348
    if (ppmd_flags & 0x20)
Packit Service 1d0348
    {
Packit Service 1d0348
      if (!rar_br_read_ahead(a, br, 8))
Packit Service 1d0348
        goto truncated_data;
Packit Service 1d0348
      rar->dictionary_size = (rar_br_bits(br, 8) + 1) << 20;
Packit Service 1d0348
      rar_br_consume(br, 8);
Packit Service 1d0348
    }
Packit Service 1d0348
Packit Service 1d0348
    if (ppmd_flags & 0x40)
Packit Service 1d0348
    {
Packit Service 1d0348
      if (!rar_br_read_ahead(a, br, 8))
Packit Service 1d0348
        goto truncated_data;
Packit Service 1d0348
      rar->ppmd_escape = rar->ppmd7_context.InitEsc = rar_br_bits(br, 8);
Packit Service 1d0348
      rar_br_consume(br, 8);
Packit Service 1d0348
    }
Packit Service 1d0348
    else
Packit Service 1d0348
      rar->ppmd_escape = 2;
Packit Service 1d0348
Packit Service 1d0348
    if (ppmd_flags & 0x20)
Packit Service 1d0348
    {
Packit Service 1d0348
      maxorder = (ppmd_flags & 0x1F) + 1;
Packit Service 1d0348
      if(maxorder > 16)
Packit Service 1d0348
        maxorder = 16 + (maxorder - 16) * 3;
Packit Service 1d0348
Packit Service 1d0348
      if (maxorder == 1)
Packit Service 1d0348
      {
Packit Service 1d0348
        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                          "Truncated RAR file data");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
Packit Service 1d0348
      /* Make sure ppmd7_contest is freed before Ppmd7_Construct
Packit Service 1d0348
       * because reading a broken file cause this abnormal sequence. */
Packit Service 1d0348
      __archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
Packit Service 1d0348
Packit Service 1d0348
      rar->bytein.a = a;
Packit Service 1d0348
      rar->bytein.Read = &ppmd_read;
Packit Service 1d0348
      __archive_ppmd7_functions.PpmdRAR_RangeDec_CreateVTable(&rar->range_dec);
Packit Service 1d0348
      rar->range_dec.Stream = &rar->bytein;
Packit Service 1d0348
      __archive_ppmd7_functions.Ppmd7_Construct(&rar->ppmd7_context);
Packit Service 1d0348
Packit Service 1d0348
      if (rar->dictionary_size == 0) {
Packit Service 1d0348
	      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                          "Invalid zero dictionary size");
Packit Service 1d0348
	      return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
Packit Service 1d0348
      if (!__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context,
Packit Service 1d0348
        rar->dictionary_size))
Packit Service 1d0348
      {
Packit Service 1d0348
        archive_set_error(&a->archive, ENOMEM,
Packit Service 1d0348
                          "Out of memory");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      if (!__archive_ppmd7_functions.PpmdRAR_RangeDec_Init(&rar->range_dec))
Packit Service 1d0348
      {
Packit Service 1d0348
        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                          "Unable to initialize PPMd range decoder");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      __archive_ppmd7_functions.Ppmd7_Init(&rar->ppmd7_context, maxorder);
Packit Service 1d0348
      rar->ppmd_valid = 1;
Packit Service 1d0348
    }
Packit Service 1d0348
    else
Packit Service 1d0348
    {
Packit Service 1d0348
      if (!rar->ppmd_valid) {
Packit Service 1d0348
        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                          "Invalid PPMd sequence");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      if (!__archive_ppmd7_functions.PpmdRAR_RangeDec_Init(&rar->range_dec))
Packit Service 1d0348
      {
Packit Service 1d0348
        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                          "Unable to initialize PPMd range decoder");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
    }
Packit Service 1d0348
  }
Packit Service 1d0348
  else
Packit Service 1d0348
  {
Packit Service 1d0348
    rar_br_consume(br, 1);
Packit Service 1d0348
Packit Service 1d0348
    /* Keep existing table flag */
Packit Service 1d0348
    if (!rar_br_read_ahead(a, br, 1))
Packit Service 1d0348
      goto truncated_data;
Packit Service 1d0348
    if (!rar_br_bits(br, 1))
Packit Service 1d0348
      memset(rar->lengthtable, 0, sizeof(rar->lengthtable));
Packit Service 1d0348
    rar_br_consume(br, 1);
Packit Service 1d0348
Packit Service 1d0348
    memset(&bitlengths, 0, sizeof(bitlengths));
Packit Service 1d0348
    for (i = 0; i < MAX_SYMBOLS;)
Packit Service 1d0348
    {
Packit Service 1d0348
      if (!rar_br_read_ahead(a, br, 4))
Packit Service 1d0348
        goto truncated_data;
Packit Service 1d0348
      bitlengths[i++] = rar_br_bits(br, 4);
Packit Service 1d0348
      rar_br_consume(br, 4);
Packit Service 1d0348
      if (bitlengths[i-1] == 0xF)
Packit Service 1d0348
      {
Packit Service 1d0348
        if (!rar_br_read_ahead(a, br, 4))
Packit Service 1d0348
          goto truncated_data;
Packit Service 1d0348
        zerocount = rar_br_bits(br, 4);
Packit Service 1d0348
        rar_br_consume(br, 4);
Packit Service 1d0348
        if (zerocount)
Packit Service 1d0348
        {
Packit Service 1d0348
          i--;
Packit Service 1d0348
          for (j = 0; j < zerocount + 2 && i < MAX_SYMBOLS; j++)
Packit Service 1d0348
            bitlengths[i++] = 0;
Packit Service 1d0348
        }
Packit Service 1d0348
      }
Packit Service 1d0348
    }
Packit Service 1d0348
Packit Service 1d0348
    memset(&precode, 0, sizeof(precode));
Packit Service 1d0348
    r = create_code(a, &precode, bitlengths, MAX_SYMBOLS, MAX_SYMBOL_LENGTH);
Packit Service 1d0348
    if (r != ARCHIVE_OK) {
Packit Service 1d0348
      free(precode.tree);
Packit Service 1d0348
      free(precode.table);
Packit Service 1d0348
      return (r);
Packit Service 1d0348
    }
Packit Service 1d0348
Packit Service 1d0348
    for (i = 0; i < HUFFMAN_TABLE_SIZE;)
Packit Service 1d0348
    {
Packit Service 1d0348
      if ((val = read_next_symbol(a, &precode)) < 0) {
Packit Service 1d0348
        free(precode.tree);
Packit Service 1d0348
        free(precode.table);
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      if (val < 16)
Packit Service 1d0348
      {
Packit Service 1d0348
        rar->lengthtable[i] = (rar->lengthtable[i] + val) & 0xF;
Packit Service 1d0348
        i++;
Packit Service 1d0348
      }
Packit Service 1d0348
      else if (val < 18)
Packit Service 1d0348
      {
Packit Service 1d0348
        if (i == 0)
Packit Service 1d0348
        {
Packit Service 1d0348
          free(precode.tree);
Packit Service 1d0348
          free(precode.table);
Packit Service 1d0348
          archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                            "Internal error extracting RAR file.");
Packit Service 1d0348
          return (ARCHIVE_FATAL);
Packit Service 1d0348
        }
Packit Service 1d0348
Packit Service 1d0348
        if(val == 16) {
Packit Service 1d0348
          if (!rar_br_read_ahead(a, br, 3)) {
Packit Service 1d0348
            free(precode.tree);
Packit Service 1d0348
            free(precode.table);
Packit Service 1d0348
            goto truncated_data;
Packit Service 1d0348
          }
Packit Service 1d0348
          n = rar_br_bits(br, 3) + 3;
Packit Service 1d0348
          rar_br_consume(br, 3);
Packit Service 1d0348
        } else {
Packit Service 1d0348
          if (!rar_br_read_ahead(a, br, 7)) {
Packit Service 1d0348
            free(precode.tree);
Packit Service 1d0348
            free(precode.table);
Packit Service 1d0348
            goto truncated_data;
Packit Service 1d0348
          }
Packit Service 1d0348
          n = rar_br_bits(br, 7) + 11;
Packit Service 1d0348
          rar_br_consume(br, 7);
Packit Service 1d0348
        }
Packit Service 1d0348
Packit Service 1d0348
        for (j = 0; j < n && i < HUFFMAN_TABLE_SIZE; j++)
Packit Service 1d0348
        {
Packit Service 1d0348
          rar->lengthtable[i] = rar->lengthtable[i-1];
Packit Service 1d0348
          i++;
Packit Service 1d0348
        }
Packit Service 1d0348
      }
Packit Service 1d0348
      else
Packit Service 1d0348
      {
Packit Service 1d0348
        if(val == 18) {
Packit Service 1d0348
          if (!rar_br_read_ahead(a, br, 3)) {
Packit Service 1d0348
            free(precode.tree);
Packit Service 1d0348
            free(precode.table);
Packit Service 1d0348
            goto truncated_data;
Packit Service 1d0348
          }
Packit Service 1d0348
          n = rar_br_bits(br, 3) + 3;
Packit Service 1d0348
          rar_br_consume(br, 3);
Packit Service 1d0348
        } else {
Packit Service 1d0348
          if (!rar_br_read_ahead(a, br, 7)) {
Packit Service 1d0348
            free(precode.tree);
Packit Service 1d0348
            free(precode.table);
Packit Service 1d0348
            goto truncated_data;
Packit Service 1d0348
          }
Packit Service 1d0348
          n = rar_br_bits(br, 7) + 11;
Packit Service 1d0348
          rar_br_consume(br, 7);
Packit Service 1d0348
        }
Packit Service 1d0348
Packit Service 1d0348
        for(j = 0; j < n && i < HUFFMAN_TABLE_SIZE; j++)
Packit Service 1d0348
          rar->lengthtable[i++] = 0;
Packit Service 1d0348
      }
Packit Service 1d0348
    }
Packit Service 1d0348
    free(precode.tree);
Packit Service 1d0348
    free(precode.table);
Packit Service 1d0348
Packit Service 1d0348
    r = create_code(a, &rar->maincode, &rar->lengthtable[0], MAINCODE_SIZE,
Packit Service 1d0348
                MAX_SYMBOL_LENGTH);
Packit Service 1d0348
    if (r != ARCHIVE_OK)
Packit Service 1d0348
      return (r);
Packit Service 1d0348
    r = create_code(a, &rar->offsetcode, &rar->lengthtable[MAINCODE_SIZE],
Packit Service 1d0348
                OFFSETCODE_SIZE, MAX_SYMBOL_LENGTH);
Packit Service 1d0348
    if (r != ARCHIVE_OK)
Packit Service 1d0348
      return (r);
Packit Service 1d0348
    r = create_code(a, &rar->lowoffsetcode,
Packit Service 1d0348
                &rar->lengthtable[MAINCODE_SIZE + OFFSETCODE_SIZE],
Packit Service 1d0348
                LOWOFFSETCODE_SIZE, MAX_SYMBOL_LENGTH);
Packit Service 1d0348
    if (r != ARCHIVE_OK)
Packit Service 1d0348
      return (r);
Packit Service 1d0348
    r = create_code(a, &rar->lengthcode,
Packit Service 1d0348
                &rar->lengthtable[MAINCODE_SIZE + OFFSETCODE_SIZE +
Packit Service 1d0348
                LOWOFFSETCODE_SIZE], LENGTHCODE_SIZE, MAX_SYMBOL_LENGTH);
Packit Service 1d0348
    if (r != ARCHIVE_OK)
Packit Service 1d0348
      return (r);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  if (!rar->dictionary_size || !rar->lzss.window)
Packit Service 1d0348
  {
Packit Service 1d0348
    /* Seems as though dictionary sizes are not used. Even so, minimize
Packit Service 1d0348
     * memory usage as much as possible.
Packit Service 1d0348
     */
Packit Service 1d0348
    void *new_window;
Packit Service 1d0348
    unsigned int new_size;
Packit Service 1d0348
Packit Service 1d0348
    if (rar->unp_size >= DICTIONARY_MAX_SIZE)
Packit Service 1d0348
      new_size = DICTIONARY_MAX_SIZE;
Packit Service 1d0348
    else
Packit Service 1d0348
      new_size = rar_fls((unsigned int)rar->unp_size) << 1;
Packit Service 1d0348
    new_window = realloc(rar->lzss.window, new_size);
Packit Service 1d0348
    if (new_window == NULL) {
Packit Service 1d0348
      archive_set_error(&a->archive, ENOMEM,
Packit Service 1d0348
                        "Unable to allocate memory for uncompressed data.");
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
    }
Packit Service 1d0348
    rar->lzss.window = (unsigned char *)new_window;
Packit Service 1d0348
    rar->dictionary_size = new_size;
Packit Service 1d0348
    memset(rar->lzss.window, 0, rar->dictionary_size);
Packit Service 1d0348
    rar->lzss.mask = rar->dictionary_size - 1;
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  rar->start_new_table = 0;
Packit Service 1d0348
  return (ARCHIVE_OK);
Packit Service 1d0348
truncated_data:
Packit Service 1d0348
  archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                    "Truncated RAR file data");
Packit Service 1d0348
  rar->valid = 0;
Packit Service 1d0348
  return (ARCHIVE_FATAL);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static void
Packit Service 1d0348
free_codes(struct archive_read *a)
Packit Service 1d0348
{
Packit Service 1d0348
  struct rar *rar = (struct rar *)(a->format->data);
Packit Service 1d0348
  free(rar->maincode.tree);
Packit Service 1d0348
  free(rar->offsetcode.tree);
Packit Service 1d0348
  free(rar->lowoffsetcode.tree);
Packit Service 1d0348
  free(rar->lengthcode.tree);
Packit Service 1d0348
  free(rar->maincode.table);
Packit Service 1d0348
  free(rar->offsetcode.table);
Packit Service 1d0348
  free(rar->lowoffsetcode.table);
Packit Service 1d0348
  free(rar->lengthcode.table);
Packit Service 1d0348
  memset(&rar->maincode, 0, sizeof(rar->maincode));
Packit Service 1d0348
  memset(&rar->offsetcode, 0, sizeof(rar->offsetcode));
Packit Service 1d0348
  memset(&rar->lowoffsetcode, 0, sizeof(rar->lowoffsetcode));
Packit Service 1d0348
  memset(&rar->lengthcode, 0, sizeof(rar->lengthcode));
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
read_next_symbol(struct archive_read *a, struct huffman_code *code)
Packit Service 1d0348
{
Packit Service 1d0348
  unsigned char bit;
Packit Service 1d0348
  unsigned int bits;
Packit Service 1d0348
  int length, value, node;
Packit Service 1d0348
  struct rar *rar;
Packit Service 1d0348
  struct rar_br *br;
Packit Service 1d0348
Packit Service 1d0348
  if (!code->table)
Packit Service 1d0348
  {
Packit Service 1d0348
    if (make_table(a, code) != (ARCHIVE_OK))
Packit Service 1d0348
      return -1;
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  rar = (struct rar *)(a->format->data);
Packit Service 1d0348
  br = &(rar->br);
Packit Service 1d0348
Packit Service 1d0348
  /* Look ahead (peek) at bits */
Packit Service 1d0348
  if (!rar_br_read_ahead(a, br, code->tablesize)) {
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                      "Truncated RAR file data");
Packit Service 1d0348
    rar->valid = 0;
Packit Service 1d0348
    return -1;
Packit Service 1d0348
  }
Packit Service 1d0348
  bits = rar_br_bits(br, code->tablesize);
Packit Service 1d0348
Packit Service 1d0348
  length = code->table[bits].length;
Packit Service 1d0348
  value = code->table[bits].value;
Packit Service 1d0348
Packit Service 1d0348
  if (length < 0)
Packit Service 1d0348
  {
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                      "Invalid prefix code in bitstream");
Packit Service 1d0348
    return -1;
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  if (length <= code->tablesize)
Packit Service 1d0348
  {
Packit Service 1d0348
    /* Skip length bits */
Packit Service 1d0348
    rar_br_consume(br, length);
Packit Service 1d0348
    return value;
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  /* Skip tablesize bits */
Packit Service 1d0348
  rar_br_consume(br, code->tablesize);
Packit Service 1d0348
Packit Service 1d0348
  node = value;
Packit Service 1d0348
  while (!(code->tree[node].branches[0] ==
Packit Service 1d0348
    code->tree[node].branches[1]))
Packit Service 1d0348
  {
Packit Service 1d0348
    if (!rar_br_read_ahead(a, br, 1)) {
Packit Service 1d0348
      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                        "Truncated RAR file data");
Packit Service 1d0348
      rar->valid = 0;
Packit Service 1d0348
      return -1;
Packit Service 1d0348
    }
Packit Service 1d0348
    bit = rar_br_bits(br, 1);
Packit Service 1d0348
    rar_br_consume(br, 1);
Packit Service 1d0348
Packit Service 1d0348
    if (code->tree[node].branches[bit] < 0)
Packit Service 1d0348
    {
Packit Service 1d0348
      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                        "Invalid prefix code in bitstream");
Packit Service 1d0348
      return -1;
Packit Service 1d0348
    }
Packit Service 1d0348
    node = code->tree[node].branches[bit];
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  return code->tree[node].branches[0];
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
create_code(struct archive_read *a, struct huffman_code *code,
Packit Service 1d0348
            unsigned char *lengths, int numsymbols, char maxlength)
Packit Service 1d0348
{
Packit Service 1d0348
  int i, j, codebits = 0, symbolsleft = numsymbols;
Packit Service 1d0348
Packit Service 1d0348
  code->numentries = 0;
Packit Service 1d0348
  code->numallocatedentries = 0;
Packit Service 1d0348
  if (new_node(code) < 0) {
Packit Service 1d0348
    archive_set_error(&a->archive, ENOMEM,
Packit Service 1d0348
                      "Unable to allocate memory for node data.");
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
  code->numentries = 1;
Packit Service 1d0348
  code->minlength = INT_MAX;
Packit Service 1d0348
  code->maxlength = INT_MIN;
Packit Service 1d0348
  codebits = 0;
Packit Service 1d0348
  for(i = 1; i <= maxlength; i++)
Packit Service 1d0348
  {
Packit Service 1d0348
    for(j = 0; j < numsymbols; j++)
Packit Service 1d0348
    {
Packit Service 1d0348
      if (lengths[j] != i) continue;
Packit Service 1d0348
      if (add_value(a, code, j, codebits, i) != ARCHIVE_OK)
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      codebits++;
Packit Service 1d0348
      if (--symbolsleft <= 0) { break; break; }
Packit Service 1d0348
    }
Packit Service 1d0348
    codebits <<= 1;
Packit Service 1d0348
  }
Packit Service 1d0348
  return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
add_value(struct archive_read *a, struct huffman_code *code, int value,
Packit Service 1d0348
          int codebits, int length)
Packit Service 1d0348
{
Packit Service 1d0348
  int repeatpos, lastnode, bitpos, bit, repeatnode, nextnode;
Packit Service 1d0348
Packit Service 1d0348
  free(code->table);
Packit Service 1d0348
  code->table = NULL;
Packit Service 1d0348
Packit Service 1d0348
  if(length > code->maxlength)
Packit Service 1d0348
    code->maxlength = length;
Packit Service 1d0348
  if(length < code->minlength)
Packit Service 1d0348
    code->minlength = length;
Packit Service 1d0348
Packit Service 1d0348
  repeatpos = -1;
Packit Service 1d0348
  if (repeatpos == 0 || (repeatpos >= 0
Packit Service 1d0348
    && (((codebits >> (repeatpos - 1)) & 3) == 0
Packit Service 1d0348
    || ((codebits >> (repeatpos - 1)) & 3) == 3)))
Packit Service 1d0348
  {
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                      "Invalid repeat position");
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  lastnode = 0;
Packit Service 1d0348
  for (bitpos = length - 1; bitpos >= 0; bitpos--)
Packit Service 1d0348
  {
Packit Service 1d0348
    bit = (codebits >> bitpos) & 1;
Packit Service 1d0348
Packit Service 1d0348
    /* Leaf node check */
Packit Service 1d0348
    if (code->tree[lastnode].branches[0] ==
Packit Service 1d0348
      code->tree[lastnode].branches[1])
Packit Service 1d0348
    {
Packit Service 1d0348
      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                        "Prefix found");
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
    }
Packit Service 1d0348
Packit Service 1d0348
    if (bitpos == repeatpos)
Packit Service 1d0348
    {
Packit Service 1d0348
      /* Open branch check */
Packit Service 1d0348
      if (!(code->tree[lastnode].branches[bit] < 0))
Packit Service 1d0348
      {
Packit Service 1d0348
        archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                          "Invalid repeating code");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
Packit Service 1d0348
      if ((repeatnode = new_node(code)) < 0) {
Packit Service 1d0348
        archive_set_error(&a->archive, ENOMEM,
Packit Service 1d0348
                          "Unable to allocate memory for node data.");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
      if ((nextnode = new_node(code)) < 0) {
Packit Service 1d0348
        archive_set_error(&a->archive, ENOMEM,
Packit Service 1d0348
                          "Unable to allocate memory for node data.");
Packit Service 1d0348
        return (ARCHIVE_FATAL);
Packit Service 1d0348
      }
Packit Service 1d0348
Packit Service 1d0348
      /* Set branches */
Packit Service 1d0348
      code->tree[lastnode].branches[bit] = repeatnode;
Packit Service 1d0348
      code->tree[repeatnode].branches[bit] = repeatnode;
Packit Service 1d0348
      code->tree[repeatnode].branches[bit^1] = nextnode;
Packit Service 1d0348
      lastnode = nextnode;
Packit Service 1d0348
Packit Service 1d0348
      bitpos++; /* terminating bit already handled, skip it */
Packit Service 1d0348
    }
Packit Service 1d0348
    else
Packit Service 1d0348
    {
Packit Service 1d0348
      /* Open branch check */
Packit Service 1d0348
      if (code->tree[lastnode].branches[bit] < 0)
Packit Service 1d0348
      {
Packit Service 1d0348
        if (new_node(code) < 0) {
Packit Service 1d0348
          archive_set_error(&a->archive, ENOMEM,
Packit Service 1d0348
                            "Unable to allocate memory for node data.");
Packit Service 1d0348
          return (ARCHIVE_FATAL);
Packit Service 1d0348
        }
Packit Service 1d0348
        code->tree[lastnode].branches[bit] = code->numentries++;
Packit Service 1d0348
      }
Packit Service 1d0348
Packit Service 1d0348
      /* set to branch */
Packit Service 1d0348
      lastnode = code->tree[lastnode].branches[bit];
Packit Service 1d0348
    }
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  if (!(code->tree[lastnode].branches[0] == -1
Packit Service 1d0348
    && code->tree[lastnode].branches[1] == -2))
Packit Service 1d0348
  {
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                      "Prefix found");
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  /* Set leaf value */
Packit Service 1d0348
  code->tree[lastnode].branches[0] = value;
Packit Service 1d0348
  code->tree[lastnode].branches[1] = value;
Packit Service 1d0348
Packit Service 1d0348
  return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
new_node(struct huffman_code *code)
Packit Service 1d0348
{
Packit Service 1d0348
  void *new_tree;
Packit Service 1d0348
  if (code->numallocatedentries == code->numentries) {
Packit Service 1d0348
    int new_num_entries = 256;
Packit Service 1d0348
    if (code->numentries > 0) {
Packit Service 1d0348
        new_num_entries = code->numentries * 2;
Packit Service 1d0348
    }
Packit Service 1d0348
    new_tree = realloc(code->tree, new_num_entries * sizeof(*code->tree));
Packit Service 1d0348
    if (new_tree == NULL)
Packit Service 1d0348
        return (-1);
Packit Service 1d0348
    code->tree = (struct huffman_tree_node *)new_tree;
Packit Service 1d0348
    code->numallocatedentries = new_num_entries;
Packit Service 1d0348
  }
Packit Service 1d0348
  code->tree[code->numentries].branches[0] = -1;
Packit Service 1d0348
  code->tree[code->numentries].branches[1] = -2;
Packit Service 1d0348
  return 1;
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
make_table(struct archive_read *a, struct huffman_code *code)
Packit Service 1d0348
{
Packit Service 1d0348
  if (code->maxlength < code->minlength || code->maxlength > 10)
Packit Service 1d0348
    code->tablesize = 10;
Packit Service 1d0348
  else
Packit Service 1d0348
    code->tablesize = code->maxlength;
Packit Service 1d0348
Packit Service 1d0348
  code->table =
Packit Service 1d0348
    (struct huffman_table_entry *)calloc(1, sizeof(*code->table)
Packit Service 1d0348
    * ((size_t)1 << code->tablesize));
Packit Service 1d0348
Packit Service 1d0348
  return make_table_recurse(a, code, 0, code->table, 0, code->tablesize);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
make_table_recurse(struct archive_read *a, struct huffman_code *code, int node,
Packit Service 1d0348
                   struct huffman_table_entry *table, int depth,
Packit Service 1d0348
                   int maxdepth)
Packit Service 1d0348
{
Packit Service 1d0348
  int currtablesize, i, ret = (ARCHIVE_OK);
Packit Service 1d0348
Packit Service 1d0348
  if (!code->tree)
Packit Service 1d0348
  {
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                      "Huffman tree was not created.");
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
  if (node < 0 || node >= code->numentries)
Packit Service 1d0348
  {
Packit Service 1d0348
    archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                      "Invalid location to Huffman tree specified.");
Packit Service 1d0348
    return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  currtablesize = 1 << (maxdepth - depth);
Packit Service 1d0348
Packit Service 1d0348
  if (code->tree[node].branches[0] ==
Packit Service 1d0348
    code->tree[node].branches[1])
Packit Service 1d0348
  {
Packit Service 1d0348
    for(i = 0; i < currtablesize; i++)
Packit Service 1d0348
    {
Packit Service 1d0348
      table[i].length = depth;
Packit Service 1d0348
      table[i].value = code->tree[node].branches[0];
Packit Service 1d0348
    }
Packit Service 1d0348
  }
Packit Service 1d0348
  else if (node < 0)
Packit Service 1d0348
  {
Packit Service 1d0348
    for(i = 0; i < currtablesize; i++)
Packit Service 1d0348
      table[i].length = -1;
Packit Service 1d0348
  }
Packit Service 1d0348
  else
Packit Service 1d0348
  {
Packit Service 1d0348
    if(depth == maxdepth)
Packit Service 1d0348
    {
Packit Service 1d0348
      table[0].length = maxdepth + 1;
Packit Service 1d0348
      table[0].value = node;
Packit Service 1d0348
    }
Packit Service 1d0348
    else
Packit Service 1d0348
    {
Packit Service 1d0348
      ret |= make_table_recurse(a, code, code->tree[node].branches[0], table,
Packit Service 1d0348
                                depth + 1, maxdepth);
Packit Service 1d0348
      ret |= make_table_recurse(a, code, code->tree[node].branches[1],
Packit Service 1d0348
                         table + currtablesize / 2, depth + 1, maxdepth);
Packit Service 1d0348
    }
Packit Service 1d0348
  }
Packit Service 1d0348
  return ret;
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int64_t
Packit Service 1d0348
expand(struct archive_read *a, int64_t end)
Packit Service 1d0348
{
Packit Service 1d0348
  static const unsigned char lengthbases[] =
Packit Service 1d0348
    {   0,   1,   2,   3,   4,   5,   6,
Packit Service 1d0348
        7,   8,  10,  12,  14,  16,  20,
Packit Service 1d0348
       24,  28,  32,  40,  48,  56,  64,
Packit Service 1d0348
       80,  96, 112, 128, 160, 192, 224 };
Packit Service 1d0348
  static const unsigned char lengthbits[] =
Packit Service 1d0348
    { 0, 0, 0, 0, 0, 0, 0,
Packit Service 1d0348
      0, 1, 1, 1, 1, 2, 2,
Packit Service 1d0348
      2, 2, 3, 3, 3, 3, 4,
Packit Service 1d0348
      4, 4, 4, 5, 5, 5, 5 };
Packit Service 1d0348
  static const unsigned int offsetbases[] =
Packit Service 1d0348
    {       0,       1,       2,       3,       4,       6,
Packit Service 1d0348
            8,      12,      16,      24,      32,      48,
Packit Service 1d0348
           64,      96,     128,     192,     256,     384,
Packit Service 1d0348
          512,     768,    1024,    1536,    2048,    3072,
Packit Service 1d0348
         4096,    6144,    8192,   12288,   16384,   24576,
Packit Service 1d0348
        32768,   49152,   65536,   98304,  131072,  196608,
Packit Service 1d0348
       262144,  327680,  393216,  458752,  524288,  589824,
Packit Service 1d0348
       655360,  720896,  786432,  851968,  917504,  983040,
Packit Service 1d0348
      1048576, 1310720, 1572864, 1835008, 2097152, 2359296,
Packit Service 1d0348
      2621440, 2883584, 3145728, 3407872, 3670016, 3932160 };
Packit Service 1d0348
  static const unsigned char offsetbits[] =
Packit Service 1d0348
    {  0,  0,  0,  0,  1,  1,  2,  2,  3,  3,  4,  4,
Packit Service 1d0348
       5,  5,  6,  6,  7,  7,  8,  8,  9,  9, 10, 10,
Packit Service 1d0348
      11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16,
Packit Service 1d0348
      16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
Packit Service 1d0348
      18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18 };
Packit Service 1d0348
  static const unsigned char shortbases[] =
Packit Service 1d0348
    { 0, 4, 8, 16, 32, 64, 128, 192 };
Packit Service 1d0348
  static const unsigned char shortbits[] =
Packit Service 1d0348
    { 2, 2, 3, 4, 5, 6, 6, 6 };
Packit Service 1d0348
Packit Service 1d0348
  int symbol, offs, len, offsindex, lensymbol, i, offssymbol, lowoffsetsymbol;
Packit Service 1d0348
  unsigned char newfile;
Packit Service 1d0348
  struct rar *rar = (struct rar *)(a->format->data);
Packit Service 1d0348
  struct rar_br *br = &(rar->br);
Packit Service 1d0348
Packit Service 1d0348
  if (rar->filterstart < end)
Packit Service 1d0348
    end = rar->filterstart;
Packit Service 1d0348
Packit Service 1d0348
  while (1)
Packit Service 1d0348
  {
Packit Service 1d0348
    if (rar->output_last_match &&
Packit Service 1d0348
      lzss_position(&rar->lzss) + rar->lastlength <= end)
Packit Service 1d0348
    {
Packit Service 1d0348
      lzss_emit_match(rar, rar->lastoffset, rar->lastlength);
Packit Service 1d0348
      rar->output_last_match = 0;
Packit Service 1d0348
    }
Packit Service 1d0348
Packit Service 1d0348
    if(rar->is_ppmd_block || rar->output_last_match ||
Packit Service 1d0348
      lzss_position(&rar->lzss) >= end)
Packit Service 1d0348
      return lzss_position(&rar->lzss);
Packit Service 1d0348
Packit Service 1d0348
    if ((symbol = read_next_symbol(a, &rar->maincode)) < 0)
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
    rar->output_last_match = 0;
Packit Service 1d0348
Packit Service 1d0348
    if (symbol < 256)
Packit Service 1d0348
    {
Packit Service 1d0348
      lzss_emit_literal(rar, symbol);
Packit Service 1d0348
      continue;
Packit Service 1d0348
    }
Packit Service 1d0348
    else if (symbol == 256)
Packit Service 1d0348
    {
Packit Service 1d0348
      if (!rar_br_read_ahead(a, br, 1))
Packit Service 1d0348
        goto truncated_data;
Packit Service 1d0348
      newfile = !rar_br_bits(br, 1);
Packit Service 1d0348
      rar_br_consume(br, 1);
Packit Service 1d0348
Packit Service 1d0348
      if(newfile)
Packit Service 1d0348
      {
Packit Service 1d0348
        rar->start_new_block = 1;
Packit Service 1d0348
        if (!rar_br_read_ahead(a, br, 1))
Packit Service 1d0348
          goto truncated_data;
Packit Service 1d0348
        rar->start_new_table = rar_br_bits(br, 1);
Packit Service 1d0348
        rar_br_consume(br, 1);
Packit Service 1d0348
        return lzss_position(&rar->lzss);
Packit Service 1d0348
      }
Packit Service 1d0348
      else
Packit Service 1d0348
      {
Packit Service 1d0348
        if (parse_codes(a) != ARCHIVE_OK)
Packit Service 1d0348
          return (ARCHIVE_FATAL);
Packit Service 1d0348
        continue;
Packit Service 1d0348
      }
Packit Service 1d0348
    }
Packit Service 1d0348
    else if(symbol==257)
Packit Service 1d0348
    {
Packit Service 1d0348
      archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
                        "Parsing filters is unsupported.");
Packit Service 1d0348
      return (ARCHIVE_FAILED);
Packit Service 1d0348
    }
Packit Service 1d0348
    else if(symbol==258)
Packit Service 1d0348
    {
Packit Service 1d0348
      if(rar->lastlength == 0)
Packit Service 1d0348
        continue;
Packit Service 1d0348
Packit Service 1d0348
      offs = rar->lastoffset;
Packit Service 1d0348
      len = rar->lastlength;
Packit Service 1d0348
    }
Packit Service 1d0348
    else if (symbol <= 262)
Packit Service 1d0348
    {
Packit Service 1d0348
      offsindex = symbol - 259;
Packit Service 1d0348
      offs = rar->oldoffset[offsindex];
Packit Service 1d0348
Packit Service 1d0348
      if ((lensymbol = read_next_symbol(a, &rar->lengthcode)) < 0)
Packit Service 1d0348
        goto bad_data;
Packit Service 1d0348
      if (lensymbol > (int)(sizeof(lengthbases)/sizeof(lengthbases[0])))
Packit Service 1d0348
        goto bad_data;
Packit Service 1d0348
      if (lensymbol > (int)(sizeof(lengthbits)/sizeof(lengthbits[0])))
Packit Service 1d0348
        goto bad_data;
Packit Service 1d0348
      len = lengthbases[lensymbol] + 2;
Packit Service 1d0348
      if (lengthbits[lensymbol] > 0) {
Packit Service 1d0348
        if (!rar_br_read_ahead(a, br, lengthbits[lensymbol]))
Packit Service 1d0348
          goto truncated_data;
Packit Service 1d0348
        len += rar_br_bits(br, lengthbits[lensymbol]);
Packit Service 1d0348
        rar_br_consume(br, lengthbits[lensymbol]);
Packit Service 1d0348
      }
Packit Service 1d0348
Packit Service 1d0348
      for (i = offsindex; i > 0; i--)
Packit Service 1d0348
        rar->oldoffset[i] = rar->oldoffset[i-1];
Packit Service 1d0348
      rar->oldoffset[0] = offs;
Packit Service 1d0348
    }
Packit Service 1d0348
    else if(symbol<=270)
Packit Service 1d0348
    {
Packit Service 1d0348
      offs = shortbases[symbol-263] + 1;
Packit Service 1d0348
      if(shortbits[symbol-263] > 0) {
Packit Service 1d0348
        if (!rar_br_read_ahead(a, br, shortbits[symbol-263]))
Packit Service 1d0348
          goto truncated_data;
Packit Service 1d0348
        offs += rar_br_bits(br, shortbits[symbol-263]);
Packit Service 1d0348
        rar_br_consume(br, shortbits[symbol-263]);
Packit Service 1d0348
      }
Packit Service 1d0348
Packit Service 1d0348
      len = 2;
Packit Service 1d0348
Packit Service 1d0348
      for(i = 3; i > 0; i--)
Packit Service 1d0348
        rar->oldoffset[i] = rar->oldoffset[i-1];
Packit Service 1d0348
      rar->oldoffset[0] = offs;
Packit Service 1d0348
    }
Packit Service 1d0348
    else
Packit Service 1d0348
    {
Packit Service 1d0348
      if (symbol-271 > (int)(sizeof(lengthbases)/sizeof(lengthbases[0])))
Packit Service 1d0348
        goto bad_data;
Packit Service 1d0348
      if (symbol-271 > (int)(sizeof(lengthbits)/sizeof(lengthbits[0])))
Packit Service 1d0348
        goto bad_data;
Packit Service 1d0348
      len = lengthbases[symbol-271]+3;
Packit Service 1d0348
      if(lengthbits[symbol-271] > 0) {
Packit Service 1d0348
        if (!rar_br_read_ahead(a, br, lengthbits[symbol-271]))
Packit Service 1d0348
          goto truncated_data;
Packit Service 1d0348
        len += rar_br_bits(br, lengthbits[symbol-271]);
Packit Service 1d0348
        rar_br_consume(br, lengthbits[symbol-271]);
Packit Service 1d0348
      }
Packit Service 1d0348
Packit Service 1d0348
      if ((offssymbol = read_next_symbol(a, &rar->offsetcode)) < 0)
Packit Service 1d0348
        goto bad_data;
Packit Service 1d0348
      if (offssymbol > (int)(sizeof(offsetbases)/sizeof(offsetbases[0])))
Packit Service 1d0348
        goto bad_data;
Packit Service 1d0348
      if (offssymbol > (int)(sizeof(offsetbits)/sizeof(offsetbits[0])))
Packit Service 1d0348
        goto bad_data;
Packit Service 1d0348
      offs = offsetbases[offssymbol]+1;
Packit Service 1d0348
      if(offsetbits[offssymbol] > 0)
Packit Service 1d0348
      {
Packit Service 1d0348
        if(offssymbol > 9)
Packit Service 1d0348
        {
Packit Service 1d0348
          if(offsetbits[offssymbol] > 4) {
Packit Service 1d0348
            if (!rar_br_read_ahead(a, br, offsetbits[offssymbol] - 4))
Packit Service 1d0348
              goto truncated_data;
Packit Service 1d0348
            offs += rar_br_bits(br, offsetbits[offssymbol] - 4) << 4;
Packit Service 1d0348
            rar_br_consume(br, offsetbits[offssymbol] - 4);
Packit Service 1d0348
	  }
Packit Service 1d0348
Packit Service 1d0348
          if(rar->numlowoffsetrepeats > 0)
Packit Service 1d0348
          {
Packit Service 1d0348
            rar->numlowoffsetrepeats--;
Packit Service 1d0348
            offs += rar->lastlowoffset;
Packit Service 1d0348
          }
Packit Service 1d0348
          else
Packit Service 1d0348
          {
Packit Service 1d0348
            if ((lowoffsetsymbol =
Packit Service 1d0348
              read_next_symbol(a, &rar->lowoffsetcode)) < 0)
Packit Service 1d0348
              return (ARCHIVE_FATAL);
Packit Service 1d0348
            if(lowoffsetsymbol == 16)
Packit Service 1d0348
            {
Packit Service 1d0348
              rar->numlowoffsetrepeats = 15;
Packit Service 1d0348
              offs += rar->lastlowoffset;
Packit Service 1d0348
            }
Packit Service 1d0348
            else
Packit Service 1d0348
            {
Packit Service 1d0348
              offs += lowoffsetsymbol;
Packit Service 1d0348
              rar->lastlowoffset = lowoffsetsymbol;
Packit Service 1d0348
            }
Packit Service 1d0348
          }
Packit Service 1d0348
        }
Packit Service 1d0348
        else {
Packit Service 1d0348
          if (!rar_br_read_ahead(a, br, offsetbits[offssymbol]))
Packit Service 1d0348
            goto truncated_data;
Packit Service 1d0348
          offs += rar_br_bits(br, offsetbits[offssymbol]);
Packit Service 1d0348
          rar_br_consume(br, offsetbits[offssymbol]);
Packit Service 1d0348
        }
Packit Service 1d0348
      }
Packit Service 1d0348
Packit Service 1d0348
      if (offs >= 0x40000)
Packit Service 1d0348
        len++;
Packit Service 1d0348
      if (offs >= 0x2000)
Packit Service 1d0348
        len++;
Packit Service 1d0348
Packit Service 1d0348
      for(i = 3; i > 0; i--)
Packit Service 1d0348
        rar->oldoffset[i] = rar->oldoffset[i-1];
Packit Service 1d0348
      rar->oldoffset[0] = offs;
Packit Service 1d0348
    }
Packit Service 1d0348
Packit Service 1d0348
    rar->lastoffset = offs;
Packit Service 1d0348
    rar->lastlength = len;
Packit Service 1d0348
    rar->output_last_match = 1;
Packit Service 1d0348
  }
Packit Service 1d0348
truncated_data:
Packit Service 1d0348
  archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                    "Truncated RAR file data");
Packit Service 1d0348
  rar->valid = 0;
Packit Service 1d0348
  return (ARCHIVE_FATAL);
Packit Service 1d0348
bad_data:
Packit Service 1d0348
  archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                    "Bad RAR file data");
Packit Service 1d0348
  return (ARCHIVE_FATAL);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
copy_from_lzss_window(struct archive_read *a, const void **buffer,
Packit Service 1d0348
                        int64_t startpos, int length)
Packit Service 1d0348
{
Packit Service 1d0348
  int windowoffs, firstpart;
Packit Service 1d0348
  struct rar *rar = (struct rar *)(a->format->data);
Packit Service 1d0348
Packit Service 1d0348
  if (!rar->unp_buffer)
Packit Service 1d0348
  {
Packit Service 1d0348
    if ((rar->unp_buffer = malloc(rar->unp_buffer_size)) == NULL)
Packit Service 1d0348
    {
Packit Service 1d0348
      archive_set_error(&a->archive, ENOMEM,
Packit Service 1d0348
                        "Unable to allocate memory for uncompressed data.");
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
    }
Packit Service 1d0348
  }
Packit Service 1d0348
Packit Service 1d0348
  windowoffs = lzss_offset_for_position(&rar->lzss, startpos);
Packit Service 1d0348
  if(windowoffs + length <= lzss_size(&rar->lzss)) {
Packit Service 1d0348
    memcpy(&rar->unp_buffer[rar->unp_offset], &rar->lzss.window[windowoffs],
Packit Service 1d0348
           length);
Packit Service 1d0348
  } else if (length <= lzss_size(&rar->lzss)) {
Packit Service 1d0348
    firstpart = lzss_size(&rar->lzss) - windowoffs;
Packit Service 1d0348
    if (firstpart < 0) {
Packit Service 1d0348
      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                        "Bad RAR file data");
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
    }
Packit Service 1d0348
    if (firstpart < length) {
Packit Service 1d0348
      memcpy(&rar->unp_buffer[rar->unp_offset],
Packit Service 1d0348
             &rar->lzss.window[windowoffs], firstpart);
Packit Service 1d0348
      memcpy(&rar->unp_buffer[rar->unp_offset + firstpart],
Packit Service 1d0348
             &rar->lzss.window[0], length - firstpart);
Packit Service 1d0348
    } else {
Packit Service 1d0348
      memcpy(&rar->unp_buffer[rar->unp_offset],
Packit Service 1d0348
             &rar->lzss.window[windowoffs], length);
Packit Service 1d0348
    }
Packit Service 1d0348
  } else {
Packit Service 1d0348
      archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
Packit Service 1d0348
                        "Bad RAR file data");
Packit Service 1d0348
      return (ARCHIVE_FATAL);
Packit Service 1d0348
  }
Packit Service 1d0348
  rar->unp_offset += length;
Packit Service 1d0348
  if (rar->unp_offset >= rar->unp_buffer_size)
Packit Service 1d0348
    *buffer = rar->unp_buffer;
Packit Service 1d0348
  else
Packit Service 1d0348
    *buffer = NULL;
Packit Service 1d0348
  return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static const void *
Packit Service 1d0348
rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
Packit Service 1d0348
{
Packit Service 1d0348
  struct rar *rar = (struct rar *)(a->format->data);
Packit Service 1d0348
  const void *h = __archive_read_ahead(a, min, avail);
Packit Service 1d0348
  int ret;
Packit Service 1d0348
  if (avail)
Packit Service 1d0348
  {
Packit Service 1d0348
    if (a->archive.read_data_is_posix_read && *avail > (ssize_t)a->archive.read_data_requested)
Packit Service 1d0348
      *avail = a->archive.read_data_requested;
Packit Service 1d0348
    if (*avail > rar->bytes_remaining)
Packit Service 1d0348
      *avail = (ssize_t)rar->bytes_remaining;
Packit Service 1d0348
    if (*avail < 0)
Packit Service 1d0348
      return NULL;
Packit Service 1d0348
    else if (*avail == 0 && rar->main_flags & MHD_VOLUME &&
Packit Service 1d0348
      rar->file_flags & FHD_SPLIT_AFTER)
Packit Service 1d0348
    {
Packit Service 1d0348
      ret = archive_read_format_rar_read_header(a, a->entry);
Packit Service 1d0348
      if (ret == (ARCHIVE_EOF))
Packit Service 1d0348
      {
Packit Service 1d0348
        rar->has_endarc_header = 1;
Packit Service 1d0348
        ret = archive_read_format_rar_read_header(a, a->entry);
Packit Service 1d0348
      }
Packit Service 1d0348
      if (ret != (ARCHIVE_OK))
Packit Service 1d0348
        return NULL;
Packit Service 1d0348
      return rar_read_ahead(a, min, avail);
Packit Service 1d0348
    }
Packit Service 1d0348
  }
Packit Service 1d0348
  return h;
Packit Service 1d0348
}