Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b2f7477

Browse files
IPRT/zip: Added detect functions for gzip, bzip2 and zx so the tar command (and others) can autoamtically detect compressed files that are being tested or extracted.
svn:sync-xref-src-repo-rev: r171253
1 parent fdaf076 commit b2f7477

File tree

5 files changed

+179
-2
lines changed

5 files changed

+179
-2
lines changed

‎include/iprt/mangling.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3177,6 +3177,7 @@
31773177
# define RTVfsCreateReadAheadForIoStream RT_MANGLER(RTVfsCreateReadAheadForIoStream)
31783178
# define RTZipBlockCompress RT_MANGLER(RTZipBlockCompress)
31793179
# define RTZipBlockDecompress RT_MANGLER(RTZipBlockDecompress)
3180+
# define RTZipBzip2IsStartOfCompressedStream RT_MANGLER(RTZipBzip2IsStartOfCompressedStream)
31803181
# define RTZipCompCreate RT_MANGLER(RTZipCompCreate)
31813182
# define RTZipCompDestroy RT_MANGLER(RTZipCompDestroy)
31823183
# define RTZipCompFinish RT_MANGLER(RTZipCompFinish)
@@ -3186,6 +3187,7 @@
31863187
# define RTZipDecompress RT_MANGLER(RTZipDecompress)
31873188
# define RTZipGzipCompressIoStream RT_MANGLER(RTZipGzipCompressIoStream)
31883189
# define RTZipGzipDecompressIoStream RT_MANGLER(RTZipGzipDecompressIoStream)
3190+
# define RTZipGzipIsStartOfCompressedStream RT_MANGLER(RTZipGzipIsStartOfCompressedStream)
31893191
# define RTZipGzipCmd RT_MANGLER(RTZipGzipCmd)
31903192
# define RTZipPkzipFsStreamFromIoStream RT_MANGLER(RTZipPkzipFsStreamFromIoStream)
31913193
# define RTZipPkzipMemDecompress RT_MANGLER(RTZipPkzipMemDecompress)
@@ -3205,6 +3207,7 @@
32053207
# define RTZipCpioFsStreamFromIoStream RT_MANGLER(RTZipCpioFsStreamFromIoStream)
32063208
# define RTZipXzCompressIoStream RT_MANGLER(RTZipXzCompressIoStream)
32073209
# define RTZipXzDecompressIoStream RT_MANGLER(RTZipXzDecompressIoStream)
3210+
# define RTZipXzIsStartOfCompressedStream RT_MANGLER(RTZipXzIsStartOfCompressedStream)
32083211

32093212
/* sort/merge into the above later: */
32103213
# define RTAsn1ContentAllocZ RT_MANGLER(RTAsn1ContentAllocZ)

