Fossil SCM

Use a Blob object rather than a custom printf function in order to construct the PAX header for tarballs.

drh 2011-07-24 19:47 UTC ge-tarfix
Commit 02ce8b4a46822a7af941515516299701044750ad
1 file changed +26 -70
+26 -70
--- src/tar.c
+++ src/tar.c
@@ -28,13 +28,11 @@
2828
static struct tarball_t {
2929
unsigned char *aHdr; /* Space for building headers */
3030
char *zSpaces; /* Spaces for padding */
3131
char *zPrevDir; /* Name of directory for previous entry */
3232
int nPrevDirAlloc; /* size of zPrevDir */
33
- char *pScratch; /* scratch buffer used to build PAX data */
34
- int nScratchUsed; /* part of buffer containing data */
35
- int nScratchAlloc; /* size of buffer */
33
+ Blob pax; /* PAX data */
3634
} tball;
3735
3836
3937
/*
4038
** field lengths of 'ustar' name and prefix fields.
@@ -55,13 +53,11 @@
5553
tball.zSpaces = (char*)&tball.aHdr[512];
5654
/* zPrevDir init */
5755
tball.zPrevDir = NULL;
5856
tball.nPrevDirAlloc = 0;
5957
/* scratch buffer init */
60
- tball.pScratch = NULL;
61
- tball.nScratchUsed = 0;
62
- tball.nScratchAlloc = 0;
58
+ blob_zero(&tball.pax);
6359
6460
memcpy(&tball.aHdr[108], "0000000", 8); /* Owner ID */
6561
memcpy(&tball.aHdr[116], "0000000", 8); /* Group ID */
6662
memcpy(&tball.aHdr[257], "ustar\00000", 8); /* POSIX.1 format */
6763
memcpy(&tball.aHdr[265], "nobody", 7); /* Owner name */
@@ -70,48 +66,10 @@
7066
db_multi_exec(
7167
"CREATE TEMP TABLE dir(name UNIQUE);"
7268
);
7369
}
7470
75
-
76
-/*
77
-** print to the scratch buffer
78
-**
79
-** used to build the Pax Interchange Format data, and create
80
-** pseudo-file names for the header data.
81
-**
82
-** The buffer is grown automatically to accommodate the data.
83
-*/
84
-static int scratch_printf(
85
- const char *fmt,
86
- ...
87
-){
88
- for(;;){
89
- int newSize, minSpace, n;
90
- /* calculate space in buffer */
91
- int space = tball.nScratchAlloc - tball.nScratchUsed;
92
- /* format the string */
93
- va_list vl;
94
- va_start(vl, fmt);
95
- n = vsnprintf(&tball.pScratch[tball.nScratchUsed], space, fmt, vl);
96
- assert(n >= 0);
97
- va_end(vl);
98
- /* if it fit we're done */
99
- if(n < space)
100
- return n;
101
- /* buffer too short: calculate reasonable new size */
102
- minSpace = tball.nScratchUsed+n+1;
103
- newSize = 2 * tball.nScratchAlloc;
104
- if(newSize < minSpace)
105
- newSize = minSpace;
106
- /* grow the buffer */
107
- tball.pScratch = fossil_realloc(tball.pScratch, newSize);
108
- tball.nScratchAlloc = newSize;
109
- /* loop to try again */
110
- }
111
-}
112
-
11371
11472
/*
11573
** verify that lla characters in 'zName' are in the
11674
** ISO646 (=ASCII) character set.
11775
*/
@@ -120,12 +78,11 @@
12078
int nName /* path length */
12179
){
12280
int i;
12381
for(i = 0; i < nName; i++){
12482
unsigned char c = (unsigned char)zName[i];
125
- if(c > 0x7e)
126
- return 0;
83
+ if( c>0x7e ) return 0;
12784
}
12885
return 1;
12986
}
13087
13188
@@ -194,12 +151,11 @@
194151
for(i = 1; i+1 < nName; i++)
195152
if(zName[i] == '/'){
196153
split = i+1;
197154
/* if the split position is within USTAR_NAME_LEN bytes from
198155
* the end we can quit */
199
- if(nName - split <= USTAR_NAME_LEN)
200
- break;
156
+ if(nName - split <= USTAR_NAME_LEN) break;
201157
}
202158
}
203159
return split;
204160
}
205161
@@ -214,12 +170,13 @@
214170
char *pName, /* name field */
215171
char *pPrefix /* prefix field */
216172
){
217173
int split = find_split_pos(zName, nName);
218174
/* check whether both pieces fit */
219
- if(nName - split > USTAR_NAME_LEN || split > USTAR_PREFIX_LEN+1)
175
+ if(nName - split > USTAR_NAME_LEN || split > USTAR_PREFIX_LEN+1){
220176
return 0; /* no */
177
+ }
221178
222179
/* extract name */
223180
padded_copy(pName, USTAR_NAME_LEN, &zName[split], nName - split);
224181
225182
/* extract prefix */
@@ -242,17 +199,17 @@
242199
int bHeader /* is this a 'x' type tar header? */
243200
){
244201
int split;
245202
246203
/* if this is a Pax Interchange header prepend "PaxHeader/"
247
- * so we can tell files apart from metadata */
248
- if(bHeader){
249
- int n;
250
- tball.nScratchUsed = 0;
251
- n = scratch_printf("PaxHeader/%*.*s", nName, nName, zName);
252
- zName = tball.pScratch;
253
- nName = n;
204
+ ** so we can tell files apart from metadata */
205
+ if( bHeader ){
206
+ int n;
207
+ blob_reset(&tball.pax);
208
+ blob_appendf(&tball.pax, "PaxHeader/%*.*s", nName, nName, zName);
209
+ zName = blob_buffer(&tball.pax);
210
+ nName = blob_size(&tball.pax);
254211
}
255212
256213
/* find the split position */
257214
split = find_split_pos(zName, nName);
258215
@@ -284,19 +241,19 @@
284241
for(n = blen; n > 0; ){
285242
blen++; next10 *= 10;
286243
n /= 10;
287244
}
288245
/* adding the length extended the length field? */
289
- if(blen > next10)
246
+ if(blen > next10){
290247
blen++;
248
+ }
291249
/* build the string */
292
- n = scratch_printf("%d %s=%*.*s\n", blen, zField, nValue, nValue, zValue);
250
+ blob_appendf(&tball.pax, "%d %s=%*.*s\n", blen, zField, nValue, nValue, zValue);
293251
/* this _must_ be right */
294
- if(n != blen)
252
+ if(blob_size(&tball.pax) != blen){
295253
fossil_fatal("internal error: PAX tar header has bad length");
296
- /* add length to scratch buffer */
297
- tball.nScratchUsed += blen;
254
+ }
298255
}
299256
300257
301258
/*
302259
** set the header type, calculate the checksum and output
@@ -338,22 +295,24 @@
338295
int lastPage;
339296
/* add a file name for interoperability with older programs */
340297
approximate_split_path(zName, nName, tball.aHdr, &tball.aHdr[345], 1);
341298
342299
/* generate the Pax Interchange path header */
343
- tball.nScratchUsed = 0;
300
+ blob_reset(&tball.pax);
344301
add_pax_header("path", zName, nName);
345302
346303
/* set the header length, and write the header */
347
- sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o", tball.nScratchUsed);
304
+ sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o",
305
+ blob_size(&tball.pax));
348306
cksum_and_write_header('x');
349307
350308
/* write the Pax Interchange data */
351
- gzip_step(tball.pScratch, tball.nScratchUsed);
352
- lastPage = tball.nScratchUsed % 512;
353
- if( lastPage!=0 )
309
+ gzip_step(blob_buffer(&tball.pax), blob_size(&tball.pax));
310
+ lastPage = blob_size(&tball.pax) % 512;
311
+ if( lastPage!=0 ){
354312
gzip_step(tball.zSpaces, 512 - lastPage);
313
+ }
355314
356315
/* generate an approximate path for the regular header */
357316
approximate_split_path(zName, nName, tball.aHdr, &tball.aHdr[345], 0);
358317
}
359318
/* set the size */
@@ -431,14 +390,11 @@
431390
fossil_free(tball.aHdr);
432391
tball.aHdr = 0;
433392
fossil_free(tball.zPrevDir);
434393
tball.zPrevDir = NULL;
435394
tball.nPrevDirAlloc = 0;
436
- fossil_free(tball.pScratch);
437
- tball.pScratch = NULL;
438
- tball.nScratchUsed = 0;
439
- tball.nScratchAlloc = 0;
395
+ blob_reset(&tball.pax);
440396
}
441397
442398
443399
/*
444400
** COMMAND: test-tarball
445401
--- src/tar.c
+++ src/tar.c
@@ -28,13 +28,11 @@
28 static struct tarball_t {
29 unsigned char *aHdr; /* Space for building headers */
30 char *zSpaces; /* Spaces for padding */
31 char *zPrevDir; /* Name of directory for previous entry */
32 int nPrevDirAlloc; /* size of zPrevDir */
33 char *pScratch; /* scratch buffer used to build PAX data */
34 int nScratchUsed; /* part of buffer containing data */
35 int nScratchAlloc; /* size of buffer */
36 } tball;
37
38
39 /*
40 ** field lengths of 'ustar' name and prefix fields.
@@ -55,13 +53,11 @@
55 tball.zSpaces = (char*)&tball.aHdr[512];
56 /* zPrevDir init */
57 tball.zPrevDir = NULL;
58 tball.nPrevDirAlloc = 0;
59 /* scratch buffer init */
60 tball.pScratch = NULL;
61 tball.nScratchUsed = 0;
62 tball.nScratchAlloc = 0;
63
64 memcpy(&tball.aHdr[108], "0000000", 8); /* Owner ID */
65 memcpy(&tball.aHdr[116], "0000000", 8); /* Group ID */
66 memcpy(&tball.aHdr[257], "ustar\00000", 8); /* POSIX.1 format */
67 memcpy(&tball.aHdr[265], "nobody", 7); /* Owner name */
@@ -70,48 +66,10 @@
70 db_multi_exec(
71 "CREATE TEMP TABLE dir(name UNIQUE);"
72 );
73 }
74
75
76 /*
77 ** print to the scratch buffer
78 **
79 ** used to build the Pax Interchange Format data, and create
80 ** pseudo-file names for the header data.
81 **
82 ** The buffer is grown automatically to accommodate the data.
83 */
84 static int scratch_printf(
85 const char *fmt,
86 ...
87 ){
88 for(;;){
89 int newSize, minSpace, n;
90 /* calculate space in buffer */
91 int space = tball.nScratchAlloc - tball.nScratchUsed;
92 /* format the string */
93 va_list vl;
94 va_start(vl, fmt);
95 n = vsnprintf(&tball.pScratch[tball.nScratchUsed], space, fmt, vl);
96 assert(n >= 0);
97 va_end(vl);
98 /* if it fit we're done */
99 if(n < space)
100 return n;
101 /* buffer too short: calculate reasonable new size */
102 minSpace = tball.nScratchUsed+n+1;
103 newSize = 2 * tball.nScratchAlloc;
104 if(newSize < minSpace)
105 newSize = minSpace;
106 /* grow the buffer */
107 tball.pScratch = fossil_realloc(tball.pScratch, newSize);
108 tball.nScratchAlloc = newSize;
109 /* loop to try again */
110 }
111 }
112
113
114 /*
115 ** verify that lla characters in 'zName' are in the
116 ** ISO646 (=ASCII) character set.
117 */
@@ -120,12 +78,11 @@
120 int nName /* path length */
121 ){
122 int i;
123 for(i = 0; i < nName; i++){
124 unsigned char c = (unsigned char)zName[i];
125 if(c > 0x7e)
126 return 0;
127 }
128 return 1;
129 }
130
131
@@ -194,12 +151,11 @@
194 for(i = 1; i+1 < nName; i++)
195 if(zName[i] == '/'){
196 split = i+1;
197 /* if the split position is within USTAR_NAME_LEN bytes from
198 * the end we can quit */
199 if(nName - split <= USTAR_NAME_LEN)
200 break;
201 }
202 }
203 return split;
204 }
205
@@ -214,12 +170,13 @@
214 char *pName, /* name field */
215 char *pPrefix /* prefix field */
216 ){
217 int split = find_split_pos(zName, nName);
218 /* check whether both pieces fit */
219 if(nName - split > USTAR_NAME_LEN || split > USTAR_PREFIX_LEN+1)
220 return 0; /* no */
 
221
222 /* extract name */
223 padded_copy(pName, USTAR_NAME_LEN, &zName[split], nName - split);
224
225 /* extract prefix */
@@ -242,17 +199,17 @@
242 int bHeader /* is this a 'x' type tar header? */
243 ){
244 int split;
245
246 /* if this is a Pax Interchange header prepend "PaxHeader/"
247 * so we can tell files apart from metadata */
248 if(bHeader){
249 int n;
250 tball.nScratchUsed = 0;
251 n = scratch_printf("PaxHeader/%*.*s", nName, nName, zName);
252 zName = tball.pScratch;
253 nName = n;
254 }
255
256 /* find the split position */
257 split = find_split_pos(zName, nName);
258
@@ -284,19 +241,19 @@
284 for(n = blen; n > 0; ){
285 blen++; next10 *= 10;
286 n /= 10;
287 }
288 /* adding the length extended the length field? */
289 if(blen > next10)
290 blen++;
 
291 /* build the string */
292 n = scratch_printf("%d %s=%*.*s\n", blen, zField, nValue, nValue, zValue);
293 /* this _must_ be right */
294 if(n != blen)
295 fossil_fatal("internal error: PAX tar header has bad length");
296 /* add length to scratch buffer */
297 tball.nScratchUsed += blen;
298 }
299
300
301 /*
302 ** set the header type, calculate the checksum and output
@@ -338,22 +295,24 @@
338 int lastPage;
339 /* add a file name for interoperability with older programs */
340 approximate_split_path(zName, nName, tball.aHdr, &tball.aHdr[345], 1);
341
342 /* generate the Pax Interchange path header */
343 tball.nScratchUsed = 0;
344 add_pax_header("path", zName, nName);
345
346 /* set the header length, and write the header */
347 sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o", tball.nScratchUsed);
 
348 cksum_and_write_header('x');
349
350 /* write the Pax Interchange data */
351 gzip_step(tball.pScratch, tball.nScratchUsed);
352 lastPage = tball.nScratchUsed % 512;
353 if( lastPage!=0 )
354 gzip_step(tball.zSpaces, 512 - lastPage);
 
355
356 /* generate an approximate path for the regular header */
357 approximate_split_path(zName, nName, tball.aHdr, &tball.aHdr[345], 0);
358 }
359 /* set the size */
@@ -431,14 +390,11 @@
431 fossil_free(tball.aHdr);
432 tball.aHdr = 0;
433 fossil_free(tball.zPrevDir);
434 tball.zPrevDir = NULL;
435 tball.nPrevDirAlloc = 0;
436 fossil_free(tball.pScratch);
437 tball.pScratch = NULL;
438 tball.nScratchUsed = 0;
439 tball.nScratchAlloc = 0;
440 }
441
442
443 /*
444 ** COMMAND: test-tarball
445
--- src/tar.c
+++ src/tar.c
@@ -28,13 +28,11 @@
28 static struct tarball_t {
29 unsigned char *aHdr; /* Space for building headers */
30 char *zSpaces; /* Spaces for padding */
31 char *zPrevDir; /* Name of directory for previous entry */
32 int nPrevDirAlloc; /* size of zPrevDir */
33 Blob pax; /* PAX data */
 
 
34 } tball;
35
36
37 /*
38 ** field lengths of 'ustar' name and prefix fields.
@@ -55,13 +53,11 @@
53 tball.zSpaces = (char*)&tball.aHdr[512];
54 /* zPrevDir init */
55 tball.zPrevDir = NULL;
56 tball.nPrevDirAlloc = 0;
57 /* scratch buffer init */
58 blob_zero(&tball.pax);
 
 
59
60 memcpy(&tball.aHdr[108], "0000000", 8); /* Owner ID */
61 memcpy(&tball.aHdr[116], "0000000", 8); /* Group ID */
62 memcpy(&tball.aHdr[257], "ustar\00000", 8); /* POSIX.1 format */
63 memcpy(&tball.aHdr[265], "nobody", 7); /* Owner name */
@@ -70,48 +66,10 @@
66 db_multi_exec(
67 "CREATE TEMP TABLE dir(name UNIQUE);"
68 );
69 }
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
72 /*
73 ** verify that lla characters in 'zName' are in the
74 ** ISO646 (=ASCII) character set.
75 */
@@ -120,12 +78,11 @@
78 int nName /* path length */
79 ){
80 int i;
81 for(i = 0; i < nName; i++){
82 unsigned char c = (unsigned char)zName[i];
83 if( c>0x7e ) return 0;
 
84 }
85 return 1;
86 }
87
88
@@ -194,12 +151,11 @@
151 for(i = 1; i+1 < nName; i++)
152 if(zName[i] == '/'){
153 split = i+1;
154 /* if the split position is within USTAR_NAME_LEN bytes from
155 * the end we can quit */
156 if(nName - split <= USTAR_NAME_LEN) break;
 
157 }
158 }
159 return split;
160 }
161
@@ -214,12 +170,13 @@
170 char *pName, /* name field */
171 char *pPrefix /* prefix field */
172 ){
173 int split = find_split_pos(zName, nName);
174 /* check whether both pieces fit */
175 if(nName - split > USTAR_NAME_LEN || split > USTAR_PREFIX_LEN+1){
176 return 0; /* no */
177 }
178
179 /* extract name */
180 padded_copy(pName, USTAR_NAME_LEN, &zName[split], nName - split);
181
182 /* extract prefix */
@@ -242,17 +199,17 @@
199 int bHeader /* is this a 'x' type tar header? */
200 ){
201 int split;
202
203 /* if this is a Pax Interchange header prepend "PaxHeader/"
204 ** so we can tell files apart from metadata */
205 if( bHeader ){
206 int n;
207 blob_reset(&tball.pax);
208 blob_appendf(&tball.pax, "PaxHeader/%*.*s", nName, nName, zName);
209 zName = blob_buffer(&tball.pax);
210 nName = blob_size(&tball.pax);
211 }
212
213 /* find the split position */
214 split = find_split_pos(zName, nName);
215
@@ -284,19 +241,19 @@
241 for(n = blen; n > 0; ){
242 blen++; next10 *= 10;
243 n /= 10;
244 }
245 /* adding the length extended the length field? */
246 if(blen > next10){
247 blen++;
248 }
249 /* build the string */
250 blob_appendf(&tball.pax, "%d %s=%*.*s\n", blen, zField, nValue, nValue, zValue);
251 /* this _must_ be right */
252 if(blob_size(&tball.pax) != blen){
253 fossil_fatal("internal error: PAX tar header has bad length");
254 }
 
255 }
256
257
258 /*
259 ** set the header type, calculate the checksum and output
@@ -338,22 +295,24 @@
295 int lastPage;
296 /* add a file name for interoperability with older programs */
297 approximate_split_path(zName, nName, tball.aHdr, &tball.aHdr[345], 1);
298
299 /* generate the Pax Interchange path header */
300 blob_reset(&tball.pax);
301 add_pax_header("path", zName, nName);
302
303 /* set the header length, and write the header */
304 sqlite3_snprintf(12, (char*)&tball.aHdr[124], "%011o",
305 blob_size(&tball.pax));
306 cksum_and_write_header('x');
307
308 /* write the Pax Interchange data */
309 gzip_step(blob_buffer(&tball.pax), blob_size(&tball.pax));
310 lastPage = blob_size(&tball.pax) % 512;
311 if( lastPage!=0 ){
312 gzip_step(tball.zSpaces, 512 - lastPage);
313 }
314
315 /* generate an approximate path for the regular header */
316 approximate_split_path(zName, nName, tball.aHdr, &tball.aHdr[345], 0);
317 }
318 /* set the size */
@@ -431,14 +390,11 @@
390 fossil_free(tball.aHdr);
391 tball.aHdr = 0;
392 fossil_free(tball.zPrevDir);
393 tball.zPrevDir = NULL;
394 tball.nPrevDirAlloc = 0;
395 blob_reset(&tball.pax);
 
 
 
396 }
397
398
399 /*
400 ** COMMAND: test-tarball
401

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button