Skip to content

Commit f99470b

Browse files
committed
unknown fields in conan exiles inline data record!
1 parent 16bf756 commit f99470b

File tree

5 files changed

+54
-23
lines changed

5 files changed

+54
-23
lines changed

README.md

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -145,27 +145,19 @@ if version <= 1
145145
end
146146
? 20 uint8_t[20] data sha1 hash
147147
if version >= 3
148-
if compression method != 0x00
148+
if compression_method != 0x00
149149
?+20 4 uint32_t block count (M)
150150
?+24 M*16 CB[M] compression blocks
151151
end
152152
? 1 uint8_t is encrypted
153153
?+1 4 uint32_t The uncompressed size of each compression block.
154154
end The last block can be smaller, of course.
155-
if variant == "Conan Exiles" or (version >= 4 and is data record)
156-
? 4 uint32_t Unknown field. For Conan Exiles only seen it to have
157-
the value 0.
155+
if variant == "Conan Exiles"
156+
? 4 uint32_t Unknown field. For Conan Exiles index record only
157+
seen it to have the value 0.
158158
end
159159
```
160160

161-
**NOTE:** Starting with version 4 there is an additional 4 bytes in the repeated
162-
*inline* record copy (the record that precedes the actual file date, not the
163-
record in the index). I don't know what that is. It is not always the same value.
164-
E.g. it is the same for some files, but different for others. The last 2 bytes
165-
are more often the same than the whole 4 bytes.
166-
167-
This is why I've deactivated packing for versions > 3.
168-
169161
### Compression Block (CB)
170162

171163
Size: 16 bytes
@@ -188,16 +180,35 @@ Offset Size Type Description
188180
```plain
189181
Offset Size Type Description
190182
0 ? Record file metadata (offset field is 0, N = compressed_size)
183+
if variant == "Conan Exiles"
184+
? 20 ? Unknown. Maybe another SHA-1 sum of something?
185+
The first 4 bytes have values other than the extra
186+
4 bytes in the index record, which is why I didn't
187+
put those into the general record structure.
188+
else if version >= 4
189+
? 4 uint32_t Unknown.
190+
end
191191
? N uint8_t[N] file data
192192
```
193193

194+
**NOTE:** Starting with version 4 there is an additional 4 bytes in the repeated
195+
*data* record copy (the record that precedes the actual file date, not the
196+
record in the index). I don't know what that is. It is not always the same value.
197+
E.g. it is the same for some files, but different for others. The last 2 bytes
198+
are more often the same than the whole 4 bytes.
199+
200+
This is why I've deactivated packing for versions > 3.
201+
194202
### Index Record
195203

196204
```plain
197205
Offset Size Type Description
198206
0 4 uint32_t file name size (S)
199207
4 S char[S] file name (includes terminating null byte)
200208
4+S ? Record file metadata
209+
if variant == "Conan Exiles"
210+
? 4 ? Unknown. Only saw all 0 so far.
211+
end
201212
```
202213

203214
### Index

src/check.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use openssl::sha::Sha1 as OpenSSLSha1;
2222
use crate::{Error, Filter, Pak, pak::{BUFFER_SIZE, COMPR_METHODS, COMPR_NONE, HexDisplay, Sha1, Variant}};
2323
use crate::reopen::Reopen;
2424
use crate::{Record, Result};
25+
//use crate::{decode, decode::Decode};
2526

2627
pub const NULL_SHA1: Sha1 = [0u8; 20];
2728

@@ -218,6 +219,14 @@ pub fn check<'a>(pak: &'a Pak, in_file: &mut File, options: CheckOptions) -> Res
218219
check_error!(ok, result_sender, abort_on_error, error);
219220
}
220221
};
222+
//if version >= 4 {
223+
// let mut f = || -> Result<()> {
224+
// decode!(&mut reader, unknown: u32);
225+
// println!(">>> {:20} {:15x} {}", unknown, unknown, record.filename());
226+
// Ok(())
227+
// };
228+
// let _ = f();
229+
//}
221230
}
222231

223232
if let Some(blocks) = record.compression_blocks() {
@@ -228,8 +237,12 @@ pub fn check<'a>(pak: &'a Pak, in_file: &mut File, options: CheckOptions) -> Res
228237
let base_offset;
229238
let mut next_start_offset;
230239

231-
// + 4 for unknown extra field in inline record
232-
if version >= 7 {
240+
if variant == Variant::ConanExiles {
241+
// only version 4 is correctly supported
242+
base_offset = 0;
243+
next_start_offset = record.offset() + header_size + 20;
244+
} else if version >= 7 {
245+
// + 4 for unknown extra field in inline record
233246
base_offset = record.offset();
234247
next_start_offset = header_size + 4;
235248
} else if version >= 4 {

src/pack.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,18 @@ impl Default for PackOptions<'_> {
160160
pub fn pack(pak_path: impl AsRef<Path>, paths: &[PackPath], options: PackOptions) -> Result<Pak> {
161161
let write_record_inline = match options.variant {
162162
Variant::ConanExiles => {
163-
if options.version != 4 {
164-
return Err(Error::new(format!(
165-
"Only know how to handle Conan Exile paks of version 4, but version was {}.",
166-
options.version)).
167-
with_path(pak_path));
168-
}
169-
Record::write_conan_exiles_inline
163+
return Err(Error::new("Writing of Conan Exile paks is not supported.".to_string()).
164+
with_path(pak_path));
165+
// XXX: There a are 20 unknown bytes after the inline record information if compressed.
166+
// That is 16 extra to the already 4 extra bytes in standard version >= 4.
167+
// In the index record there are only 4 extra bytes that are always 0.
168+
//if options.version != 4 {
169+
// return Err(Error::new(format!(
170+
// "Only know how to handle Conan Exile paks of version 4, but version was {}.",
171+
// options.version)).
172+
// with_path(pak_path));
173+
//}
174+
//Record::write_conan_exiles_inline
170175
}
171176
Variant::Standard => match options.version {
172177
1 => Record::write_v1_inline,

src/pak.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ impl Pak {
354354
// filter.filter(self.records.iter())
355355
//}
356356

357+
// FIXME: inline header has different size in some versions/variants!
357358
pub fn header_size(version: u32, variant: Variant, record: &Record) -> u64 {
358359
match variant {
359360
Variant::ConanExiles => {

src/record.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
use std::io::{Read, Write};
1717
use std::fmt::Write as FmtWrite;
1818

19-
use crate::pak::{COMPR_NONE, HexDisplay, Sha1};
19+
use crate::{check::NULL_SHA1, pak::{COMPR_NONE, HexDisplay, Sha1}};
2020
use crate::decode;
2121
use crate::decode::Decode;
2222
use crate::encode;
@@ -346,7 +346,8 @@ impl Record {
346346
}
347347
self.encrypted as u8,
348348
self.compression_block_size,
349-
0u32,
349+
// there are suppodes to be 20 more bytes of something that I don't know:
350+
NULL_SHA1,
350351
);
351352
Ok(())
352353
}

0 commit comments

Comments
 (0)