‎include/iprt/zip.h‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,41 @@ RTDECL(int) RTZipGzipCompressIoStream(RTVFSIOSTREAM hVfsIosDst, uint32_t fFlags,
298298
RTDECL(int) RTZipXzCompressIoStream(RTVFSIOSTREAM hVfsIosDst, uint32_t fFlags, uint8_t uLevel, PRTVFSIOSTREAM phVfsIosXz);
299299

300300

301+
/**
302+
* Tests if the given bytes could be the start of an gzip compression stream.
303+
*
304+
* @returns true if like, false if not.
305+
* @param pabStart Pointer to a buffer containing @a cbStart bytes
306+
* from the start of the stream.
307+
* @param cbStart Number of bytes @a pabStart contains. Must be
308+
* at least 4 bytes for a positive gzip detection.
309+
*/
310+
RTDECL(bool) RTZipGzipIsStartOfCompressedStream(uint8_t const *pbStart, size_t cbStart);
311+
312+
/**
313+
* Tests if the given bytes could be the start of an bzip2 compression stream.
314+
*
315+
* @returns true if like, false if not.
316+
* @param pabStart Pointer to a buffer containing @a cbStart bytes
317+
* from the start of the stream.
318+
* @param cbStart Number of bytes @a pabStart contains. Must be
319+
* at least 6 bytes for a positive bzip2 detection,
320+
* 10 is better.
321+
*/
322+
RTDECL(bool) RTZipBzip2IsStartOfCompressedStream(uint8_t const *pbStart, size_t cbStart);
323+
324+
/**
325+
* Tests if the given bytes could be the start of an xz compression stream.
326+
*
327+
* @returns true if like, false if not.
328+
* @param pabStart Pointer to a buffer containing @a cbStart bytes
329+
* from the start of the stream.
330+
* @param cbStart Number of bytes @a pabStart contains. Must be
331+
* at least 6 bytes for a positive XZ detection.
332+
*/
333+
RTDECL(bool) RTZipXzIsStartOfCompressedStream(uint8_t const *pbStart, size_t cbStart);
334+
335+
301336
/**
302337
* A mini GZIP program.
303338
*

‎src/VBox/Runtime/Makefile.kmk‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Id: Makefile.kmk 111649 2025年11月12日 09:45:14Z knut.osmundsen@oracle.com $
1+
# $Id: Makefile.kmk 111661 2025年11月12日 12:00:49Z knut.osmundsen@oracle.com $
22
## @file
33
# Sub-Makefile for the IPRT.
44
#
@@ -793,6 +793,7 @@ RuntimeBaseR3_SOURCES := \
793793
common/vfs/vfsstdpipe.cpp \
794794
common/vfs/vfsprintf.cpp \
795795
common/zip/cpiovfs.cpp \
796+
common/zip/detect.cpp \
796797
common/zip/tarcmd.cpp \
797798
common/zip/tarvfs.cpp \
798799
common/zip/tarvfswriter.cpp \
@@ -2603,6 +2604,7 @@ RuntimeBldProg_SOURCES = \
26032604
common/vfs/vfsstdpipe.cpp \
26042605
common/zip/gzipvfs.cpp \
26052606
common/zip/cpiovfs.cpp \
2607+
common/zip/detect.cpp \
26062608
common/zip/tarcmd.cpp \
26072609
common/zip/tarvfs.cpp \
26082610
common/zip/tarvfswriter.cpp \
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/* $Id: detect.cpp 111661 2025年11月12日 12:00:49Z knut.osmundsen@oracle.com $ */
2+
/** @file
3+
* IPRT - Compression Detection.
4+
*/
5+
6+
/*
7+
* Copyright (C) 2025 Oracle and/or its affiliates.
8+
*
9+
* This file is part of VirtualBox base platform packages, as
10+
* available from https://www.virtualbox.org.
11+
*
12+
* This program is free software; you can redistribute it and/or
13+
* modify it under the terms of the GNU General Public License
14+
* as published by the Free Software Foundation, in version 3 of the
15+
* License.
16+
*
17+
* This program is distributed in the hope that it will be useful, but
18+
* WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20+
* General Public License for more details.
21+
*
22+
* You should have received a copy of the GNU General Public License
23+
* along with this program; if not, see <https://www.gnu.org/licenses>.
24+
*
25+
* The contents of this file may alternatively be used under the terms
26+
* of the Common Development and Distribution License Version 1.0
27+
* (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28+
* in the VirtualBox distribution, in which case the provisions of the
29+
* CDDL are applicable instead of those of the GPL.
30+
*
31+
* You may elect to license modified versions of this file under the
32+
* terms and conditions of either the GPL or the CDDL or both.
33+
*
34+
* SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35+
*/
36+
37+
38+
/*********************************************************************************************************************************
39+
* Header Files *
40+
*********************************************************************************************************************************/
41+
#include <iprt/zip.h>
42+
#include "internal/iprt.h"
43+
44+
45+
46+
RTDECL(bool) RTZipGzipIsStartOfCompressedStream(uint8_t const *pbStart, size_t cbStart)
47+
{
48+
/*
49+
* The gzip header starts with a two byte magic, which isn't much to go on.
50+
* Fortunately, the 3rd byte which specifies the compression method, is fixed
51+
* to 8 (deflate). We can also check the reserved flag bits of the 4th bytes,
52+
* which according to RFC-1952 must be zero.
53+
*/
54+
return cbStart >= 4
55+
&& pbStart[0] == 0x1f /* ID1 */
56+
&& pbStart[1] == 0x8b /* ID2 */
57+
&& pbStart[2] == 0x08 /* CM - deflate */
58+
&& (pbStart[3] & 0xe0) == 0; /* FLG - bits 5, 6 & 7 MBZ. */
59+
}
60+
61+
62+
RTDECL(bool) RTZipBzip2IsStartOfCompressedStream(uint8_t const *pbStart, size_t cbStart)
63+
{
64+
/*
65+
* The first 10 bytes of the Bzip2 header has 9 fixed bytes and the only
66+
* variable one is severely restricted in range. This makes it reasonably
67+
* easy to detect.
68+
*/
69+
return cbStart >= 6
70+
&& pbStart[0] == 0x42 /* magic[0] = 'B' */
71+
&& pbStart[1] == 0x5a /* magic[0] = 'Z' */
72+
&& pbStart[2] == 0x68 /* version = 'h' - huffman encoding; BZip1 uses '0' (0x30). */
73+
&& pbStart[3] >= 0x31 /* block-size (ascii) in 100KB units. */
74+
&& pbStart[3] <= 0x39
75+
&& pbStart[4] == 0x31 /* 6 byte block header = 0x314159265359 (pi) */
76+
&& pbStart[5] == 0x41
77+
&& (cbStart <= 6 || pbStart[6] == 0x59)
78+
&& (cbStart <= 7 || pbStart[7] == 0x26)
79+
&& (cbStart <= 8 || pbStart[8] == 0x53)
80+
&& (cbStart <= 9 || pbStart[9] == 0x59);
81+
}
82+
83+
84+
RTDECL(bool) RTZipXzIsStartOfCompressedStream(uint8_t const *pbStart, size_t cbStart)
85+
{
86+
/* The XZ magic is 6 bytes long. */
87+
return cbStart >= 6
88+
&& pbStart[0] == 0xfd
89+
&& pbStart[1] == 0x37
90+
&& pbStart[2] == 0x7a
91+
&& pbStart[3] == 0x58
92+
&& pbStart[4] == 0x5a
93+
&& pbStart[5] == 0x00;
94+
}
95+
96+

‎src/VBox/Runtime/common/zip/tarcmd.cpp‎

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $Id: tarcmd.cpp 111646 2025年11月12日 09:34:43Z knut.osmundsen@oracle.com $ */
1+
/* $Id: tarcmd.cpp 111661 2025年11月12日 12:00:49Z knut.osmundsen@oracle.com $ */
22
/** @file
33
* IPRT - A mini TAR Command.
44
*/
@@ -865,6 +865,47 @@ static RTEXITCODE rtZipTarCmdOpenInputArchive(PRTZIPTARCMDOPS pOpts, PRTVFSFSSTR
865865
return RTMsgErrorExitFailure("Failed to prepare standard in for reading: %Rrc", rc);
866866
}
867867

868+
/*
869+
* If no decompressor was specified and the stream is a seekable file, we
870+
* will try detect if the input is compressed and which decompressor to use.
871+
*/
872+
if (pOpts->chZipper == '0円')
873+
{
874+
RTVFSFILE hVfsFile = RTVfsIoStrmToFile(hVfsIos);
875+
if (hVfsFile != NIL_RTVFSFILE)
876+
{
877+
rc = RTVfsFileSeek(hVfsFile, 0, RTFILE_SEEK_CURRENT, NULL);
878+
if (RT_SUCCESS(rc))
879+
{
880+
uint8_t abFirstBytes[16];
881+
size_t cbFirstBytes = 0;
882+
rc = RTVfsFileRead(hVfsFile, &abFirstBytes, sizeof(abFirstBytes), &cbFirstBytes);
883+
if (RT_SUCCESS(rc))
884+
{
885+
rc = RTVfsFileSeek(hVfsFile, -(RTFOFF)cbFirstBytes, RTFILE_SEEK_CURRENT, NULL);
886+
if (RT_SUCCESS(rc))
887+
{
888+
if (RTZipGzipIsStartOfCompressedStream(abFirstBytes, cbFirstBytes))
889+
pOpts->chZipper = 'z';
890+
else if (RTZipXzIsStartOfCompressedStream(abFirstBytes, cbFirstBytes))
891+
pOpts->chZipper = 'J';
892+
else if (RTZipBzip2IsStartOfCompressedStream(abFirstBytes, cbFirstBytes))
893+
pOpts->chZipper = 'j';
894+
}
895+
else
896+
RTMsgErrorExitFailure("Failed to rewind the input after compression detection: %Rrc", rc);
897+
}
898+
else
899+
RTMsgErrorExitFailure("Failed to read the first bytes of the input: %Rrc", rc);
900+
if (RT_FAILURE(rc))
901+
{
902+
RTVfsIoStrmRelease(hVfsIos);
903+
return RTEXITCODE_FAILURE;
904+
}
905+
}
906+
}
907+
}
908+
868909
/*
869910
* Pass it thru a decompressor?
870911
*/

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /