Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
rar.c File Reference
#include "rar.h"
+ Include dependency graph for rar.c:

Go to the source code of this file.

Functions

static void rar_close (ar_archive *ar)
 
static bool rar_parse_entry (ar_archive *ar, off64_t offset)
 
static bool rar_copy_stored (ar_archive_rar *rar, void *buffer, size_t count)
 
static bool rar_restart_solid (ar_archive *ar)
 
static bool rar_uncompress (ar_archive *ar, void *buffer, size_t count)
 
ar_archivear_open_rar_archive (ar_stream *stream)
 

Function Documentation

ar_archive* ar_open_rar_archive ( ar_stream stream)

Definition at line 205 of file rar.c.

206 {
207  char signature[FILE_SIGNATURE_SIZE];
208  if (!ar_seek(stream, 0, SEEK_SET))
209  return NULL;
210  if (ar_read(stream, signature, sizeof(signature)) != sizeof(signature))
211  return NULL;
212  if (memcmp(signature, "Rar!\x1A\x07\x00", sizeof(signature)) != 0) {
213  if (memcmp(signature, "Rar!\x1A\x07\x01", sizeof(signature)) == 0)
214  warn("RAR 5 format isn't supported");
215  else if (memcmp(signature, "RE~^", 4) == 0)
216  warn("Ancient RAR format isn't supported");
217  else if (memcmp(signature, "MZ", 2) == 0 || memcmp(signature, "\x7F\x45LF", 4) == 0)
218  warn("SFX archives aren't supported");
219  return NULL;
220  }
221 
223 }

+ Here is the caller graph for this function:

static void rar_close ( ar_archive ar)
static

Definition at line 6 of file rar.c.

7 {
8  ar_archive_rar *rar = (ar_archive_rar *)ar;
9  free(rar->entry.name);
11 }

+ Here is the caller graph for this function:

static bool rar_copy_stored ( ar_archive_rar rar,
void *  buffer,
size_t  count 
)
static

Definition at line 120 of file rar.c.

121 {
122  if (count > rar->progress.data_left) {
123  warn("Unexpected EOS in stored data");
124  return false;
125  }
126  if (ar_read(rar->super.stream, buffer, count) != count) {
127  warn("Unexpected EOF in stored data");
128  return false;
129  }
130  rar->progress.data_left -= count;
131  rar->progress.bytes_done += count;
132  return true;
133 }

+ Here is the caller graph for this function:

static bool rar_parse_entry ( ar_archive ar,
off64_t  offset 
)
static

Definition at line 13 of file rar.c.

14 {
15  ar_archive_rar *rar = (ar_archive_rar *)ar;
16  struct rar_header header;
17  struct rar_entry entry;
18  bool out_of_order = offset != ar->entry_offset_next;
19 
20  if (!ar_seek(ar->stream, offset, SEEK_SET)) {
21  warn("Couldn't seek to offset %" PRIi64, offset);
22  return false;
23  }
24 
25  for (;;) {
26  ar->entry_offset = ar_tell(ar->stream);
28 
29  if (!rar_parse_header(ar, &header))
30  return false;
31 
32  ar->entry_offset_next = ar->entry_offset + header.size + header.datasize;
33  if (ar->entry_offset_next < ar->entry_offset + header.size) {
34  warn("Integer overflow due to overly large data size");
35  return false;
36  }
37 
38  switch (header.type) {
39  case TYPE_MAIN_HEADER:
40  if ((header.flags & MHD_PASSWORD)) {
41  warn("Encrypted archives aren't supported");
42  return false;
43  }
44  ar_skip(ar->stream, 6 /* reserved data */);
45  if ((header.flags & MHD_ENCRYPTVER)) {
46  log("MHD_ENCRYPTVER is set");
47  ar_skip(ar->stream, 1);
48  }
49  if ((header.flags & MHD_COMMENT))
50  log("MHD_COMMENT is set");
51  if (ar_tell(ar->stream) - ar->entry_offset > header.size) {
52  warn("Invalid RAR header size: %d", header.size);
53  return false;
54  }
55  rar->archive_flags = header.flags;
56  break;
57 
58  case TYPE_FILE_ENTRY:
59  if (!rar_parse_header_entry(rar, &header, &entry))
60  return false;
61  if ((header.flags & LHD_PASSWORD))
62  warn("Encrypted entries will fail to uncompress");
63  if ((header.flags & LHD_DIRECTORY) == LHD_DIRECTORY) {
64  if (header.datasize == 0) {
65  log("Skipping directory entry \"%s\"", rar_get_name(ar));
66  break;
67  }
68  warn("Can't skip directory entries containing data");
69  }
70  if ((header.flags & (LHD_SPLIT_BEFORE | LHD_SPLIT_AFTER)))
71  warn("Splitting files isn't really supported");
72  ar->entry_size_uncompressed = (size_t)entry.size;
73  ar->entry_filetime = ar_conv_dosdate_to_filetime(entry.dosdate);
74  if (!rar->entry.solid || rar->entry.method == METHOD_STORE || out_of_order) {
76  memset(&rar->solid, 0, sizeof(rar->solid));
77  }
78  else {
80  }
81 
82  rar->solid.restart = rar->entry.solid && (out_of_order || !rar->solid.part_done);
84  rar->progress.data_left = (size_t)header.datasize;
85  rar->progress.bytes_done = 0;
86  rar->progress.crc = 0;
87 
88  /* TODO: CRC checks don't always hold (claim in XADRARParser.m @readBlockHeader) */
89  if (!rar_check_header_crc(ar))
90  warn("Invalid header checksum @%" PRIi64, ar->entry_offset);
91  if (ar_tell(ar->stream) != ar->entry_offset + rar->entry.header_size) {
92  warn("Couldn't seek to offset %" PRIi64, ar->entry_offset + rar->entry.header_size);
93  return false;
94  }
95  return true;
96 
97  case TYPE_NEWSUB:
98  log("Skipping newsub header @%" PRIi64, ar->entry_offset);
99  break;
100 
101  case TYPE_END_OF_ARCHIVE:
102  ar->at_eof = true;
103  return false;
104 
105  default:
106  log("Unknown RAR header type %02x", header.type);
107  break;
108  }
109 
110  /* TODO: CRC checks don't always hold (claim in XADRARParser.m @readBlockHeader) */
111  if (!rar_check_header_crc(ar))
112  warn("Invalid header checksum @%" PRIi64, ar->entry_offset);
113  if (!ar_seek(ar->stream, ar->entry_offset_next, SEEK_SET)) {
114  warn("Couldn't seek to offset %" PRIi64, ar->entry_offset_next);
115  return false;
116  }
117  }
118 }

+ Here is the caller graph for this function:

static bool rar_restart_solid ( ar_archive ar)
static

Definition at line 135 of file rar.c.

136 {
137  ar_archive_rar *rar = (ar_archive_rar *)ar;
138  off64_t current_offset = ar->entry_offset;
139  log("Restarting decompression for solid entry");
140  if (!ar_parse_entry_at(ar, ar->entry_offset_first)) {
141  ar_parse_entry_at(ar, current_offset);
142  return false;
143  }
144  while (ar->entry_offset < current_offset) {
145  size_t size = ar->entry_size_uncompressed;
146  rar->solid.restart = false;
147  while (size > 0) {
148  unsigned char buffer[1024];
149  size_t count = smin(size, sizeof(buffer));
150  if (!ar_entry_uncompress(ar, buffer, count)) {
151  ar_parse_entry_at(ar, current_offset);
152  return false;
153  }
154  size -= count;
155  }
156  if (!ar_parse_entry(ar)) {
157  ar_parse_entry_at(ar, current_offset);
158  return false;
159  }
160  }
161  rar->solid.restart = false;
162  return true;
163 }

+ Here is the caller graph for this function:

static bool rar_uncompress ( ar_archive ar,
void *  buffer,
size_t  count 
)
static

Definition at line 165 of file rar.c.

166 {
167  ar_archive_rar *rar = (ar_archive_rar *)ar;
168  if (count > ar->entry_size_uncompressed - rar->progress.bytes_done) {
169  warn("Requesting too much data (%" PRIuPTR " < %" PRIuPTR ")", ar->entry_size_uncompressed - rar->progress.bytes_done, count);
170  return false;
171  }
172  if (rar->entry.method == METHOD_STORE) {
173  if (!rar_copy_stored(rar, buffer, count))
174  return false;
175  }
176  else if (rar->entry.method == METHOD_FASTEST || rar->entry.method == METHOD_FAST ||
177  rar->entry.method == METHOD_NORMAL || rar->entry.method == METHOD_GOOD ||
178  rar->entry.method == METHOD_BEST) {
179  if (rar->solid.restart && !rar_restart_solid(ar)) {
180  warn("Failed to produce the required solid decompression state");
181  return false;
182  }
183  if (!rar_uncompress_part(rar, buffer, count))
184  return false;
185  }
186  else {
187  warn("Unknown compression method %#02x", rar->entry.method);
188  return false;
189  }
190 
191  rar->progress.crc = ar_crc32(rar->progress.crc, buffer, count);
193  return true;
194  if (rar->progress.data_left)
195  log("Compressed block has more data than required");
196  rar->solid.part_done = true;
197  rar->solid.size_total += rar->progress.bytes_done;
198  if (rar->progress.crc != rar->entry.crc) {
199  warn("Checksum of extracted data doesn't match");
200  return false;
201  }
202  return true;
203 }

+ Here is the caller graph for this function: