Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
d26d804c
Commit
d26d804c
authored
Nov 21, 2019
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Migrate to generic stream implementation
parent
4f9a25ee
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
634 additions
and
756 deletions
+634
-756
bootimg.cpp
native/jni/magiskboot/bootimg.cpp
+9
-10
compress.cpp
native/jni/magiskboot/compress.cpp
+565
-443
compress.h
native/jni/magiskboot/compress.h
+2
-166
ramdisk.cpp
native/jni/magiskboot/ramdisk.cpp
+18
-14
cpio.cpp
native/jni/utils/cpio.cpp
+8
-8
cpio.h
native/jni/utils/include/cpio.h
+3
-3
stream.h
native/jni/utils/include/stream.h
+10
-112
stream.cpp
native/jni/utils/stream.cpp
+19
-0
No files found.
native/jni/magiskboot/bootimg.cpp
View file @
d26d804c
...
...
@@ -21,19 +21,18 @@ using namespace std;
uint32_t
dyn_img_hdr
::
j32
=
0
;
uint64_t
dyn_img_hdr
::
j64
=
0
;
static
int64_t
one_step
(
unique_ptr
<
Compression
>
&&
ptr
,
int
fd
,
const
void
*
in
,
size_t
size
)
{
ptr
->
setOut
(
make_unique
<
FDOutStream
>
(
fd
));
if
(
!
ptr
->
write
(
in
,
size
))
return
-
1
;
return
ptr
->
finalize
();
}
static
int64_t
decompress
(
format_t
type
,
int
fd
,
const
void
*
in
,
size_t
size
)
{
return
one_step
(
unique_ptr
<
Compression
>
(
get_decoder
(
type
)),
fd
,
in
,
size
);
static
void
decompress
(
format_t
type
,
int
fd
,
const
void
*
in
,
size_t
size
)
{
unique_ptr
<
stream
>
ptr
(
get_decoder
(
type
,
open_stream
<
fd_stream
>
(
fd
)));
ptr
->
write
(
in
,
size
);
}
static
int64_t
compress
(
format_t
type
,
int
fd
,
const
void
*
in
,
size_t
size
)
{
return
one_step
(
unique_ptr
<
Compression
>
(
get_encoder
(
type
)),
fd
,
in
,
size
);
auto
prev
=
lseek
(
fd
,
0
,
SEEK_CUR
);
unique_ptr
<
stream
>
ptr
(
get_encoder
(
type
,
open_stream
<
fd_stream
>
(
fd
)));
ptr
->
write
(
in
,
size
);
ptr
->
close
();
auto
now
=
lseek
(
fd
,
0
,
SEEK_CUR
);
return
now
-
prev
;
}
static
void
dump
(
void
*
buf
,
size_t
size
,
const
char
*
filename
)
{
...
...
native/jni/magiskboot/compress.cpp
View file @
d26d804c
...
...
@@ -6,6 +6,13 @@
#include <memory>
#include <functional>
#include <zlib.h>
#include <bzlib.h>
#include <lzma.h>
#include <lz4.h>
#include <lz4frame.h>
#include <lz4hc.h>
#include <logging.h>
#include <utils.h>
...
...
@@ -14,524 +21,639 @@
using
namespace
std
;
static
bool
read_file
(
FILE
*
fp
,
const
function
<
void
(
void
*
,
size_t
)
>
&
fn
)
{
char
buf
[
4096
];
size_t
len
;
while
((
len
=
fread
(
buf
,
1
,
sizeof
(
buf
),
fp
)))
fn
(
buf
,
len
);
return
true
;
}
#define bwrite filter_stream::write
#define bclose filter_stream::close
void
decompress
(
char
*
infile
,
const
char
*
outfile
)
{
bool
in_std
=
strcmp
(
infile
,
"-"
)
==
0
;
bool
rm_in
=
false
;
constexpr
size_t
CHUNK
=
0x40000
;
constexpr
size_t
LZ4_UNCOMPRESSED
=
0x80000
0
;
constexpr
size_t
LZ4_COMPRESSED
=
LZ4_COMPRESSBOUND
(
LZ4_UNCOMPRESSED
)
;
FILE
*
in_file
=
in_std
?
stdin
:
xfopen
(
infile
,
"re"
);
int
out_fd
=
-
1
;
unique_ptr
<
Compression
>
cmp
;
class
cpr_stream
:
public
filter_stream
{
public
:
explicit
cpr_stream
(
FILE
*
fp
)
:
filter_stream
(
fp
)
{}
read_file
(
in_file
,
[
&
](
void
*
buf
,
size_t
len
)
->
void
{
if
(
out_fd
<
0
)
{
format_t
type
=
check_fmt
(
buf
,
len
);
int
read
(
void
*
buf
,
size_t
len
)
final
{
return
stream
::
read
(
buf
,
len
);
}
fprintf
(
stderr
,
"Detected format: [%s]
\n
"
,
fmt2name
[
type
]);
int
close
()
final
{
finish
();
return
bclose
();
}
if
(
!
COMPRESSED
(
type
))
LOGE
(
"Input file is not a supported compressed type!
\n
"
);
protected
:
// If finish is overridden, destroy should be called in the destructor
virtual
void
finish
()
{}
void
destroy
()
{
if
(
fp
)
finish
();
}
};
cmp
.
reset
(
get_decoder
(
type
));
class
gz_strm
:
public
cpr_stream
{
public
:
~
gz_strm
()
override
{
destroy
();
}
/* If user does not provide outfile, infile has to be either
* <path>.[ext], or '-'. Outfile will be either <path> or '-'.
* If the input does not have proper format, abort */
int
write
(
const
void
*
buf
,
size_t
len
)
override
{
return
len
?
write
(
buf
,
len
,
Z_NO_FLUSH
)
:
0
;
}
char
*
ext
=
nullptr
;
if
(
outfile
==
nullptr
)
{
outfile
=
infile
;
if
(
!
in_std
)
{
ext
=
strrchr
(
infile
,
'.'
);
if
(
ext
==
nullptr
||
strcmp
(
ext
,
fmt2ext
[
type
])
!=
0
)
LOGE
(
"Input file is not a supported type!
\n
"
);
protected
:
enum
mode_t
{
DECODE
,
ENCODE
}
mode
;
// Strip out extension and remove input
*
ext
=
'\0'
;
rm_in
=
true
;
fprintf
(
stderr
,
"Decompressing to [%s]
\n
"
,
outfile
);
}
}
gz_strm
(
mode_t
mode
,
FILE
*
fp
)
:
cpr_stream
(
fp
),
mode
(
mode
)
{
switch
(
mode
)
{
case
DECODE
:
inflateInit2
(
&
strm
,
15
|
16
);
break
;
case
ENCODE
:
deflateInit2
(
&
strm
,
9
,
Z_DEFLATED
,
15
|
16
,
8
,
Z_DEFAULT_STRATEGY
);
break
;
}
}
out_fd
=
strcmp
(
outfile
,
"-"
)
==
0
?
STDOUT_FILENO
:
xopen
(
outfile
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
0644
);
cmp
->
setOut
(
make_unique
<
FDOutStream
>
(
out_fd
));
if
(
ext
)
*
ext
=
'.'
;
void
finish
()
override
{
write
(
nullptr
,
0
,
Z_FINISH
);
switch
(
mode
)
{
case
DECODE
:
inflateEnd
(
&
strm
);
break
;
case
ENCODE
:
deflateEnd
(
&
strm
);
break
;
}
if
(
!
cmp
->
write
(
buf
,
len
))
LOGE
(
"Decompression error!
\n
"
);
});
}
cmp
->
finalize
();
fclose
(
in_file
);
close
(
out_fd
);
private
:
z_stream
strm
;
uint8_t
outbuf
[
CHUNK
];
int
write
(
const
void
*
buf
,
size_t
len
,
int
flush
)
{
strm
.
next_in
=
(
Bytef
*
)
buf
;
strm
.
avail_in
=
len
;
do
{
int
code
;
strm
.
next_out
=
outbuf
;
strm
.
avail_out
=
sizeof
(
outbuf
);
switch
(
mode
)
{
case
DECODE
:
code
=
inflate
(
&
strm
,
flush
);
break
;
case
ENCODE
:
code
=
deflate
(
&
strm
,
flush
);
break
;
}
if
(
code
==
Z_STREAM_ERROR
)
{
LOGW
(
"gzip %s failed (%d)
\n
"
,
mode
?
"encode"
:
"decode"
,
code
);
return
-
1
;
}
bwrite
(
outbuf
,
sizeof
(
outbuf
)
-
strm
.
avail_out
);
}
while
(
strm
.
avail_out
==
0
);
return
len
;
}
};
if
(
rm_in
)
unlink
(
infile
);
}
class
gz_decoder
:
public
gz_strm
{
public
:
explicit
gz_decoder
(
FILE
*
fp
)
:
gz_strm
(
DECODE
,
fp
)
{};
};
void
compress
(
const
char
*
method
,
const
char
*
infile
,
const
char
*
outfile
)
{
auto
it
=
name2fmt
.
find
(
method
);
if
(
it
==
name2fmt
.
end
())
LOGE
(
"Unsupported compression method: [%s]
\n
"
,
method
)
;
class
gz_encoder
:
public
gz_strm
{
public
:
explicit
gz_encoder
(
FILE
*
fp
)
:
gz_strm
(
ENCODE
,
fp
)
{};
}
;
unique_ptr
<
Compression
>
cmp
(
get_encoder
(
it
->
second
));
class
bz_strm
:
public
cpr_stream
{
public
:
~
bz_strm
()
override
{
destroy
();
}
bool
in_std
=
strcmp
(
infile
,
"-"
)
==
0
;
bool
rm_in
=
false
;
int
write
(
const
void
*
buf
,
size_t
len
)
override
{
return
len
?
write
(
buf
,
len
,
BZ_RUN
)
:
0
;
}
FILE
*
in_file
=
in_std
?
stdin
:
xfopen
(
infile
,
"re"
);
int
out_fd
;
protected
:
enum
mode_t
{
DECODE
,
ENCODE
}
mode
;
if
(
outfile
==
nullptr
)
{
if
(
in_std
)
{
out_fd
=
STDOUT_FILENO
;
}
else
{
/* If user does not provide outfile and infile is not
* STDIN, output to <infile>.[ext] */
char
*
tmp
=
new
char
[
strlen
(
infile
)
+
5
];
sprintf
(
tmp
,
"%s%s"
,
infile
,
fmt2ext
[
it
->
second
]);
out_fd
=
xopen
(
tmp
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
0644
);
fprintf
(
stderr
,
"Compressing to [%s]
\n
"
,
tmp
);
delete
[]
tmp
;
rm_in
=
true
;
bz_strm
(
mode_t
mode
,
FILE
*
fp
)
:
cpr_stream
(
fp
),
mode
(
mode
)
{
switch
(
mode
)
{
case
DECODE
:
BZ2_bzDecompressInit
(
&
strm
,
0
,
0
);
break
;
case
ENCODE
:
BZ2_bzCompressInit
(
&
strm
,
9
,
0
,
0
);
break
;
}
}
else
{
out_fd
=
strcmp
(
outfile
,
"-"
)
==
0
?
STDOUT_FILENO
:
xopen
(
outfile
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
0644
);
}
cmp
->
setOut
(
make_unique
<
FDOutStream
>
(
out_fd
));
void
finish
()
override
{
switch
(
mode
)
{
case
DECODE
:
BZ2_bzDecompressEnd
(
&
strm
);
break
;
case
ENCODE
:
write
(
nullptr
,
0
,
BZ_FINISH
);
BZ2_bzCompressEnd
(
&
strm
);
break
;
}
}
read_file
(
in_file
,
[
&
](
void
*
buf
,
size_t
len
)
->
void
{
if
(
!
cmp
->
write
(
buf
,
len
))
LOGE
(
"Compression error!
\n
"
);
});
private
:
bz_stream
strm
;
char
outbuf
[
CHUNK
];
int
write
(
const
void
*
buf
,
size_t
len
,
int
flush
)
{
strm
.
next_in
=
(
char
*
)
buf
;
strm
.
avail_in
=
len
;
do
{
int
code
;
strm
.
avail_out
=
sizeof
(
outbuf
);
strm
.
next_out
=
outbuf
;
switch
(
mode
)
{
case
DECODE
:
code
=
BZ2_bzDecompress
(
&
strm
);
break
;
case
ENCODE
:
code
=
BZ2_bzCompress
(
&
strm
,
flush
);
break
;
}
if
(
code
<
0
)
{
LOGW
(
"bzip2 %s failed (%d)
\n
"
,
mode
?
"encode"
:
"decode"
,
code
);
return
-
1
;
}
bwrite
(
outbuf
,
sizeof
(
outbuf
)
-
strm
.
avail_out
);
}
while
(
strm
.
avail_out
==
0
);
return
len
;
}
};
cmp
->
finalize
();
fclose
(
in_file
);
close
(
out_fd
);
class
bz_decoder
:
public
bz_strm
{
public
:
explicit
bz_decoder
(
FILE
*
fp
)
:
bz_strm
(
DECODE
,
fp
)
{};
};
if
(
rm_in
)
unlink
(
infile
);
}
class
bz_encoder
:
public
bz_strm
{
public
:
explicit
bz_encoder
(
FILE
*
fp
)
:
bz_strm
(
ENCODE
,
fp
)
{};
};
Compression
*
get_encoder
(
format_t
type
)
{
switch
(
type
)
{
case
XZ
:
return
new
XZEncoder
();
case
LZMA
:
return
new
LZMAEncoder
();
case
BZIP2
:
return
new
BZEncoder
();
case
LZ4
:
return
new
LZ4FEncoder
();
case
LZ4_LEGACY
:
return
new
LZ4Encoder
();
case
GZIP
:
default:
return
new
GZEncoder
();
}
}
class
lzma_strm
:
public
cpr_stream
{
public
:
~
lzma_strm
()
override
{
destroy
();
}
Compression
*
get_decoder
(
format_t
type
)
{
switch
(
type
)
{
case
XZ
:
case
LZMA
:
return
new
LZMADecoder
();
case
BZIP2
:
return
new
BZDecoder
();
case
LZ4
:
return
new
LZ4FDecoder
();
case
LZ4_LEGACY
:
return
new
LZ4Decoder
();
case
GZIP
:
default:
return
new
GZDecoder
();
int
write
(
const
void
*
buf
,
size_t
len
)
override
{
return
len
?
write
(
buf
,
len
,
LZMA_RUN
)
:
0
;
}
}
GZStream
::
GZStream
(
int
mode
)
:
mode
(
mode
),
strm
({})
{
switch
(
mode
)
{
case
0
:
inflateInit2
(
&
strm
,
15
|
16
);
break
;
case
1
:
deflateInit2
(
&
strm
,
9
,
Z_DEFLATED
,
15
|
16
,
8
,
Z_DEFAULT_STRATEGY
);
break
;
}
}
protected
:
enum
mode_t
{
DECODE
,
ENCODE_XZ
,
ENCODE_LZMA
}
mode
;
bool
GZStream
::
write
(
const
void
*
in
,
size_t
size
)
{
return
size
?
write
(
in
,
size
,
Z_NO_FLUSH
)
:
true
;
}
lzma_strm
(
mode_t
mode
,
FILE
*
fp
)
:
cpr_stream
(
fp
),
mode
(
mode
),
strm
(
LZMA_STREAM_INIT
)
{
lzma_options_lzma
opt
;
uint64_t
GZStream
::
finalize
()
{
write
(
nullptr
,
0
,
Z_FINISH
);
uint64_t
total
=
strm
.
total_out
;
switch
(
mode
)
{
case
0
:
inflateEnd
(
&
strm
);
break
;
case
1
:
deflateEnd
(
&
strm
);
break
;
}
return
total
;
}
// Initialize preset
lzma_lzma_preset
(
&
opt
,
9
);
lzma_filter
filters
[]
=
{
{
.
id
=
LZMA_FILTER_LZMA2
,
.
options
=
&
opt
},
{
.
id
=
LZMA_VLI_UNKNOWN
,
.
options
=
nullptr
},
};
bool
GZStream
::
write
(
const
void
*
in
,
size_t
size
,
int
flush
)
{
int
ret
;
strm
.
next_in
=
(
Bytef
*
)
in
;
strm
.
avail_in
=
size
;
do
{
strm
.
next_out
=
outbuf
;
strm
.
avail_out
=
sizeof
(
outbuf
);
lzma_ret
ret
;
switch
(
mode
)
{
case
0
:
ret
=
inflate
(
&
strm
,
flush
);
case
DECODE
:
ret
=
lzma_auto_decoder
(
&
strm
,
UINT64_MAX
,
0
);
break
;
case
1
:
ret
=
deflate
(
&
strm
,
flush
);
case
ENCODE_XZ
:
ret
=
lzma_stream_encoder
(
&
strm
,
filters
,
LZMA_CHECK_CRC32
);
break
;
case
ENCODE_LZMA
:
ret
=
lzma_alone_encoder
(
&
strm
,
&
opt
);
break
;
}
if
(
ret
==
Z_STREAM_ERROR
)
{
LOGW
(
"Gzip %s failed (%d)
\n
"
,
mode
?
"encode"
:
"decode"
,
ret
);
return
false
;
}
FilterOutStream
::
write
(
outbuf
,
sizeof
(
outbuf
)
-
strm
.
avail_out
);
}
while
(
strm
.
avail_out
==
0
);
return
true
;
}
}
BZStream
::
BZStream
(
int
mode
)
:
mode
(
mode
),
strm
({})
{
switch
(
mode
)
{
case
0
:
BZ2_bzDecompressInit
(
&
strm
,
0
,
0
);
break
;
case
1
:
BZ2_bzCompressInit
(
&
strm
,
9
,
0
,
0
);
break
;
void
finish
()
override
{
write
(
nullptr
,
0
,
LZMA_FINISH
);
lzma_end
(
&
strm
);
}
}
bool
BZStream
::
write
(
const
void
*
in
,
size_t
size
)
{
return
size
?
write
(
in
,
size
,
BZ_RUN
)
:
true
;
}
private
:
lzma_stream
strm
;
uint8_t
outbuf
[
CHUNK
];
int
write
(
const
void
*
buf
,
size_t
len
,
lzma_action
flush
)
{
strm
.
next_in
=
(
uint8_t
*
)
buf
;
strm
.
avail_in
=
len
;
do
{
strm
.
avail_out
=
sizeof
(
outbuf
);
strm
.
next_out
=
outbuf
;
int
code
=
lzma_code
(
&
strm
,
flush
);
if
(
code
!=
LZMA_OK
&&
code
!=
LZMA_STREAM_END
)
{
LOGW
(
"LZMA %s failed (%d)
\n
"
,
mode
?
"encode"
:
"decode"
,
code
);
return
-
1
;
}
bwrite
(
outbuf
,
sizeof
(
outbuf
)
-
strm
.
avail_out
);
}
while
(
strm
.
avail_out
==
0
);
return
len
;
}
};
class
lzma_decoder
:
public
lzma_strm
{
public
:
lzma_decoder
(
FILE
*
fp
)
:
lzma_strm
(
DECODE
,
fp
)
{}
};
class
xz_encoder
:
public
lzma_strm
{
public
:
xz_encoder
(
FILE
*
fp
)
:
lzma_strm
(
ENCODE_XZ
,
fp
)
{}
};
class
lzma_encoder
:
public
lzma_strm
{
public
:
lzma_encoder
(
FILE
*
fp
)
:
lzma_strm
(
ENCODE_LZMA
,
fp
)
{}
};
class
LZ4F_decoder
:
public
cpr_stream
{
public
:
explicit
LZ4F_decoder
(
FILE
*
fp
)
:
cpr_stream
(
fp
),
outbuf
(
nullptr
)
{
LZ4F_createDecompressionContext
(
&
ctx
,
LZ4F_VERSION
);
}
uint64_t
BZStream
::
finalize
()
{
if
(
mode
)
write
(
nullptr
,
0
,
BZ_FINISH
);
uint64_t
total
=
((
uint64_t
)
strm
.
total_out_hi32
<<
32
)
+
strm
.
total_out_lo32
;
switch
(
mode
)
{
case
0
:
BZ2_bzDecompressEnd
(
&
strm
);
break
;
case
1
:
BZ2_bzCompressEnd
(
&
strm
);
break
;
}
return
total
;
}
~
LZ4F_decoder
()
override
{
LZ4F_freeDecompressionContext
(
ctx
);
delete
[]
outbuf
;
}
bool
BZStream
::
write
(
const
void
*
in
,
size_t
size
,
int
flush
)
{
int
ret
;
strm
.
next_in
=
(
char
*
)
in
;
strm
.
avail_in
=
size
;
do
{
strm
.
avail_out
=
sizeof
(
outbuf
);
strm
.
next_out
=
outbuf
;
switch
(
mode
)
{
case
0
:
ret
=
BZ2_bzDecompress
(
&
strm
);
break
;
case
1
:
ret
=
BZ2_bzCompress
(
&
strm
,
flush
);
break
;
}
if
(
ret
<
0
)
{
LOGW
(
"Bzip2 %s failed (%d)
\n
"
,
mode
?
"encode"
:
"decode"
,
ret
);
return
false
;
int
write
(
const
void
*
buf
,
size_t
len
)
override
{
auto
ret
=
len
;
auto
inbuf
=
reinterpret_cast
<
const
uint8_t
*>
(
buf
);
if
(
!
outbuf
)
read_header
(
inbuf
,
len
);
size_t
read
,
write
;
LZ4F_errorCode_t
code
;
do
{
read
=
len
;
write
=
outCapacity
;
code
=
LZ4F_decompress
(
ctx
,
outbuf
,
&
write
,
inbuf
,
&
read
,
nullptr
);
if
(
LZ4F_isError
(
code
))
{
LOGW
(
"LZ4F decode error: %s
\n
"
,
LZ4F_getErrorName
(
code
));
return
-
1
;
}
len
-=
read
;
inbuf
+=
read
;
bwrite
(
outbuf
,
write
);
}
while
(
len
!=
0
||
write
!=
0
);
return
ret
;
}
private
:
LZ4F_decompressionContext_t
ctx
;
uint8_t
*
outbuf
;
size_t
outCapacity
;
void
read_header
(
const
uint8_t
*&
in
,
size_t
&
size
)
{
size_t
read
=
size
;
LZ4F_frameInfo_t
info
;
LZ4F_getFrameInfo
(
ctx
,
&
info
,
in
,
&
read
);
switch
(
info
.
blockSizeID
)
{
case
LZ4F_default
:
case
LZ4F_max64KB
:
outCapacity
=
1
<<
16
;
break
;
case
LZ4F_max256KB
:
outCapacity
=
1
<<
18
;
break
;
case
LZ4F_max1MB
:
outCapacity
=
1
<<
20
;
break
;
case
LZ4F_max4MB
:
outCapacity
=
1
<<
22
;
break
;
}
FilterOutStream
::
write
(
outbuf
,
sizeof
(
outbuf
)
-
strm
.
avail_out
);
}
while
(
strm
.
avail_out
==
0
);
return
true
;
}
outbuf
=
new
uint8_t
[
outCapacity
];
in
+=
read
;
size
-=
read
;
}
};
LZMAStream
::
LZMAStream
(
int
mode
)
:
mode
(
mode
),
strm
(
LZMA_STREAM_INIT
)
{
lzma_options_lzma
opt
;
int
ret
;
class
LZ4F_encoder
:
public
cpr_stream
{
public
:
explicit
LZ4F_encoder
(
FILE
*
fp
)
:
cpr_stream
(
fp
),
outbuf
(
nullptr
),
outCapacity
(
0
)
{
LZ4F_createCompressionContext
(
&
ctx
,
LZ4F_VERSION
);
}
// Initialize preset
lzma_lzma_preset
(
&
opt
,
9
);
lzma_filter
filters
[]
=
{
{
.
id
=
LZMA_FILTER_LZMA2
,
.
options
=
&
opt
},
{
.
id
=
LZMA_VLI_UNKNOWN
,
.
options
=
nullptr
},
};
~
LZ4F_encoder
()
override
{
destroy
();
LZ4F_freeCompressionContext
(
ctx
);
delete
[]
outbuf
;
}
switch
(
mode
)
{
case
0
:
ret
=
lzma_auto_decoder
(
&
strm
,
UINT64_MAX
,
0
);
break
;
case
1
:
ret
=
lzma_stream_encoder
(
&
strm
,
filters
,
LZMA_CHECK_CRC32
);
break
;
case
2
:
ret
=
lzma_alone_encoder
(
&
strm
,
&
opt
);
break
;
int
write
(
const
void
*
buf
,
size_t
len
)
override
{
auto
ret
=
len
;
if
(
!
outbuf
)
write_header
();
if
(
len
==
0
)
return
0
;
auto
inbuf
=
reinterpret_cast
<
const
uint8_t
*>
(
buf
);
size_t
read
,
write
;
do
{
read
=
len
>
BLOCK_SZ
?
BLOCK_SZ
:
len
;
write
=
LZ4F_compressUpdate
(
ctx
,
outbuf
,
outCapacity
,
inbuf
,
read
,
nullptr
);
if
(
LZ4F_isError
(
write
))
{
LOGW
(
"LZ4F encode error: %s
\n
"
,
LZ4F_getErrorName
(
write
));
return
-
1
;
}
len
-=
read
;
inbuf
+=
read
;
bwrite
(
outbuf
,
write
);
}
while
(
len
!=
0
);
return
ret
;
}
}
bool
LZMAStream
::
write
(
const
void
*
in
,
size_t
size
)
{
return
size
?
write
(
in
,
size
,
LZMA_RUN
)
:
true
;
}
protected
:
void
finish
()
override
{
size_t
len
=
LZ4F_compressEnd
(
ctx
,
outbuf
,
outCapacity
,
nullptr
);
bwrite
(
outbuf
,
len
);
}
uint64_t
LZMAStream
::
finalize
()
{
write
(
nullptr
,
0
,
LZMA_FINISH
);
uint64_t
total
=
strm
.
total_out
;
lzma_end
(
&
strm
);
return
total
;
}
private
:
LZ4F_compressionContext_t
ctx
;
uint8_t
*
outbuf
;
size_t
outCapacity
;
static
constexpr
size_t
BLOCK_SZ
=
1
<<
22
;
void
write_header
()
{
LZ4F_preferences_t
prefs
{
.
autoFlush
=
1
,
.
compressionLevel
=
9
,
.
frameInfo
=
{
.
blockMode
=
LZ4F_blockIndependent
,
.
blockSizeID
=
LZ4F_max4MB
,
.
blockChecksumFlag
=
LZ4F_noBlockChecksum
,
.
contentChecksumFlag
=
LZ4F_contentChecksumEnabled
}
};
outCapacity
=
LZ4F_compressBound
(
BLOCK_SZ
,
&
prefs
);
outbuf
=
new
uint8_t
[
outCapacity
];
size_t
write
=
LZ4F_compressBegin
(
ctx
,
outbuf
,
outCapacity
,
&
prefs
);
bwrite
(
outbuf
,
write
);
}
};
class
LZ4_decoder
:
public
cpr_stream
{
public
:
explicit
LZ4_decoder
(
FILE
*
fp
)
:
cpr_stream
(
fp
),
out_buf
(
new
char
[
LZ4_UNCOMPRESSED
]),
buffer
(
new
char
[
LZ4_COMPRESSED
]),
init
(
false
),
block_sz
(
0
),
buf_off
(
0
)
{}
~
LZ4_decoder
()
override
{
delete
[]
out_buf
;
delete
[]
buffer
;
}
bool
LZMAStream
::
write
(
const
void
*
in
,
size_t
size
,
lzma_action
flush
)
{
int
ret
;
strm
.
next_in
=
(
uint8_t
*
)
in
;
strm
.
avail_in
=
size
;
do
{
strm
.
avail_out
=
sizeof
(
outbuf
);
strm
.
next_out
=
outbuf
;
ret
=
lzma_code
(
&
strm
,
flush
);
if
(
ret
!=
LZMA_OK
&&
ret
!=
LZMA_STREAM_END
)
{
LOGW
(
"LZMA %s failed (%d)
\n
"
,
mode
?
"encode"
:
"decode"
,
ret
);
return
false
;
int
write
(
const
void
*
in
,
size_t
size
)
override
{
auto
ret
=
size
;
auto
inbuf
=
static_cast
<
const
char
*>
(
in
);
if
(
!
init
)
{
// Skip magic
inbuf
+=
4
;
size
-=
4
;
init
=
true
;
}
FilterOutStream
::
write
(
outbuf
,
sizeof
(
outbuf
)
-
strm
.
avail_out
);
}
while
(
strm
.
avail_out
==
0
);
return
true
;
}
int
write
;
size_t
consumed
;
do
{
if
(
block_sz
==
0
)
{
block_sz
=
*
((
unsigned
*
)
inbuf
);
inbuf
+=
sizeof
(
unsigned
);
size
-=
sizeof
(
unsigned
);
}
else
if
(
buf_off
+
size
>=
block_sz
)
{
consumed
=
block_sz
-
buf_off
;
memcpy
(
buffer
+
buf_off
,
inbuf
,
consumed
);
inbuf
+=
consumed
;
size
-=
consumed
;
write
=
LZ4_decompress_safe
(
buffer
,
out_buf
,
block_sz
,
LZ4_UNCOMPRESSED
);
if
(
write
<
0
)
{
LOGW
(
"LZ4HC decompression failure (%d)
\n
"
,
write
);
return
-
1
;
}
bwrite
(
out_buf
,
write
);
// Reset
buf_off
=
0
;
block_sz
=
0
;
}
else
{
// Copy to internal buffer
memcpy
(
buffer
+
buf_off
,
inbuf
,
size
);
buf_off
+=
size
;
size
=
0
;
}
}
while
(
size
!=
0
);
return
ret
;
}
LZ4FDecoder
::
LZ4FDecoder
()
:
outbuf
(
nullptr
),
total
(
0
)
{
LZ4F_createDecompressionContext
(
&
ctx
,
LZ4F_VERSION
);
}
private
:
char
*
out_buf
;
char
*
buffer
;
bool
init
;
unsigned
block_sz
;
int
buf_off
;
};
class
LZ4_encoder
:
public
cpr_stream
{
public
:
explicit
LZ4_encoder
(
FILE
*
fp
)
:
cpr_stream
(
fp
),
outbuf
(
new
char
[
LZ4_COMPRESSED
]),
buf
(
new
char
[
LZ4_UNCOMPRESSED
]),
init
(
false
),
buf_off
(
0
),
in_total
(
0
)
{}
~
LZ4_encoder
()
override
{
destroy
();
delete
[]
outbuf
;
delete
[]
buf
;
}
LZ4FDecoder
::~
LZ4FDecoder
()
{
LZ4F_freeDecompressionContext
(
ctx
);
delete
[]
outbuf
;
}
int
write
(
const
void
*
in
,
size_t
size
)
override
{
if
(
!
init
)
{
bwrite
(
"
\x02\x21\x4c\x18
"
,
4
);
init
=
true
;
}
if
(
size
==
0
)
return
0
;
in_total
+=
size
;
const
char
*
inbuf
=
(
const
char
*
)
in
;
size_t
consumed
;
int
write
;
do
{
if
(
buf_off
+
size
>=
LZ4_UNCOMPRESSED
)
{
consumed
=
LZ4_UNCOMPRESSED
-
buf_off
;
memcpy
(
buf
+
buf_off
,
inbuf
,
consumed
);
inbuf
+=
consumed
;
size
-=
consumed
;
write
=
LZ4_compress_HC
(
buf
,
outbuf
,
LZ4_UNCOMPRESSED
,
LZ4_COMPRESSED
,
9
);
if
(
write
==
0
)
{
LOGW
(
"LZ4HC compression failure
\n
"
);
return
false
;
}
bwrite
(
&
write
,
sizeof
(
write
));
bwrite
(
outbuf
,
write
);
// Reset buffer
buf_off
=
0
;
}
else
{
// Copy to internal buffer
memcpy
(
buf
+
buf_off
,
inbuf
,
size
);
buf_off
+=
size
;
size
=
0
;
}
}
while
(
size
!=
0
);
return
true
;
}
bool
LZ4FDecoder
::
write
(
const
void
*
in
,
size_t
size
)
{
auto
inbuf
=
(
const
uint8_t
*
)
in
;
if
(
!
outbuf
)
read_header
(
inbuf
,
size
);
size_t
read
,
write
;
LZ4F_errorCode_t
ret
;
do
{
read
=
size
;
write
=
outCapacity
;
ret
=
LZ4F_decompress
(
ctx
,
outbuf
,
&
write
,
inbuf
,
&
read
,
nullptr
);
if
(
LZ4F_isError
(
ret
))
{
LOGW
(
"LZ4 decode error: %s
\n
"
,
LZ4F_getErrorName
(
ret
));
return
false
;
protected
:
void
finish
()
override
{
if
(
buf_off
)
{
int
write
=
LZ4_compress_HC
(
buf
,
outbuf
,
buf_off
,
LZ4_COMPRESSED
,
9
);
bwrite
(
&
write
,
sizeof
(
write
));
bwrite
(
outbuf
,
write
);
}
size
-=
read
;
inbuf
+=
read
;
total
+=
write
;
FilterOutStream
::
write
(
outbuf
,
write
);
}
while
(
size
!=
0
||
write
!=
0
);
return
true
;
}
bwrite
(
&
in_total
,
sizeof
(
in_total
));
}
uint64_t
LZ4FDecoder
::
finalize
()
{
return
total
;
}
private
:
char
*
outbuf
;
char
*
buf
;
bool
init
;
int
buf_off
;
unsigned
in_total
;
};
void
LZ4FDecoder
::
read_header
(
const
uint8_t
*&
in
,
size_t
&
size
)
{
size_t
read
=
size
;
LZ4F_frameInfo_t
info
;
LZ4F_getFrameInfo
(
ctx
,
&
info
,
in
,
&
read
);
switch
(
info
.
blockSizeID
)
{
case
LZ4F_default
:
case
LZ4F_max64KB
:
outCapacity
=
1
<<
16
;
break
;
case
LZ4F_max256KB
:
outCapacity
=
1
<<
18
;
break
;
case
LZ4F_max1MB
:
outCapacity
=
1
<<
20
;
break
;
case
LZ4F_max4MB
:
outCapacity
=
1
<<
22
;
break
;
}
outbuf
=
new
uint8_t
[
outCapacity
];
in
+=
read
;
size
-=
read
;
filter_stream
*
get_encoder
(
format_t
type
,
FILE
*
fp
)
{
switch
(
type
)
{
case
XZ
:
return
new
xz_encoder
(
fp
);
case
LZMA
:
return
new
lzma_encoder
(
fp
);
case
BZIP2
:
return
new
bz_encoder
(
fp
);
case
LZ4
:
return
new
LZ4F_encoder
(
fp
);
case
LZ4_LEGACY
:
return
new
LZ4_encoder
(
fp
);
case
GZIP
:
default:
return
new
gz_encoder
(
fp
);
}
}
LZ4FEncoder
::
LZ4FEncoder
()
:
outbuf
(
nullptr
),
outCapacity
(
0
),
total
(
0
)
{
LZ4F_createCompressionContext
(
&
ctx
,
LZ4F_VERSION
);
filter_stream
*
get_decoder
(
format_t
type
,
FILE
*
fp
)
{
switch
(
type
)
{
case
XZ
:
case
LZMA
:
return
new
lzma_decoder
(
fp
);
case
BZIP2
:
return
new
bz_decoder
(
fp
);
case
LZ4
:
return
new
LZ4F_decoder
(
fp
);
case
LZ4_LEGACY
:
return
new
LZ4_decoder
(
fp
);
case
GZIP
:
default:
return
new
gz_decoder
(
fp
);
}
}
LZ4FEncoder
::~
LZ4FEncoder
()
{
LZ4F_freeCompressionContext
(
ctx
);
delete
[]
outbuf
;
}
void
decompress
(
char
*
infile
,
const
char
*
outfile
)
{
bool
in_std
=
infile
==
"-"
sv
;
bool
rm_in
=
false
;
bool
LZ4FEncoder
::
write
(
const
void
*
in
,
size_t
size
)
{
if
(
!
outbuf
)
write_header
();
if
(
size
==
0
)
return
true
;
auto
inbuf
=
(
const
uint8_t
*
)
in
;
size_t
read
,
write
;
do
{
read
=
size
>
BLOCK_SZ
?
BLOCK_SZ
:
size
;
write
=
LZ4F_compressUpdate
(
ctx
,
outbuf
,
outCapacity
,
inbuf
,
read
,
nullptr
);
if
(
LZ4F_isError
(
write
))
{
LOGW
(
"LZ4 encode error: %s
\n
"
,
LZ4F_getErrorName
(
write
));
return
false
;
}
size
-=
read
;
inbuf
+=
read
;
total
+=
write
;
FilterOutStream
::
write
(
outbuf
,
write
);
}
while
(
size
!=
0
);
return
true
;
}
FILE
*
in_fp
=
in_std
?
stdin
:
xfopen
(
infile
,
"re"
);
unique_ptr
<
stream
>
strm
;
uint64_t
LZ4FEncoder
::
finalize
()
{
size_t
write
=
LZ4F_compressEnd
(
ctx
,
outbuf
,
outCapacity
,
nullptr
);
total
+=
write
;
FilterOutStream
::
write
(
outbuf
,
write
);
return
total
;
}
char
buf
[
4096
];
size_t
len
;
while
((
len
=
fread
(
buf
,
1
,
sizeof
(
buf
),
in_fp
)))
{
if
(
!
strm
)
{
format_t
type
=
check_fmt
(
buf
,
len
);
void
LZ4FEncoder
::
write_header
()
{
LZ4F_preferences_t
prefs
{
.
autoFlush
=
1
,
.
compressionLevel
=
9
,
.
frameInfo
=
{
.
blockMode
=
LZ4F_blockIndependent
,
.
blockSizeID
=
LZ4F_max4MB
,
.
blockChecksumFlag
=
LZ4F_noBlockChecksum
,
.
contentChecksumFlag
=
LZ4F_contentChecksumEnabled
}
};
outCapacity
=
LZ4F_compressBound
(
BLOCK_SZ
,
&
prefs
);
outbuf
=
new
uint8_t
[
outCapacity
];
size_t
write
=
LZ4F_compressBegin
(
ctx
,
outbuf
,
outCapacity
,
&
prefs
);
total
+=
write
;
FilterOutStream
::
write
(
outbuf
,
write
);
}
if
(
!
COMPRESSED
(
type
))
LOGE
(
"Input file is not a supported compressed type!
\n
"
);
LZ4Decoder
::
LZ4Decoder
()
:
outbuf
(
new
char
[
LZ4_UNCOMPRESSED
]),
buf
(
new
char
[
LZ4_COMPRESSED
]),
init
(
false
),
block_sz
(
0
),
buf_off
(
0
),
total
(
0
)
{}
fprintf
(
stderr
,
"Detected format: [%s]
\n
"
,
fmt2name
[
type
]);
LZ4Decoder
::~
LZ4Decoder
()
{
delete
[]
outbuf
;
delete
[]
buf
;
}
/* If user does not provide outfile, infile has to be either
* <path>.[ext], or '-'. Outfile will be either <path> or '-'.
* If the input does not have proper format, abort */
char
*
ext
=
nullptr
;
if
(
outfile
==
nullptr
)
{
outfile
=
infile
;
if
(
!
in_std
)
{
ext
=
strrchr
(
infile
,
'.'
);
if
(
ext
==
nullptr
||
strcmp
(
ext
,
fmt2ext
[
type
])
!=
0
)
LOGE
(
"Input file is not a supported type!
\n
"
);
bool
LZ4Decoder
::
write
(
const
void
*
in
,
size_t
size
)
{
const
char
*
inbuf
=
(
const
char
*
)
in
;
if
(
!
init
)
{
// Skip magic
inbuf
+=
4
;
size
-=
4
;
init
=
true
;
}
int
write
;
size_t
consumed
;
do
{
if
(
block_sz
==
0
)
{
block_sz
=
*
((
unsigned
*
)
inbuf
);
inbuf
+=
sizeof
(
unsigned
);
size
-=
sizeof
(
unsigned
);
}
else
if
(
buf_off
+
size
>=
block_sz
)
{
consumed
=
block_sz
-
buf_off
;
memcpy
(
buf
+
buf_off
,
inbuf
,
consumed
);
inbuf
+=
consumed
;
size
-=
consumed
;
write
=
LZ4_decompress_safe
(
buf
,
outbuf
,
block_sz
,
LZ4_UNCOMPRESSED
);
if
(
write
<
0
)
{
LOGW
(
"LZ4HC decompression failure (%d)
\n
"
,
write
);
return
false
;
// Strip out extension and remove input
*
ext
=
'\0'
;
rm_in
=
true
;
fprintf
(
stderr
,
"Decompressing to [%s]
\n
"
,
outfile
);
}
}
FilterOutStream
::
write
(
outbuf
,
write
);
total
+=
write
;
// Reset
buf_off
=
0
;
block_sz
=
0
;
}
else
{
// Copy to internal buffer
memcpy
(
buf
+
buf_off
,
inbuf
,
size
);
buf_off
+=
size
;
size
=
0
;
FILE
*
out_fp
=
outfile
==
"-"
sv
?
stdout
:
xfopen
(
outfile
,
"we"
);
strm
.
reset
(
get_decoder
(
type
,
out_fp
));
if
(
ext
)
*
ext
=
'.'
;
}
}
while
(
size
!=
0
);
return
true
;
}
if
(
strm
->
write
(
buf
,
len
)
<
0
)
LOGE
(
"Decompression error!
\n
"
)
;
}
uint64_t
LZ4Decoder
::
finalize
()
{
return
total
;
strm
->
close
();
fclose
(
in_fp
);
if
(
rm_in
)
unlink
(
infile
);
}
LZ4Encoder
::
LZ4Encoder
()
:
outbuf
(
new
char
[
LZ4_COMPRESSED
]),
buf
(
new
char
[
LZ4_UNCOMPRESSED
]),
init
(
false
),
buf_off
(
0
),
out_total
(
0
),
in_total
(
0
)
{}
void
compress
(
const
char
*
method
,
const
char
*
infile
,
const
char
*
outfile
)
{
auto
it
=
name2fmt
.
find
(
method
);
if
(
it
==
name2fmt
.
end
())
LOGE
(
"Unknown compression method: [%s]
\n
"
,
method
);
LZ4Encoder
::~
LZ4Encoder
()
{
delete
[]
outbuf
;
delete
[]
buf
;
}
bool
in_std
=
infile
==
"-"
sv
;
bool
rm_in
=
false
;
bool
LZ4Encoder
::
write
(
const
void
*
in
,
size_t
size
)
{
if
(
!
init
)
{
FilterOutStream
::
write
(
"
\x02\x21\x4c\x18
"
,
4
);
init
=
true
;
}
if
(
size
==
0
)
return
true
;
in_total
+=
size
;
const
char
*
inbuf
=
(
const
char
*
)
in
;
size_t
consumed
;
int
write
;
do
{
if
(
buf_off
+
size
>=
LZ4_UNCOMPRESSED
)
{
consumed
=
LZ4_UNCOMPRESSED
-
buf_off
;
memcpy
(
buf
+
buf_off
,
inbuf
,
consumed
);
inbuf
+=
consumed
;
size
-=
consumed
;
write
=
LZ4_compress_HC
(
buf
,
outbuf
,
LZ4_UNCOMPRESSED
,
LZ4_COMPRESSED
,
9
);
if
(
write
==
0
)
{
LOGW
(
"LZ4HC compression failure
\n
"
);
return
false
;
}
FilterOutStream
::
write
(
&
write
,
sizeof
(
write
));
FilterOutStream
::
write
(
outbuf
,
write
);
out_total
+=
write
+
sizeof
(
write
);
FILE
*
in_fp
=
in_std
?
stdin
:
xfopen
(
infile
,
"re"
);
FILE
*
out_fp
;
// Reset buffer
buf_off
=
0
;
if
(
outfile
==
nullptr
)
{
if
(
in_std
)
{
out_fp
=
stdout
;
}
else
{
// Copy to internal buffer
memcpy
(
buf
+
buf_off
,
inbuf
,
size
);
buf_off
+=
size
;
size
=
0
;
/* If user does not provide outfile and infile is not
* STDIN, output to <infile>.[ext] */
string
tmp
(
infile
);
tmp
+=
fmt2ext
[
it
->
second
];
out_fp
=
xfopen
(
tmp
.
data
(),
"we"
);
fprintf
(
stderr
,
"Compressing to [%s]
\n
"
,
tmp
.
data
());
rm_in
=
true
;
}
}
while
(
size
!=
0
);
return
true
;
}
uint64_t
LZ4Encoder
::
finalize
()
{
if
(
buf_off
)
{
int
write
=
LZ4_compress_HC
(
buf
,
outbuf
,
buf_off
,
LZ4_COMPRESSED
,
9
);
FilterOutStream
::
write
(
&
write
,
sizeof
(
write
));
FilterOutStream
::
write
(
outbuf
,
write
);
out_total
+=
write
+
sizeof
(
write
);
}
else
{
out_fp
=
outfile
==
"-"
sv
?
stdout
:
xfopen
(
outfile
,
"we"
);
}
FilterOutStream
::
write
(
&
in_total
,
sizeof
(
in_total
));
return
out_total
+
sizeof
(
in_total
);
unique_ptr
<
stream
>
strm
(
get_encoder
(
it
->
second
,
out_fp
));
char
buf
[
4096
];
size_t
len
;
while
((
len
=
fread
(
buf
,
1
,
sizeof
(
buf
),
in_fp
)))
{
if
(
strm
->
write
(
buf
,
len
)
<
0
)
LOGE
(
"Compression error!
\n
"
);
};
strm
->
close
();
fclose
(
in_fp
);
if
(
rm_in
)
unlink
(
infile
);
}
native/jni/magiskboot/compress.h
View file @
d26d804c
#pragma once
#include <zlib.h>
#include <bzlib.h>
#include <lzma.h>
#include <lz4.h>
#include <lz4frame.h>
#include <lz4hc.h>
#include <stream.h>
#include "format.h"
#define CHUNK 0x40000
class
Compression
:
public
FilterOutStream
{
public
:
virtual
uint64_t
finalize
()
=
0
;
};
class
GZStream
:
public
Compression
{
public
:
bool
write
(
const
void
*
in
,
size_t
size
)
override
;
uint64_t
finalize
()
override
;
protected
:
explicit
GZStream
(
int
mode
);
private
:
int
mode
;
z_stream
strm
;
uint8_t
outbuf
[
CHUNK
];
bool
write
(
const
void
*
in
,
size_t
size
,
int
flush
);
};
class
GZDecoder
:
public
GZStream
{
public
:
GZDecoder
()
:
GZStream
(
0
)
{};
};
class
GZEncoder
:
public
GZStream
{
public
:
GZEncoder
()
:
GZStream
(
1
)
{};
};
class
BZStream
:
public
Compression
{
public
:
bool
write
(
const
void
*
in
,
size_t
size
)
override
;
uint64_t
finalize
()
override
;
protected
:
explicit
BZStream
(
int
mode
);
private
:
int
mode
;
bz_stream
strm
;
char
outbuf
[
CHUNK
];
bool
write
(
const
void
*
in
,
size_t
size
,
int
flush
);
};
class
BZDecoder
:
public
BZStream
{
public
:
BZDecoder
()
:
BZStream
(
0
)
{};
};
class
BZEncoder
:
public
BZStream
{
public
:
BZEncoder
()
:
BZStream
(
1
)
{};
};
class
LZMAStream
:
public
Compression
{
public
:
bool
write
(
const
void
*
in
,
size_t
size
)
override
;
uint64_t
finalize
()
override
;
protected
:
explicit
LZMAStream
(
int
mode
);
private
:
int
mode
;
lzma_stream
strm
;
uint8_t
outbuf
[
CHUNK
];
bool
write
(
const
void
*
in
,
size_t
size
,
lzma_action
flush
);
};
class
LZMADecoder
:
public
LZMAStream
{
public
:
LZMADecoder
()
:
LZMAStream
(
0
)
{}
};
class
XZEncoder
:
public
LZMAStream
{
public
:
XZEncoder
()
:
LZMAStream
(
1
)
{}
};
class
LZMAEncoder
:
public
LZMAStream
{
public
:
LZMAEncoder
()
:
LZMAStream
(
2
)
{}
};
class
LZ4FDecoder
:
public
Compression
{
public
:
LZ4FDecoder
();
~
LZ4FDecoder
()
override
;
bool
write
(
const
void
*
in
,
size_t
size
)
override
;
uint64_t
finalize
()
override
;
private
:
LZ4F_decompressionContext_t
ctx
;
uint8_t
*
outbuf
;
size_t
outCapacity
;
uint64_t
total
;
void
read_header
(
const
uint8_t
*&
in
,
size_t
&
size
);
};
class
LZ4FEncoder
:
public
Compression
{
public
:
LZ4FEncoder
();
~
LZ4FEncoder
()
override
;
bool
write
(
const
void
*
in
,
size_t
size
)
override
;
uint64_t
finalize
()
override
;
private
:
static
constexpr
size_t
BLOCK_SZ
=
1
<<
22
;
LZ4F_compressionContext_t
ctx
;
uint8_t
*
outbuf
;
size_t
outCapacity
;
uint64_t
total
;
void
write_header
();
};
#define LZ4_UNCOMPRESSED 0x800000
#define LZ4_COMPRESSED LZ4_COMPRESSBOUND(LZ4_UNCOMPRESSED)
class
LZ4Decoder
:
public
Compression
{
public
:
LZ4Decoder
();
~
LZ4Decoder
()
override
;
bool
write
(
const
void
*
in
,
size_t
size
)
override
;
uint64_t
finalize
()
override
;
private
:
char
*
outbuf
;
char
*
buf
;
bool
init
;
unsigned
block_sz
;
int
buf_off
;
uint64_t
total
;
};
class
LZ4Encoder
:
public
Compression
{
public
:
LZ4Encoder
();
~
LZ4Encoder
()
override
;
bool
write
(
const
void
*
in
,
size_t
size
)
override
;
uint64_t
finalize
()
override
;
private
:
char
*
outbuf
;
char
*
buf
;
bool
init
;
int
buf_off
;
uint64_t
out_total
;
unsigned
in_total
;
};
Compression
*
get_encoder
(
format_t
type
);
Compression
*
get_decoder
(
format_t
type
);
filter_stream
*
get_encoder
(
format_t
type
,
FILE
*
fp
=
nullptr
);
filter_stream
*
get_decoder
(
format_t
type
,
FILE
*
fp
=
nullptr
);
void
compress
(
const
char
*
method
,
const
char
*
infile
,
const
char
*
outfile
);
void
decompress
(
char
*
infile
,
const
char
*
outfile
);
native/jni/magiskboot/ramdisk.cpp
View file @
d26d804c
...
...
@@ -241,14 +241,17 @@ void magisk_cpio::compress() {
return
;
fprintf
(
stderr
,
"Compressing cpio -> [%s]
\n
"
,
RAMDISK_XZ
);
auto
init
=
entries
.
extract
(
"init"
);
XZEncoder
encoder
;
encoder
.
setOut
(
make_unique
<
BufOutStream
>
());
output
(
encoder
);
encoder
.
finalize
();
uint8_t
*
data
;
size_t
len
;
FILE
*
fp
=
open_stream
(
get_encoder
(
XZ
,
open_stream
<
byte_stream
>
(
data
,
len
)));
dump
(
fp
);
entries
.
clear
();
entries
.
insert
(
std
::
move
(
init
));
auto
xz
=
new
cpio_entry
(
RAMDISK_XZ
,
S_IFREG
);
static_cast
<
BufOutStream
*>
(
encoder
.
getOut
())
->
release
(
xz
->
data
,
xz
->
filesize
);
xz
->
data
=
data
;
xz
->
filesize
=
len
;
insert
(
xz
);
}
...
...
@@ -257,15 +260,16 @@ void magisk_cpio::decompress() {
if
(
it
==
entries
.
end
())
return
;
fprintf
(
stderr
,
"Decompressing cpio [%s]
\n
"
,
RAMDISK_XZ
);
LZMADecoder
decoder
;
decoder
.
setOut
(
make_unique
<
BufOutStream
>
());
decoder
.
write
(
it
->
second
->
data
,
it
->
second
->
filesize
);
decoder
.
finalize
();
char
*
data
;
size_t
len
;
auto
strm
=
get_decoder
(
XZ
,
open_stream
<
byte_stream
>
(
data
,
len
));
strm
->
write
(
it
->
second
->
data
,
it
->
second
->
filesize
);
delete
strm
;
entries
.
erase
(
it
);
char
*
buf
;
size_t
sz
;
static_cast
<
BufOutStream
*>
(
decoder
.
getOut
())
->
getbuf
(
buf
,
sz
);
load_cpio
(
buf
,
sz
);
load_cpio
(
data
,
len
);
free
(
data
);
}
int
cpio_commands
(
int
argc
,
char
*
argv
[])
{
...
...
@@ -338,4 +342,4 @@ int cpio_commands(int argc, char *argv[]) {
cpio
.
dump
(
incpio
);
return
0
;
}
\ No newline at end of file
}
native/jni/utils/cpio.cpp
View file @
d26d804c
...
...
@@ -49,8 +49,7 @@ cpio_entry_base::cpio_entry_base(const cpio_newc_header *h)
void
cpio
::
dump
(
const
char
*
file
)
{
fprintf
(
stderr
,
"Dump cpio: [%s]
\n
"
,
file
);
FDOutStream
fd_out
(
xopen
(
file
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
0644
),
true
);
output
(
fd_out
);
dump
(
xfopen
(
file
,
"we"
));
}
void
cpio
::
rm
(
entry_map
::
iterator
&
it
)
{
...
...
@@ -110,9 +109,9 @@ bool cpio::exists(const char *name) {
return
entries
.
count
(
name
)
!=
0
;
}
#define do_out(b
, l) out.write(b, l); pos += (l)
#define out_align()
out.write(zeros, align_off(pos, 4)); pos = do_align(pos, 4
)
void
cpio
::
output
(
OutStream
&
out
)
{
#define do_out(b
uf, len) pos += fwrite(buf, len, 1, out);
#define out_align()
do_out(zeros, align_off(pos, 4)
)
void
cpio
::
dump
(
FILE
*
out
)
{
size_t
pos
=
0
;
unsigned
inode
=
300000
;
char
header
[
111
];
...
...
@@ -147,6 +146,7 @@ void cpio::output(OutStream &out) {
do_out
(
header
,
110
);
do_out
(
"TRAILER!!!
\0
"
,
11
);
out_align
();
fclose
(
out
);
}
cpio_rw
::
cpio_rw
(
const
char
*
file
)
{
...
...
@@ -221,12 +221,12 @@ bool cpio_rw::mv(const char *from, const char *to) {
#define pos_align(p) p = do_align(p, 4)
void
cpio_rw
::
load_cpio
(
char
*
buf
,
size_t
sz
)
{
void
cpio_rw
::
load_cpio
(
c
onst
c
har
*
buf
,
size_t
sz
)
{
size_t
pos
=
0
;
cpio_newc_header
*
header
;
c
onst
c
pio_newc_header
*
header
;
unique_ptr
<
cpio_entry
>
entry
;
while
(
pos
<
sz
)
{
header
=
(
cpio_newc_header
*
)
(
buf
+
pos
);
header
=
reinterpret_cast
<
const
cpio_newc_header
*>
(
buf
+
pos
);
entry
=
make_unique
<
cpio_entry
>
(
header
);
pos
+=
sizeof
(
*
header
);
string_view
name_view
(
buf
+
pos
);
...
...
native/jni/utils/include/cpio.h
View file @
d26d804c
...
...
@@ -30,7 +30,7 @@ struct cpio_entry : public cpio_entry_base {
explicit
cpio_entry
(
const
char
*
name
,
uint32_t
mode
)
:
filename
(
name
)
{
this
->
mode
=
mode
;
}
explicit
cpio_entry
(
cpio_newc_header
*
h
)
:
cpio_entry_base
(
h
)
{}
explicit
cpio_entry
(
c
onst
c
pio_newc_header
*
h
)
:
cpio_entry_base
(
h
)
{}
~
cpio_entry
()
override
{
free
(
data
);
};
};
...
...
@@ -48,7 +48,7 @@ public:
protected
:
entry_map
entries
;
void
rm
(
entry_map
::
iterator
&
it
);
void
output
(
OutStream
&
out
);
void
dump
(
FILE
*
out
);
};
class
cpio_rw
:
public
cpio
{
...
...
@@ -64,7 +64,7 @@ public:
protected
:
void
insert
(
cpio_entry
*
e
);
void
mv
(
entry_map
::
iterator
&
it
,
const
char
*
to
);
void
load_cpio
(
char
*
buf
,
size_t
sz
);
void
load_cpio
(
c
onst
c
har
*
buf
,
size_t
sz
);
};
class
cpio_mmap
:
public
cpio
{
...
...
native/jni/utils/include/stream.h
View file @
d26d804c
...
...
@@ -15,8 +15,6 @@ FILE *open_stream(Args &&... args) {
return
open_stream
(
new
T
(
args
...));
}
/* Base classes */
class
stream
{
public
:
virtual
int
read
(
void
*
buf
,
size_t
len
);
...
...
@@ -26,17 +24,17 @@ public:
virtual
~
stream
()
=
default
;
};
// Delegates all operations to the base FILE pointer
class
filter_stream
:
public
stream
{
public
:
filter_stream
(
FILE
*
fp
)
:
fp
(
fp
)
{}
int
close
()
override
{
return
fclose
(
fp
);
}
virtual
~
filter_stream
()
{
close
();
}
~
filter_stream
()
override
{
if
(
fp
)
close
();
}
void
set_base
(
FILE
*
f
)
{
if
(
fp
)
fclose
(
fp
);
fp
=
f
;
}
int
read
(
void
*
buf
,
size_t
len
)
override
;
int
write
(
const
void
*
buf
,
size_t
len
)
override
;
int
close
()
override
;
void
set_base
(
FILE
*
f
);
template
<
class
T
,
class
...
Args
>
void
set_base
(
Args
&&
...
args
)
{
set_base
(
open_stream
<
T
>
(
args
...));
...
...
@@ -46,18 +44,7 @@ protected:
FILE
*
fp
;
};
class
filter_in_stream
:
public
filter_stream
{
public
:
filter_in_stream
(
FILE
*
fp
=
nullptr
)
:
filter_stream
(
fp
)
{}
int
read
(
void
*
buf
,
size_t
len
)
override
{
return
fread
(
buf
,
len
,
1
,
fp
);
}
};
class
filter_out_stream
:
public
filter_stream
{
public
:
filter_out_stream
(
FILE
*
fp
=
nullptr
)
:
filter_stream
(
fp
)
{}
int
write
(
const
void
*
buf
,
size_t
len
)
override
{
return
fwrite
(
buf
,
len
,
1
,
fp
);
}
};
// Handy interface for classes that need custom seek logic
class
seekable_stream
:
public
stream
{
protected
:
size_t
_pos
=
0
;
...
...
@@ -66,8 +53,7 @@ protected:
virtual
size_t
end_pos
()
=
0
;
};
/* Concrete classes */
// Byte stream that dynamically allocates memory
class
byte_stream
:
public
seekable_stream
{
public
:
byte_stream
(
uint8_t
*&
buf
,
size_t
&
len
);
...
...
@@ -76,7 +62,6 @@ public:
int
read
(
void
*
buf
,
size_t
len
)
override
;
int
write
(
const
void
*
buf
,
size_t
len
)
override
;
off_t
seek
(
off_t
off
,
int
whence
)
override
;
virtual
~
byte_stream
()
=
default
;
private
:
uint8_t
*&
_buf
;
...
...
@@ -87,101 +72,14 @@ private:
size_t
end_pos
()
override
{
return
_len
;
}
};
class
fd_stream
:
stream
{
// File stream but does not close the file descriptor at any time
class
fd_stream
:
public
stream
{
public
:
fd_stream
(
int
fd
)
:
fd
(
fd
)
{}
int
read
(
void
*
buf
,
size_t
len
)
override
;
int
write
(
const
void
*
buf
,
size_t
len
)
override
;
off_t
seek
(
off_t
off
,
int
whence
)
override
;
virtual
~
fd_stream
()
=
default
;
private
:
int
fd
;
};
/* TODO: Replace classes below to new implementation */
class
OutStream
{
public
:
virtual
bool
write
(
const
void
*
buf
,
size_t
len
)
=
0
;
virtual
~
OutStream
()
=
default
;
};
typedef
std
::
unique_ptr
<
OutStream
>
strm_ptr
;
class
FilterOutStream
:
public
OutStream
{
public
:
FilterOutStream
()
=
default
;
FilterOutStream
(
strm_ptr
&&
ptr
)
:
out
(
std
::
move
(
ptr
))
{}
void
setOut
(
strm_ptr
&&
ptr
)
{
out
=
std
::
move
(
ptr
);
}
OutStream
*
getOut
()
{
return
out
.
get
();
}
bool
write
(
const
void
*
buf
,
size_t
len
)
override
{
return
out
?
out
->
write
(
buf
,
len
)
:
false
;
}
protected
:
strm_ptr
out
;
};
class
FDOutStream
:
public
OutStream
{
public
:
FDOutStream
(
int
fd
,
bool
close
=
false
)
:
fd
(
fd
),
close
(
close
)
{}
bool
write
(
const
void
*
buf
,
size_t
len
)
override
{
return
::
write
(
fd
,
buf
,
len
)
==
len
;
}
~
FDOutStream
()
override
{
if
(
close
)
::
close
(
fd
);
}
protected
:
int
fd
;
bool
close
;
};
class
BufOutStream
:
public
OutStream
{
public
:
BufOutStream
()
:
buf
(
nullptr
),
off
(
0
),
cap
(
0
)
{};
bool
write
(
const
void
*
b
,
size_t
len
)
override
{
bool
resize
=
false
;
while
(
off
+
len
>
cap
)
{
cap
=
cap
?
cap
<<
1
:
1
<<
19
;
resize
=
true
;
}
if
(
resize
)
buf
=
(
char
*
)
xrealloc
(
buf
,
cap
);
memcpy
(
buf
+
off
,
b
,
len
);
off
+=
len
;
return
true
;
}
template
<
typename
bytes
,
typename
length
>
void
release
(
bytes
*&
b
,
length
&
len
)
{
b
=
buf
;
len
=
off
;
buf
=
nullptr
;
off
=
cap
=
0
;
}
template
<
typename
bytes
,
typename
length
>
void
getbuf
(
bytes
*&
b
,
length
&
len
)
const
{
b
=
buf
;
len
=
off
;
}
~
BufOutStream
()
override
{
free
(
buf
);
}
protected
:
char
*
buf
;
size_t
off
;
size_t
cap
;
};
native/jni/utils/stream.cpp
View file @
d26d804c
...
...
@@ -49,6 +49,25 @@ int stream::close() {
return
0
;
}
int
filter_stream
::
read
(
void
*
buf
,
size_t
len
)
{
return
fread
(
buf
,
len
,
1
,
fp
);
}
int
filter_stream
::
write
(
const
void
*
buf
,
size_t
len
)
{
return
fwrite
(
buf
,
len
,
1
,
fp
);
}
int
filter_stream
::
close
()
{
int
ret
=
fclose
(
fp
);
fp
=
nullptr
;
return
ret
;
}
void
filter_stream
::
set_base
(
FILE
*
f
)
{
if
(
fp
)
fclose
(
fp
);
fp
=
f
;
}
off_t
seekable_stream
::
new_pos
(
off_t
off
,
int
whence
)
{
off_t
new_pos
;
switch
(
whence
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment