Skip to content

Commit 0d38d74

Browse files
author
Greg Beaver
committed
add unfinished experimental tar support (may not lead anywhere)
1 parent e4c2bc1 commit 0d38d74

File tree

7 files changed

+499
-5
lines changed

7 files changed

+499
-5
lines changed

ext/phar/config.m4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ PHP_ARG_ENABLE(phar, for phar support/phar zlib support,
55
[ --enable-phar Enable phar support, use --with-zlib-dir if zlib detection fails])
66

77
if test "$PHP_PHAR" != "no"; then
8-
PHP_NEW_EXTENSION(phar, phar.c phar_object.c phar_path_check.c, $ext_shared)
8+
PHP_NEW_EXTENSION(phar, phar.c phar_object.c phar_path_check.c phar2.c phar2_openhash.c, $ext_shared)
99
PHP_ADD_EXTENSION_DEP(phar, zlib, false)
1010
PHP_ADD_EXTENSION_DEP(phar, bz2, false)
1111
PHP_ADD_EXTENSION_DEP(phar, spl, false)

ext/phar/phar.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#define PHAR_MAIN
2323
#include "phar_internal.h"
24+
#include "phar2.h"
2425
#include "SAPI.h"
2526

2627
ZEND_DECLARE_MODULE_GLOBALS(phar)
@@ -947,6 +948,10 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int
947948
}
948949
return FAILURE;
949950
}
951+
if ((manifest_ver & PHAR_API_MAJORVERSION) == PHAR_API_MAJORVERSION) {
952+
/* this is a phar in tar format */
953+
return phar2_open_file(fp, fname, fname_len, alias, alias_len, halt_offset, pphar, savebuf, error TSRMLS_CC);
954+
}
950955

951956
PHAR_GET_32(buffer, manifest_flags);
952957

ext/phar/phar2.c

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| phar php single-file executable PHP extension |
4+
+----------------------------------------------------------------------+
5+
| Copyright (c) 2006-2007 The PHP Group |
6+
+----------------------------------------------------------------------+
7+
| This source file is subject to version 3.01 of the PHP license, |
8+
| that is bundled with this package in the file LICENSE, and is |
9+
| available through the world-wide-web at the following url: |
10+
| http://www.php.net/license/3_01.txt. |
11+
| If you did not receive a copy of the PHP license and are unable to |
12+
| obtain it through the world-wide-web, please send a note to |
13+
| license@php.net so we can mail you a copy immediately. |
14+
+----------------------------------------------------------------------+
15+
| Authors: Gregory Beaver <cellog@php.net> |
16+
| Marcus Boerger <helly@php.net> |
17+
| based on work by Dmitry Stogov <dmitry@zend.com> |
18+
+----------------------------------------------------------------------+
19+
*/
20+
21+
/* $Id$ */
22+
23+
#include "phar_internal.h"
24+
25+
26+
#define TAR_FILE '0'
27+
#define TAR_LINK '1'
28+
#define TAR_SYMLINK '2'
29+
#define TAR_DIR '5'
30+
#define TAR_NEW '8'
31+
32+
/**
33+
* the format of the header block for a file, in the older UNIX-compatible
34+
* TAR format
35+
*/
36+
typedef struct _old_tar_header { /* {{{ */
37+
char name[100]; /* name of file;
38+
directory is indicated by a trailing slash (/) */
39+
char mode[8]; /* file mode */
40+
char uid[8]; /* owner user ID */
41+
char gid[8]; /* owner group ID */
42+
char size[12]; /* length of file in bytes */
43+
char mtime[12]; /* modify time of file */
44+
char chksum[8]; /* checksum for header */
45+
char link; /* indicator for links;
46+
1 for a linked file,
47+
2 for a symbolic link,
48+
0 otherwise */
49+
char linkname[100]; /* name of linked file */
50+
} old_tar_header;
51+
/* }}} */
52+
53+
/**
54+
* the new USTAR header format.
55+
* Note that tar can determine that the USTAR format is being used by the
56+
* presence of the null-terminated string "ustar" in the magic field.
57+
*/
58+
typedef struct _tar_header { /* {{{ */
59+
char name[100]; /* name of file */
60+
char mode[8]; /* file mode */
61+
char uid[8]; /* owner user ID */
62+
char gid[8]; /* owner group ID */
63+
char size[12]; /* length of file in bytes */
64+
char mtime[12]; /* modify time of file */
65+
char chksum[8]; /* checksum for header */
66+
char typeflag; /* type of file
67+
0 Regular file
68+
1 Link to another file already archived
69+
2 Symbolic link
70+
3 Character special device
71+
4 Block special device
72+
5 Directory
73+
6 FIFO special file
74+
7 Reserved */
75+
char linkname[100]; /* name of linked file */
76+
char magic[6]; /* USTAR indicator */
77+
char version[2]; /* USTAR version */
78+
char uname[32]; /* owner user name */
79+
char gname[32]; /* owner group name */
80+
char devmajor[8]; /* device major number */
81+
char devminor[8]; /* device minor number */
82+
char prefix[155]; /* prefix for file name;
83+
the value of the prefix field, if non-null,
84+
is prefixed to the name field to allow names
85+
longer then 100 characters */
86+
} tar_header;
87+
/* }}} */
88+
89+
typedef struct _tar_file tar_file;
90+
91+
typedef struct _tar_entry { /* {{{ */
92+
tar_file *tar;
93+
char type;
94+
off_t start;
95+
off_t pos;
96+
off_t size;
97+
mode_t mode;
98+
time_t mtime;
99+
uid_t uid;
100+
gid_t gid;
101+
union {
102+
HashTable *content;
103+
char *link;
104+
} u;
105+
} tar_entry;
106+
/* }}} */
107+
108+
struct _tar_file { /* {{{ */
109+
php_stream *stream;
110+
char *real_name;
111+
int refcount;
112+
int opened;
113+
tar_entry root;
114+
};
115+
/* }}} */
116+
117+
static int tar_number(char* buf, int len) /* {{{ */
118+
{
119+
int num = 0;
120+
int i = 0;
121+
122+
while (i < len && buf[i] == ' ') {
123+
i++;
124+
}
125+
while (i < len &&
126+
buf[i] >= '0' &&
127+
buf[i] <= '7') {
128+
num = num * 8 + (buf[i] - '0');
129+
i++;
130+
}
131+
return num;
132+
}
133+
/* }}} */
134+
135+
static int tar_checksum(char* buf, int len) /* {{{ */
136+
{
137+
int sum = 0;
138+
char *end = buf + len;
139+
140+
while (buf != end) {
141+
sum += (unsigned char)*buf;
142+
buf++;
143+
}
144+
return sum;
145+
}
146+
/* }}} */
147+
#define MAPPHAR_ALLOC_FAIL(msg) \
148+
php_stream_close(fp);\
149+
if (error) {\
150+
spprintf(error, 0, msg, fname);\
151+
}\
152+
return FAILURE;
153+
154+
#ifdef WORDS_BIGENDIAN
155+
# define PHAR_GET_32(buffer, var) \
156+
var = ((((unsigned char*)(buffer))[3]) << 24) \
157+
| ((((unsigned char*)(buffer))[2]) << 16) \
158+
| ((((unsigned char*)(buffer))[1]) << 8) \
159+
| (((unsigned char*)(buffer))[0]); \
160+
(buffer) += 4
161+
# define PHAR_GET_16(buffer, var) \
162+
var = ((((unsigned char*)(buffer))[1]) << 8) \
163+
| (((unsigned char*)(buffer))[0]); \
164+
(buffer) += 2
165+
#else
166+
# define PHAR_GET_32(buffer, var) \
167+
var = *(php_uint32*)(buffer); \
168+
buffer += 4
169+
# define PHAR_GET_16(buffer, var) \
170+
var = *(php_uint16*)(buffer); \
171+
buffer += 2
172+
#endif
173+
174+
int phar2_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int alias_len, long halt_offset, phar_archive_data** pphar, char *buffer, char **error TSRMLS_DC) /* {{{ */
175+
{
176+
/* The structure of a tar-based phar archive is as follows:
177+
- the first file contains the loader stub and file hash. The file hash is a mapping
178+
of filename hash to location of manifest data within the official phar manifest using
179+
an implementation of open hash that allows the entire thing to be read in without any
180+
processing beyond signature check.
181+
- the second file contains the official phar manifest as used in phar 1.x
182+
- third file to second-to-last file contain the phar's files
183+
- final file contains the phar signature
184+
*/
185+
php_uint32 openhash_len;
186+
phar_archive_data *mydata;
187+
188+
buffer += 6;
189+
PHAR_GET_32(buffer), openhash_len);
190+
if (openhash_len != sizeof(phar2_openhash) && openhash_len != sizeof(phar2_openhash_large)) {
191+
MAPPHAR_ALLOC_FAIL("Corrupted phar2 archive, filename hash is wrong size in phar \"%s\"");
192+
}
193+
buffer -= 6;
194+
buffer = (char *) erealloc((void *) buffer, openhash_len);
195+
if (!buffer) {
196+
MAPPHAR_ALLOC_FAIL("Could not allocate space for fast filename hash in phar \"%s\"");
197+
}
198+
if (openhash_len != php_stream_read(fp, buffer, openhash_len)) {
199+
MAPPHAR_ALLOC_FAIL("Could not read fast filename hash in phar \"%s\"");
200+
}
201+
202+
PHAR_G(fast_fname_map) = (phar2_openhash *) buffer;
203+
mydata = ecalloc(sizeof(phar_archive_data), 1);
204+
205+
/* check whether we have meta data, zero check works regardless of byte order */
206+
if (phar_parse_metadata(fp, &buffer, endbuffer, &mydata->metadata TSRMLS_CC) == FAILURE) {
207+
MAPPHAR_FAIL("unable to read phar metadata in .phar file \"%s\"");
208+
}
209+
210+
/* set up our manifest - entries will be created JIT as accessed */
211+
zend_hash_init(&mydata->manifest, sizeof(phar_entry_info),
212+
zend_get_hash_value, destroy_phar_manifest, 0);
213+
snprintf(mydata->version, sizeof(mydata->version), "%u.%u.%u", manifest_ver >> 12, (manifest_ver >> 8) & 0xF, (manifest_ver >> 4) & 0xF);
214+
mydata->internal_file_start = halt_offset + manifest_len + 4;
215+
mydata->halt_offset = halt_offset;
216+
mydata->flags = manifest_flags;
217+
mydata->fp = fp;
218+
mydata->fname = estrndup(fname, fname_len);
219+
#ifdef PHP_WIN32
220+
phar_unixify_path_separators(mydata->fname, fname_len);
221+
#endif
222+
mydata->fname_len = fname_len;
223+
mydata->alias = alias ? estrndup(alias, alias_len) : mydata->fname;
224+
mydata->alias_len = alias ? alias_len : fname_len;
225+
mydata->sig_flags = sig_flags;
226+
mydata->sig_len = sig_len;
227+
mydata->signature = signature;
228+
phar_request_initialize(TSRMLS_C);
229+
zend_hash_add(&(PHAR_GLOBALS->phar_fname_map), mydata->fname, fname_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
230+
if (register_alias) {
231+
mydata->is_explicit_alias = 1;
232+
zend_hash_add(&(PHAR_GLOBALS->phar_alias_map), alias, alias_len, (void*)&mydata, sizeof(phar_archive_data*), NULL);
233+
} else {
234+
mydata->is_explicit_alias = 0;
235+
}
236+
efree(savebuf);
237+
238+
if (pphar) {
239+
*pphar = mydata;
240+
}
241+
242+
return SUCCESS;
243+
}
244+
/* }}} */

