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;
...
@@ -21,19 +21,18 @@ using namespace std;
uint32_t
dyn_img_hdr
::
j32
=
0
;
uint32_t
dyn_img_hdr
::
j32
=
0
;
uint64_t
dyn_img_hdr
::
j64
=
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
)
{
static
void
decompress
(
format_t
type
,
int
fd
,
const
void
*
in
,
size_t
size
)
{
ptr
->
setOut
(
make_unique
<
FDOutStream
>
(
fd
));
unique_ptr
<
stream
>
ptr
(
get_decoder
(
type
,
open_stream
<
fd_stream
>
(
fd
)));
if
(
!
ptr
->
write
(
in
,
size
))
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
int64_t
compress
(
format_t
type
,
int
fd
,
const
void
*
in
,
size_t
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
)
{
static
void
dump
(
void
*
buf
,
size_t
size
,
const
char
*
filename
)
{
...
...
native/jni/magiskboot/compress.cpp
View file @
d26d804c
...
@@ -6,6 +6,13 @@
...
@@ -6,6 +6,13 @@
#include <memory>
#include <memory>
#include <functional>
#include <functional>
#include <zlib.h>
#include <bzlib.h>
#include <lzma.h>
#include <lz4.h>
#include <lz4frame.h>
#include <lz4hc.h>
#include <logging.h>
#include <logging.h>
#include <utils.h>
#include <utils.h>
...
@@ -14,524 +21,639 @@
...
@@ -14,524 +21,639 @@
using
namespace
std
;
using
namespace
std
;
static
bool
read_file
(
FILE
*
fp
,
const
function
<
void
(
void
*
,
size_t
)
>
&
fn
)
{
#define bwrite filter_stream::write
char
buf
[
4096
];
#define bclose filter_stream::close
size_t
len
;
while
((
len
=
fread
(
buf
,
1
,
sizeof
(
buf
),
fp
)))
fn
(
buf
,
len
);
return
true
;
}
void
decompress
(
char
*
infile
,
const
char
*
outfile
)
{
constexpr
size_t
CHUNK
=
0x40000
;
bool
in_std
=
strcmp
(
infile
,
"-"
)
==
0
;
constexpr
size_t
LZ4_UNCOMPRESSED
=
0x80000
0
;
bool
rm_in
=
false
;
constexpr
size_t
LZ4_COMPRESSED
=
LZ4_COMPRESSBOUND
(
LZ4_UNCOMPRESSED
)
;
FILE
*
in_file
=
in_std
?
stdin
:
xfopen
(
infile
,
"re"
);
class
cpr_stream
:
public
filter_stream
{
int
out_fd
=
-
1
;
public
:
unique_ptr
<
Compression
>
cmp
;
explicit
cpr_stream
(
FILE
*
fp
)
:
filter_stream
(
fp
)
{}
read_file
(
in_file
,
[
&
](
void
*
buf
,
size_t
len
)
->
void
{
int
read
(
void
*
buf
,
size_t
len
)
final
{
if
(
out_fd
<
0
)
{
return
stream
::
read
(
buf
,
len
);
format_t
type
=
check_fmt
(
buf
,
len
);
}
fprintf
(
stderr
,
"Detected format: [%s]
\n
"
,
fmt2name
[
type
]);
int
close
()
final
{
finish
();
return
bclose
();
}
if
(
!
COMPRESSED
(
type
))
protected
:
LOGE
(
"Input file is not a supported compressed type!
\n
"
);
// 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
int
write
(
const
void
*
buf
,
size_t
len
)
override
{
* <path>.[ext], or '-'. Outfile will be either <path> or '-'.
return
len
?
write
(
buf
,
len
,
Z_NO_FLUSH
)
:
0
;
* If the input does not have proper format, abort */
}
char
*
ext
=
nullptr
;
protected
:
if
(
outfile
==
nullptr
)
{
enum
mode_t
{
outfile
=
infile
;
DECODE
,
if
(
!
in_std
)
{
ENCODE
ext
=
strrchr
(
infile
,
'.'
);
}
mode
;
if
(
ext
==
nullptr
||
strcmp
(
ext
,
fmt2ext
[
type
])
!=
0
)
LOGE
(
"Input file is not a supported type!
\n
"
);
// Strip out extension and remove input
gz_strm
(
mode_t
mode
,
FILE
*
fp
)
:
cpr_stream
(
fp
),
mode
(
mode
)
{
*
ext
=
'\0'
;
switch
(
mode
)
{
rm_in
=
true
;
case
DECODE
:
fprintf
(
stderr
,
"Decompressing to [%s]
\n
"
,
outfile
);
inflateInit2
(
&
strm
,
15
|
16
);
}
break
;
}
case
ENCODE
:
deflateInit2
(
&
strm
,
9
,
Z_DEFLATED
,
15
|
16
,
8
,
Z_DEFAULT_STRATEGY
);
break
;
}
}
out_fd
=
strcmp
(
outfile
,
"-"
)
==
0
?
void
finish
()
override
{
STDOUT_FILENO
:
xopen
(
outfile
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
0644
);
write
(
nullptr
,
0
,
Z_FINISH
);
cmp
->
setOut
(
make_unique
<
FDOutStream
>
(
out_fd
));
switch
(
mode
)
{
if
(
ext
)
*
ext
=
'.'
;
case
DECODE
:
inflateEnd
(
&
strm
);
break
;
case
ENCODE
:
deflateEnd
(
&
strm
);
break
;
}
}
if
(
!
cmp
->
write
(
buf
,
len
))
}
LOGE
(
"Decompression error!
\n
"
);
});
cmp
->
finalize
();
private
:
fclose
(
in_file
);
z_stream
strm
;
close
(
out_fd
);
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
)
class
gz_decoder
:
public
gz_strm
{
unlink
(
infile
);
public
:
}
explicit
gz_decoder
(
FILE
*
fp
)
:
gz_strm
(
DECODE
,
fp
)
{};
};
void
compress
(
const
char
*
method
,
const
char
*
infile
,
const
char
*
outfile
)
{
class
gz_encoder
:
public
gz_strm
{
auto
it
=
name2fmt
.
find
(
method
);
public
:
if
(
it
==
name2fmt
.
end
())
explicit
gz_encoder
(
FILE
*
fp
)
:
gz_strm
(
ENCODE
,
fp
)
{};
LOGE
(
"Unsupported compression method: [%s]
\n
"
,
method
)
;
}
;
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
;
int
write
(
const
void
*
buf
,
size_t
len
)
override
{
bool
rm_in
=
false
;
return
len
?
write
(
buf
,
len
,
BZ_RUN
)
:
0
;
}
FILE
*
in_file
=
in_std
?
stdin
:
xfopen
(
infile
,
"re"
);
protected
:
int
out_fd
;
enum
mode_t
{
DECODE
,
ENCODE
}
mode
;
if
(
outfile
==
nullptr
)
{
bz_strm
(
mode_t
mode
,
FILE
*
fp
)
:
cpr_stream
(
fp
),
mode
(
mode
)
{
if
(
in_std
)
{
switch
(
mode
)
{
out_fd
=
STDOUT_FILENO
;
case
DECODE
:
}
else
{
BZ2_bzDecompressInit
(
&
strm
,
0
,
0
);
/* If user does not provide outfile and infile is not
break
;
* STDIN, output to <infile>.[ext] */
case
ENCODE
:
char
*
tmp
=
new
char
[
strlen
(
infile
)
+
5
];
BZ2_bzCompressInit
(
&
strm
,
9
,
0
,
0
);
sprintf
(
tmp
,
"%s%s"
,
infile
,
fmt2ext
[
it
->
second
]);
break
;
out_fd
=
xopen
(
tmp
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
0644
);
fprintf
(
stderr
,
"Compressing to [%s]
\n
"
,
tmp
);
delete
[]
tmp
;
rm_in
=
true
;
}
}
}
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
{
private
:
if
(
!
cmp
->
write
(
buf
,
len
))
bz_stream
strm
;
LOGE
(
"Compression error!
\n
"
);
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
();
class
bz_decoder
:
public
bz_strm
{
fclose
(
in_file
);
public
:
close
(
out_fd
);
explicit
bz_decoder
(
FILE
*
fp
)
:
bz_strm
(
DECODE
,
fp
)
{};
};
if
(
rm_in
)
class
bz_encoder
:
public
bz_strm
{
unlink
(
infile
);
public
:
}
explicit
bz_encoder
(
FILE
*
fp
)
:
bz_strm
(
ENCODE
,
fp
)
{};
};
Compression
*
get_encoder
(
format_t
type
)
{
class
lzma_strm
:
public
cpr_stream
{
switch
(
type
)
{
public
:
case
XZ
:
~
lzma_strm
()
override
{
destroy
();
}
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
();
}
}
Compression
*
get_decoder
(
format_t
type
)
{
int
write
(
const
void
*
buf
,
size_t
len
)
override
{
switch
(
type
)
{
return
len
?
write
(
buf
,
len
,
LZMA_RUN
)
:
0
;
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
();
}
}
}
GZStream
::
GZStream
(
int
mode
)
:
mode
(
mode
),
strm
({})
{
protected
:
switch
(
mode
)
{
enum
mode_t
{
case
0
:
DECODE
,
inflateInit2
(
&
strm
,
15
|
16
);
ENCODE_XZ
,
break
;
ENCODE_LZMA
case
1
:
}
mode
;
deflateInit2
(
&
strm
,
9
,
Z_DEFLATED
,
15
|
16
,
8
,
Z_DEFAULT_STRATEGY
);
break
;
}
}
bool
GZStream
::
write
(
const
void
*
in
,
size_t
size
)
{
lzma_strm
(
mode_t
mode
,
FILE
*
fp
)
:
cpr_stream
(
fp
),
mode
(
mode
),
strm
(
LZMA_STREAM_INIT
)
{
return
size
?
write
(
in
,
size
,
Z_NO_FLUSH
)
:
true
;
lzma_options_lzma
opt
;
}
uint64_t
GZStream
::
finalize
()
{
// Initialize preset
write
(
nullptr
,
0
,
Z_FINISH
);
lzma_lzma_preset
(
&
opt
,
9
);
uint64_t
total
=
strm
.
total_out
;
lzma_filter
filters
[]
=
{
switch
(
mode
)
{
{
.
id
=
LZMA_FILTER_LZMA2
,
.
options
=
&
opt
},
case
0
:
{
.
id
=
LZMA_VLI_UNKNOWN
,
.
options
=
nullptr
},
inflateEnd
(
&
strm
);
};
break
;
case
1
:
deflateEnd
(
&
strm
);
break
;
}
return
total
;
}
bool
GZStream
::
write
(
const
void
*
in
,
size_t
size
,
int
flush
)
{
lzma_ret
ret
;
int
ret
;
strm
.
next_in
=
(
Bytef
*
)
in
;
strm
.
avail_in
=
size
;
do
{
strm
.
next_out
=
outbuf
;
strm
.
avail_out
=
sizeof
(
outbuf
);
switch
(
mode
)
{
switch
(
mode
)
{
case
0
:
case
DECODE
:
ret
=
inflate
(
&
strm
,
flush
);
ret
=
lzma_auto_decoder
(
&
strm
,
UINT64_MAX
,
0
);
break
;
break
;
case
1
:
case
ENCODE_XZ
:
ret
=
deflate
(
&
strm
,
flush
);
ret
=
lzma_stream_encoder
(
&
strm
,
filters
,
LZMA_CHECK_CRC32
);
break
;
case
ENCODE_LZMA
:
ret
=
lzma_alone_encoder
(
&
strm
,
&
opt
);
break
;
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
({})
{
void
finish
()
override
{
switch
(
mode
)
{
write
(
nullptr
,
0
,
LZMA_FINISH
);
case
0
:
lzma_end
(
&
strm
);
BZ2_bzDecompressInit
(
&
strm
,
0
,
0
);
break
;
case
1
:
BZ2_bzCompressInit
(
&
strm
,
9
,
0
,
0
);
break
;
}
}
}
bool
BZStream
::
write
(
const
void
*
in
,
size_t
size
)
{
private
:
return
size
?
write
(
in
,
size
,
BZ_RUN
)
:
true
;
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
()
{
~
LZ4F_decoder
()
override
{
if
(
mode
)
LZ4F_freeDecompressionContext
(
ctx
);
write
(
nullptr
,
0
,
BZ_FINISH
);
delete
[]
outbuf
;
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
;
}
bool
BZStream
::
write
(
const
void
*
in
,
size_t
size
,
int
flush
)
{
int
write
(
const
void
*
buf
,
size_t
len
)
override
{
int
ret
;
auto
ret
=
len
;
strm
.
next_in
=
(
char
*
)
in
;
auto
inbuf
=
reinterpret_cast
<
const
uint8_t
*>
(
buf
);
strm
.
avail_in
=
size
;
if
(
!
outbuf
)
do
{
read_header
(
inbuf
,
len
);
strm
.
avail_out
=
sizeof
(
outbuf
);
size_t
read
,
write
;
strm
.
next_out
=
outbuf
;
LZ4F_errorCode_t
code
;
switch
(
mode
)
{
do
{
case
0
:
read
=
len
;
ret
=
BZ2_bzDecompress
(
&
strm
);
write
=
outCapacity
;
break
;
code
=
LZ4F_decompress
(
ctx
,
outbuf
,
&
write
,
inbuf
,
&
read
,
nullptr
);
case
1
:
if
(
LZ4F_isError
(
code
))
{
ret
=
BZ2_bzCompress
(
&
strm
,
flush
);
LOGW
(
"LZ4F decode error: %s
\n
"
,
LZ4F_getErrorName
(
code
));
break
;
return
-
1
;
}
}
if
(
ret
<
0
)
{
len
-=
read
;
LOGW
(
"Bzip2 %s failed (%d)
\n
"
,
mode
?
"encode"
:
"decode"
,
ret
);
inbuf
+=
read
;
return
false
;
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
);
outbuf
=
new
uint8_t
[
outCapacity
];
}
while
(
strm
.
avail_out
==
0
);
in
+=
read
;
return
true
;
size
-=
read
;
}
}
};
LZMAStream
::
LZMAStream
(
int
mode
)
:
mode
(
mode
),
strm
(
LZMA_STREAM_INIT
)
{
class
LZ4F_encoder
:
public
cpr_stream
{
lzma_options_lzma
opt
;
public
:
int
ret
;
explicit
LZ4F_encoder
(
FILE
*
fp
)
:
cpr_stream
(
fp
),
outbuf
(
nullptr
),
outCapacity
(
0
)
{
LZ4F_createCompressionContext
(
&
ctx
,
LZ4F_VERSION
);
}
// Initialize preset
~
LZ4F_encoder
()
override
{
lzma_lzma_preset
(
&
opt
,
9
);
destroy
();
lzma_filter
filters
[]
=
{
LZ4F_freeCompressionContext
(
ctx
);
{
.
id
=
LZMA_FILTER_LZMA2
,
.
options
=
&
opt
},
delete
[]
outbuf
;
{
.
id
=
LZMA_VLI_UNKNOWN
,
.
options
=
nullptr
},
}
};
switch
(
mode
)
{
int
write
(
const
void
*
buf
,
size_t
len
)
override
{
case
0
:
auto
ret
=
len
;
ret
=
lzma_auto_decoder
(
&
strm
,
UINT64_MAX
,
0
);
if
(
!
outbuf
)
break
;
write_header
();
case
1
:
if
(
len
==
0
)
ret
=
lzma_stream_encoder
(
&
strm
,
filters
,
LZMA_CHECK_CRC32
);
return
0
;
break
;
auto
inbuf
=
reinterpret_cast
<
const
uint8_t
*>
(
buf
);
case
2
:
size_t
read
,
write
;
ret
=
lzma_alone_encoder
(
&
strm
,
&
opt
);
do
{
break
;
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
)
{
protected
:
return
size
?
write
(
in
,
size
,
LZMA_RUN
)
:
true
;
void
finish
()
override
{
}
size_t
len
=
LZ4F_compressEnd
(
ctx
,
outbuf
,
outCapacity
,
nullptr
);
bwrite
(
outbuf
,
len
);
}
uint64_t
LZMAStream
::
finalize
()
{
private
:
write
(
nullptr
,
0
,
LZMA_FINISH
);
LZ4F_compressionContext_t
ctx
;
uint64_t
total
=
strm
.
total_out
;
uint8_t
*
outbuf
;
lzma_end
(
&
strm
);
size_t
outCapacity
;
return
total
;
}
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
write
(
const
void
*
in
,
size_t
size
)
override
{
int
ret
;
auto
ret
=
size
;
strm
.
next_in
=
(
uint8_t
*
)
in
;
auto
inbuf
=
static_cast
<
const
char
*>
(
in
);
strm
.
avail_in
=
size
;
if
(
!
init
)
{
do
{
// Skip magic
strm
.
avail_out
=
sizeof
(
outbuf
);
inbuf
+=
4
;
strm
.
next_out
=
outbuf
;
size
-=
4
;
ret
=
lzma_code
(
&
strm
,
flush
);
init
=
true
;
if
(
ret
!=
LZMA_OK
&&
ret
!=
LZMA_STREAM_END
)
{
LOGW
(
"LZMA %s failed (%d)
\n
"
,
mode
?
"encode"
:
"decode"
,
ret
);
return
false
;
}
}
FilterOutStream
::
write
(
outbuf
,
sizeof
(
outbuf
)
-
strm
.
avail_out
);
int
write
;
}
while
(
strm
.
avail_out
==
0
);
size_t
consumed
;
return
true
;
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
)
{
private
:
LZ4F_createDecompressionContext
(
&
ctx
,
LZ4F_VERSION
);
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
()
{
int
write
(
const
void
*
in
,
size_t
size
)
override
{
LZ4F_freeDecompressionContext
(
ctx
);
if
(
!
init
)
{
delete
[]
outbuf
;
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
)
{
protected
:
auto
inbuf
=
(
const
uint8_t
*
)
in
;
void
finish
()
override
{
if
(
!
outbuf
)
if
(
buf_off
)
{
read_header
(
inbuf
,
size
);
int
write
=
LZ4_compress_HC
(
buf
,
outbuf
,
buf_off
,
LZ4_COMPRESSED
,
9
);
size_t
read
,
write
;
bwrite
(
&
write
,
sizeof
(
write
));
LZ4F_errorCode_t
ret
;
bwrite
(
outbuf
,
write
);
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
;
}
}
size
-=
read
;
bwrite
(
&
in_total
,
sizeof
(
in_total
));
inbuf
+=
read
;
}
total
+=
write
;
FilterOutStream
::
write
(
outbuf
,
write
);
}
while
(
size
!=
0
||
write
!=
0
);
return
true
;
}
uint64_t
LZ4FDecoder
::
finalize
()
{
private
:
return
total
;
char
*
outbuf
;
}
char
*
buf
;
bool
init
;
int
buf_off
;
unsigned
in_total
;
};
void
LZ4FDecoder
::
read_header
(
const
uint8_t
*&
in
,
size_t
&
size
)
{
filter_stream
*
get_encoder
(
format_t
type
,
FILE
*
fp
)
{
size_t
read
=
size
;
switch
(
type
)
{
LZ4F_frameInfo_t
info
;
case
XZ
:
LZ4F_getFrameInfo
(
ctx
,
&
info
,
in
,
&
read
);
return
new
xz_encoder
(
fp
);
switch
(
info
.
blockSizeID
)
{
case
LZMA
:
case
LZ4F_default
:
return
new
lzma_encoder
(
fp
);
case
LZ4F_max64KB
:
outCapacity
=
1
<<
16
;
break
;
case
BZIP2
:
case
LZ4F_max256KB
:
outCapacity
=
1
<<
18
;
break
;
return
new
bz_encoder
(
fp
);
case
LZ4F_max1MB
:
outCapacity
=
1
<<
20
;
break
;
case
LZ4
:
case
LZ4F_max4MB
:
outCapacity
=
1
<<
22
;
break
;
return
new
LZ4F_encoder
(
fp
);
}
case
LZ4_LEGACY
:
outbuf
=
new
uint8_t
[
outCapacity
];
return
new
LZ4_encoder
(
fp
);
in
+=
read
;
case
GZIP
:
size
-=
read
;
default:
return
new
gz_encoder
(
fp
);
}
}
}
LZ4FEncoder
::
LZ4FEncoder
()
:
outbuf
(
nullptr
),
outCapacity
(
0
),
total
(
0
)
{
filter_stream
*
get_decoder
(
format_t
type
,
FILE
*
fp
)
{
LZ4F_createCompressionContext
(
&
ctx
,
LZ4F_VERSION
);
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
()
{
void
decompress
(
char
*
infile
,
const
char
*
outfile
)
{
LZ4F_freeCompressionContext
(
ctx
);
bool
in_std
=
infile
==
"-"
sv
;
delete
[]
outbuf
;
bool
rm_in
=
false
;
}
bool
LZ4FEncoder
::
write
(
const
void
*
in
,
size_t
size
)
{
FILE
*
in_fp
=
in_std
?
stdin
:
xfopen
(
infile
,
"re"
);
if
(
!
outbuf
)
unique_ptr
<
stream
>
strm
;
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
;
}
uint64_t
LZ4FEncoder
::
finalize
()
{
char
buf
[
4096
];
size_t
write
=
LZ4F_compressEnd
(
ctx
,
outbuf
,
outCapacity
,
nullptr
);
size_t
len
;
total
+=
write
;
while
((
len
=
fread
(
buf
,
1
,
sizeof
(
buf
),
in_fp
)))
{
FilterOutStream
::
write
(
outbuf
,
write
);
if
(
!
strm
)
{
return
total
;
format_t
type
=
check_fmt
(
buf
,
len
);
}
void
LZ4FEncoder
::
write_header
()
{
if
(
!
COMPRESSED
(
type
))
LZ4F_preferences_t
prefs
{
LOGE
(
"Input file is not a supported compressed type!
\n
"
);
.
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
);
}
LZ4Decoder
::
LZ4Decoder
()
:
outbuf
(
new
char
[
LZ4_UNCOMPRESSED
]),
buf
(
new
char
[
LZ4_COMPRESSED
]),
fprintf
(
stderr
,
"Detected format: [%s]
\n
"
,
fmt2name
[
type
]);
init
(
false
),
block_sz
(
0
),
buf_off
(
0
),
total
(
0
)
{}
LZ4Decoder
::~
LZ4Decoder
()
{
/* If user does not provide outfile, infile has to be either
delete
[]
outbuf
;
* <path>.[ext], or '-'. Outfile will be either <path> or '-'.
delete
[]
buf
;
* 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
)
{
// Strip out extension and remove input
const
char
*
inbuf
=
(
const
char
*
)
in
;
*
ext
=
'\0'
;
if
(
!
init
)
{
rm_in
=
true
;
// Skip magic
fprintf
(
stderr
,
"Decompressing to [%s]
\n
"
,
outfile
);
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
;
}
}
FilterOutStream
::
write
(
outbuf
,
write
);
total
+=
write
;
// Reset
FILE
*
out_fp
=
outfile
==
"-"
sv
?
stdout
:
xfopen
(
outfile
,
"we"
);
buf_off
=
0
;
strm
.
reset
(
get_decoder
(
type
,
out_fp
));
block_sz
=
0
;
if
(
ext
)
*
ext
=
'.'
;
}
else
{
// Copy to internal buffer
memcpy
(
buf
+
buf_off
,
inbuf
,
size
);
buf_off
+=
size
;
size
=
0
;
}
}
}
while
(
size
!=
0
);
if
(
strm
->
write
(
buf
,
len
)
<
0
)
return
true
;
LOGE
(
"Decompression error!
\n
"
)
;
}
}
uint64_t
LZ4Decoder
::
finalize
()
{
strm
->
close
();
return
total
;
fclose
(
in_fp
);
if
(
rm_in
)
unlink
(
infile
);
}
}
LZ4Encoder
::
LZ4Encoder
()
:
outbuf
(
new
char
[
LZ4_COMPRESSED
]),
buf
(
new
char
[
LZ4_UNCOMPRESSED
]),
void
compress
(
const
char
*
method
,
const
char
*
infile
,
const
char
*
outfile
)
{
init
(
false
),
buf_off
(
0
),
out_total
(
0
),
in_total
(
0
)
{}
auto
it
=
name2fmt
.
find
(
method
);
if
(
it
==
name2fmt
.
end
())
LOGE
(
"Unknown compression method: [%s]
\n
"
,
method
);
LZ4Encoder
::~
LZ4Encoder
()
{
bool
in_std
=
infile
==
"-"
sv
;
delete
[]
outbuf
;
bool
rm_in
=
false
;
delete
[]
buf
;
}
bool
LZ4Encoder
::
write
(
const
void
*
in
,
size_t
size
)
{
FILE
*
in_fp
=
in_std
?
stdin
:
xfopen
(
infile
,
"re"
);
if
(
!
init
)
{
FILE
*
out_fp
;
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
);
// Reset buffer
if
(
outfile
==
nullptr
)
{
buf_off
=
0
;
if
(
in_std
)
{
out_fp
=
stdout
;
}
else
{
}
else
{
// Copy to internal buffer
/* If user does not provide outfile and infile is not
memcpy
(
buf
+
buf_off
,
inbuf
,
size
);
* STDIN, output to <infile>.[ext] */
buf_off
+=
size
;
string
tmp
(
infile
);
size
=
0
;
tmp
+=
fmt2ext
[
it
->
second
];
out_fp
=
xfopen
(
tmp
.
data
(),
"we"
);
fprintf
(
stderr
,
"Compressing to [%s]
\n
"
,
tmp
.
data
());
rm_in
=
true
;
}
}
}
while
(
size
!=
0
);
}
else
{
return
true
;
out_fp
=
outfile
==
"-"
sv
?
stdout
:
xfopen
(
outfile
,
"we"
);
}
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
);
}
}
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
#pragma once
#include <zlib.h>
#include <bzlib.h>
#include <lzma.h>
#include <lz4.h>
#include <lz4frame.h>
#include <lz4hc.h>
#include <stream.h>
#include <stream.h>
#include "format.h"
#include "format.h"
#define CHUNK 0x40000
filter_stream
*
get_encoder
(
format_t
type
,
FILE
*
fp
=
nullptr
);
filter_stream
*
get_decoder
(
format_t
type
,
FILE
*
fp
=
nullptr
);
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
);
void
compress
(
const
char
*
method
,
const
char
*
infile
,
const
char
*
outfile
);
void
compress
(
const
char
*
method
,
const
char
*
infile
,
const
char
*
outfile
);
void
decompress
(
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() {
...
@@ -241,14 +241,17 @@ void magisk_cpio::compress() {
return
;
return
;
fprintf
(
stderr
,
"Compressing cpio -> [%s]
\n
"
,
RAMDISK_XZ
);
fprintf
(
stderr
,
"Compressing cpio -> [%s]
\n
"
,
RAMDISK_XZ
);
auto
init
=
entries
.
extract
(
"init"
);
auto
init
=
entries
.
extract
(
"init"
);
XZEncoder
encoder
;
encoder
.
setOut
(
make_unique
<
BufOutStream
>
());
uint8_t
*
data
;
output
(
encoder
);
size_t
len
;
encoder
.
finalize
();
FILE
*
fp
=
open_stream
(
get_encoder
(
XZ
,
open_stream
<
byte_stream
>
(
data
,
len
)));
dump
(
fp
);
entries
.
clear
();
entries
.
clear
();
entries
.
insert
(
std
::
move
(
init
));
entries
.
insert
(
std
::
move
(
init
));
auto
xz
=
new
cpio_entry
(
RAMDISK_XZ
,
S_IFREG
);
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
);
insert
(
xz
);
}
}
...
@@ -257,15 +260,16 @@ void magisk_cpio::decompress() {
...
@@ -257,15 +260,16 @@ void magisk_cpio::decompress() {
if
(
it
==
entries
.
end
())
if
(
it
==
entries
.
end
())
return
;
return
;
fprintf
(
stderr
,
"Decompressing cpio [%s]
\n
"
,
RAMDISK_XZ
);
fprintf
(
stderr
,
"Decompressing cpio [%s]
\n
"
,
RAMDISK_XZ
);
LZMADecoder
decoder
;
decoder
.
setOut
(
make_unique
<
BufOutStream
>
());
char
*
data
;
decoder
.
write
(
it
->
second
->
data
,
it
->
second
->
filesize
);
size_t
len
;
decoder
.
finalize
();
auto
strm
=
get_decoder
(
XZ
,
open_stream
<
byte_stream
>
(
data
,
len
));
strm
->
write
(
it
->
second
->
data
,
it
->
second
->
filesize
);
delete
strm
;
entries
.
erase
(
it
);
entries
.
erase
(
it
);
char
*
buf
;
load_cpio
(
data
,
len
);
size_t
sz
;
free
(
data
);
static_cast
<
BufOutStream
*>
(
decoder
.
getOut
())
->
getbuf
(
buf
,
sz
);
load_cpio
(
buf
,
sz
);
}
}
int
cpio_commands
(
int
argc
,
char
*
argv
[])
{
int
cpio_commands
(
int
argc
,
char
*
argv
[])
{
...
@@ -338,4 +342,4 @@ int cpio_commands(int argc, char *argv[]) {
...
@@ -338,4 +342,4 @@ int cpio_commands(int argc, char *argv[]) {
cpio
.
dump
(
incpio
);
cpio
.
dump
(
incpio
);
return
0
;
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)
...
@@ -49,8 +49,7 @@ cpio_entry_base::cpio_entry_base(const cpio_newc_header *h)
void
cpio
::
dump
(
const
char
*
file
)
{
void
cpio
::
dump
(
const
char
*
file
)
{
fprintf
(
stderr
,
"Dump cpio: [%s]
\n
"
,
file
);
fprintf
(
stderr
,
"Dump cpio: [%s]
\n
"
,
file
);
FDOutStream
fd_out
(
xopen
(
file
,
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
0644
),
true
);
dump
(
xfopen
(
file
,
"we"
));
output
(
fd_out
);
}
}
void
cpio
::
rm
(
entry_map
::
iterator
&
it
)
{
void
cpio
::
rm
(
entry_map
::
iterator
&
it
)
{
...
@@ -110,9 +109,9 @@ bool cpio::exists(const char *name) {
...
@@ -110,9 +109,9 @@ bool cpio::exists(const char *name) {
return
entries
.
count
(
name
)
!=
0
;
return
entries
.
count
(
name
)
!=
0
;
}
}
#define do_out(b
, l) out.write(b, l); pos += (l)
#define do_out(b
uf, len) pos += fwrite(buf, len, 1, out);
#define out_align()
out.write(zeros, align_off(pos, 4)); pos = do_align(pos, 4
)
#define out_align()
do_out(zeros, align_off(pos, 4)
)
void
cpio
::
output
(
OutStream
&
out
)
{
void
cpio
::
dump
(
FILE
*
out
)
{
size_t
pos
=
0
;
size_t
pos
=
0
;
unsigned
inode
=
300000
;
unsigned
inode
=
300000
;
char
header
[
111
];
char
header
[
111
];
...
@@ -147,6 +146,7 @@ void cpio::output(OutStream &out) {
...
@@ -147,6 +146,7 @@ void cpio::output(OutStream &out) {
do_out
(
header
,
110
);
do_out
(
header
,
110
);
do_out
(
"TRAILER!!!
\0
"
,
11
);
do_out
(
"TRAILER!!!
\0
"
,
11
);
out_align
();
out_align
();
fclose
(
out
);
}
}
cpio_rw
::
cpio_rw
(
const
char
*
file
)
{
cpio_rw
::
cpio_rw
(
const
char
*
file
)
{
...
@@ -221,12 +221,12 @@ bool cpio_rw::mv(const char *from, const char *to) {
...
@@ -221,12 +221,12 @@ bool cpio_rw::mv(const char *from, const char *to) {
#define pos_align(p) p = do_align(p, 4)
#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
;
size_t
pos
=
0
;
cpio_newc_header
*
header
;
c
onst
c
pio_newc_header
*
header
;
unique_ptr
<
cpio_entry
>
entry
;
unique_ptr
<
cpio_entry
>
entry
;
while
(
pos
<
sz
)
{
while
(
pos
<
sz
)
{
header
=
(
cpio_newc_header
*
)
(
buf
+
pos
);
header
=
reinterpret_cast
<
const
cpio_newc_header
*>
(
buf
+
pos
);
entry
=
make_unique
<
cpio_entry
>
(
header
);
entry
=
make_unique
<
cpio_entry
>
(
header
);
pos
+=
sizeof
(
*
header
);
pos
+=
sizeof
(
*
header
);
string_view
name_view
(
buf
+
pos
);
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 {
...
@@ -30,7 +30,7 @@ struct cpio_entry : public cpio_entry_base {
explicit
cpio_entry
(
const
char
*
name
,
uint32_t
mode
)
:
filename
(
name
)
{
explicit
cpio_entry
(
const
char
*
name
,
uint32_t
mode
)
:
filename
(
name
)
{
this
->
mode
=
mode
;
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
);
};
~
cpio_entry
()
override
{
free
(
data
);
};
};
};
...
@@ -48,7 +48,7 @@ public:
...
@@ -48,7 +48,7 @@ public:
protected
:
protected
:
entry_map
entries
;
entry_map
entries
;
void
rm
(
entry_map
::
iterator
&
it
);
void
rm
(
entry_map
::
iterator
&
it
);
void
output
(
OutStream
&
out
);
void
dump
(
FILE
*
out
);
};
};
class
cpio_rw
:
public
cpio
{
class
cpio_rw
:
public
cpio
{
...
@@ -64,7 +64,7 @@ public:
...
@@ -64,7 +64,7 @@ public:
protected
:
protected
:
void
insert
(
cpio_entry
*
e
);
void
insert
(
cpio_entry
*
e
);
void
mv
(
entry_map
::
iterator
&
it
,
const
char
*
to
);
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
{
class
cpio_mmap
:
public
cpio
{
...
...
native/jni/utils/include/stream.h
View file @
d26d804c
...
@@ -15,8 +15,6 @@ FILE *open_stream(Args &&... args) {
...
@@ -15,8 +15,6 @@ FILE *open_stream(Args &&... args) {
return
open_stream
(
new
T
(
args
...));
return
open_stream
(
new
T
(
args
...));
}
}
/* Base classes */
class
stream
{
class
stream
{
public
:
public
:
virtual
int
read
(
void
*
buf
,
size_t
len
);
virtual
int
read
(
void
*
buf
,
size_t
len
);
...
@@ -26,17 +24,17 @@ public:
...
@@ -26,17 +24,17 @@ public:
virtual
~
stream
()
=
default
;
virtual
~
stream
()
=
default
;
};
};
// Delegates all operations to the base FILE pointer
class
filter_stream
:
public
stream
{
class
filter_stream
:
public
stream
{
public
:
public
:
filter_stream
(
FILE
*
fp
)
:
fp
(
fp
)
{}
filter_stream
(
FILE
*
fp
)
:
fp
(
fp
)
{}
int
close
()
override
{
return
fclose
(
fp
);
}
~
filter_stream
()
override
{
if
(
fp
)
close
();
}
virtual
~
filter_stream
()
{
close
();
}
void
set_base
(
FILE
*
f
)
{
int
read
(
void
*
buf
,
size_t
len
)
override
;
if
(
fp
)
fclose
(
fp
);
int
write
(
const
void
*
buf
,
size_t
len
)
override
;
fp
=
f
;
int
close
()
override
;
}
void
set_base
(
FILE
*
f
);
template
<
class
T
,
class
...
Args
>
template
<
class
T
,
class
...
Args
>
void
set_base
(
Args
&&
...
args
)
{
void
set_base
(
Args
&&
...
args
)
{
set_base
(
open_stream
<
T
>
(
args
...));
set_base
(
open_stream
<
T
>
(
args
...));
...
@@ -46,18 +44,7 @@ protected:
...
@@ -46,18 +44,7 @@ protected:
FILE
*
fp
;
FILE
*
fp
;
};
};
class
filter_in_stream
:
public
filter_stream
{
// Handy interface for classes that need custom seek logic
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
);
}
};
class
seekable_stream
:
public
stream
{
class
seekable_stream
:
public
stream
{
protected
:
protected
:
size_t
_pos
=
0
;
size_t
_pos
=
0
;
...
@@ -66,8 +53,7 @@ protected:
...
@@ -66,8 +53,7 @@ protected:
virtual
size_t
end_pos
()
=
0
;
virtual
size_t
end_pos
()
=
0
;
};
};
/* Concrete classes */
// Byte stream that dynamically allocates memory
class
byte_stream
:
public
seekable_stream
{
class
byte_stream
:
public
seekable_stream
{
public
:
public
:
byte_stream
(
uint8_t
*&
buf
,
size_t
&
len
);
byte_stream
(
uint8_t
*&
buf
,
size_t
&
len
);
...
@@ -76,7 +62,6 @@ public:
...
@@ -76,7 +62,6 @@ public:
int
read
(
void
*
buf
,
size_t
len
)
override
;
int
read
(
void
*
buf
,
size_t
len
)
override
;
int
write
(
const
void
*
buf
,
size_t
len
)
override
;
int
write
(
const
void
*
buf
,
size_t
len
)
override
;
off_t
seek
(
off_t
off
,
int
whence
)
override
;
off_t
seek
(
off_t
off
,
int
whence
)
override
;
virtual
~
byte_stream
()
=
default
;
private
:
private
:
uint8_t
*&
_buf
;
uint8_t
*&
_buf
;
...
@@ -87,101 +72,14 @@ private:
...
@@ -87,101 +72,14 @@ private:
size_t
end_pos
()
override
{
return
_len
;
}
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
:
public
:
fd_stream
(
int
fd
)
:
fd
(
fd
)
{}
fd_stream
(
int
fd
)
:
fd
(
fd
)
{}
int
read
(
void
*
buf
,
size_t
len
)
override
;
int
read
(
void
*
buf
,
size_t
len
)
override
;
int
write
(
const
void
*
buf
,
size_t
len
)
override
;
int
write
(
const
void
*
buf
,
size_t
len
)
override
;
off_t
seek
(
off_t
off
,
int
whence
)
override
;
off_t
seek
(
off_t
off
,
int
whence
)
override
;
virtual
~
fd_stream
()
=
default
;
private
:
private
:
int
fd
;
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() {
...
@@ -49,6 +49,25 @@ int stream::close() {
return
0
;
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
seekable_stream
::
new_pos
(
off_t
off
,
int
whence
)
{
off_t
new_pos
;
off_t
new_pos
;
switch
(
whence
)
{
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