ext/phar/phar2.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| phar php single-file executable PHP extension |
4+
+----------------------------------------------------------------------+
5+
| Copyright (c) 2006-2007 The PHP Group |
6+
+----------------------------------------------------------------------+
7+
| This source file is subject to version 3.01 of the PHP license, |
8+
| that is bundled with this package in the file LICENSE, and is |
9+
| available through the world-wide-web at the following url: |
10+
| http://www.php.net/license/3_01.txt. |
11+
| If you did not receive a copy of the PHP license and are unable to |
12+
| obtain it through the world-wide-web, please send a note to |
13+
| license@php.net so we can mail you a copy immediately. |
14+
+----------------------------------------------------------------------+
15+
| Authors: Gregory Beaver <cellog@php.net> |
16+
| Marcus Boerger <helly@php.net> |
17+
+----------------------------------------------------------------------+
18+
*/
19+
20+
/* $Id$ */
21+
BEGIN_EXTERN_C()
22+
23+
int phar2_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int alias_len, long halt_offset, phar_archive_data** pphar, char *buffer, char **error TSRMLS_DC);
24+
25+
END_EXTERN_C()
26+
27+
/*
28+
* Local variables:
29+
* tab-width: 4
30+
* c-basic-offset: 4
31+
* End:
32+
* vim600: noet sw=4 ts=4 fdm=marker
33+
* vim<600: noet sw=4 ts=4
34+
*/

0 commit comments

Comments
 (0)