4
4
#include "cache.h"
5
5
#include "tar.h"
6
6
#include "archive.h"
7
+ #include "streaming.h"
7
8
#include "run-command.h"
8
9
9
10
#define RECORDSIZE (512)
@@ -30,10 +31,9 @@ static void write_if_needed(void)
30
31
* queues up writes, so that all our write(2) calls write exactly one
31
32
* full block; pads writes to RECORDSIZE
32
33
*/
33
- static void write_blocked (const void * data , unsigned long size )
34
+ static void do_write_blocked (const void * data , unsigned long size )
34
35
{
35
36
const char * buf = data ;
36
- unsigned long tail ;
37
37
38
38
if (offset ) {
39
39
unsigned long chunk = BLOCKSIZE - offset ;
@@ -54,6 +54,11 @@ static void write_blocked(const void *data, unsigned long size)
54
54
memcpy (block + offset , buf , size );
55
55
offset += size ;
56
56
}
57
+ }
58
+
59
+ static void finish_record (void )
60
+ {
61
+ unsigned long tail ;
57
62
tail = offset % RECORDSIZE ;
58
63
if (tail ) {
59
64
memset (block + offset , 0 , RECORDSIZE - tail );
@@ -62,6 +67,12 @@ static void write_blocked(const void *data, unsigned long size)
62
67
write_if_needed ();
63
68
}
64
69
70
+ static void write_blocked (const void * data , unsigned long size )
71
+ {
72
+ do_write_blocked (data , size );
73
+ finish_record ();
74
+ }
75
+
65
76
/*
66
77
* The end of tar archives is marked by 2*512 nul bytes and after that
67
78
* follows the rest of the block (if any).
@@ -77,6 +88,33 @@ static void write_trailer(void)
77
88
}
78
89
}
79
90
91
+ /*
92
+ * queues up writes, so that all our write(2) calls write exactly one
93
+ * full block; pads writes to RECORDSIZE
94
+ */
95
+ static int stream_blocked (const unsigned char * sha1 )
96
+ {
97
+ struct git_istream * st ;
98
+ enum object_type type ;
99
+ unsigned long sz ;
100
+ char buf [BLOCKSIZE ];
101
+ ssize_t readlen ;
102
+
103
+ st = open_istream (sha1 , & type , & sz , NULL );
104
+ if (!st )
105
+ return error ("cannot stream blob %s" , sha1_to_hex (sha1 ));
106
+ for (;;) {
107
+ readlen = read_istream (st , buf , sizeof (buf ));
108
+ if (readlen <= 0 )
109
+ break ;
110
+ do_write_blocked (buf , readlen );
111
+ }
112
+ close_istream (st );
113
+ if (!readlen )
114
+ finish_record ();
115
+ return readlen ;
116
+ }
117
+
80
118
/*
81
119
* pax extended header records have the format "%u %s=%s\n". %u contains
82
120
* the size of the whole string (including the %u), the first %s is the
@@ -123,56 +161,101 @@ static size_t get_path_prefix(const char *path, size_t pathlen, size_t maxlen)
123
161
return i ;
124
162
}
125
163
164
+ static void prepare_header (struct archiver_args * args ,
165
+ struct ustar_header * header ,
166
+ unsigned int mode , unsigned long size )
167
+ {
168
+ sprintf (header -> mode , "%07o" , mode & 07777 );
169
+ sprintf (header -> size , "%011lo" , S_ISREG (mode ) ? size : 0 );
170
+ sprintf (header -> mtime , "%011lo" , (unsigned long ) args -> time );
171
+
172
+ sprintf (header -> uid , "%07o" , 0 );
173
+ sprintf (header -> gid , "%07o" , 0 );
174
+ strlcpy (header -> uname , "root" , sizeof (header -> uname ));
175
+ strlcpy (header -> gname , "root" , sizeof (header -> gname ));
176
+ sprintf (header -> devmajor , "%07o" , 0 );
177
+ sprintf (header -> devminor , "%07o" , 0 );
178
+
179
+ memcpy (header -> magic , "ustar" , 6 );
180
+ memcpy (header -> version , "00" , 2 );
181
+
182
+ sprintf (header -> chksum , "%07o" , ustar_header_chksum (header ));
183
+ }
184
+
185
+ static int write_extended_header (struct archiver_args * args ,
186
+ const unsigned char * sha1 ,
187
+ const void * buffer , unsigned long size )
188
+ {
189
+ struct ustar_header header ;
190
+ unsigned int mode ;
191
+ memset (& header , 0 , sizeof (header ));
192
+ * header .typeflag = TYPEFLAG_EXT_HEADER ;
193
+ mode = 0100666 ;
194
+ sprintf (header .name , "%s.paxheader" , sha1_to_hex (sha1 ));
195
+ prepare_header (args , & header , mode , size );
196
+ write_blocked (& header , sizeof (header ));
197
+ write_blocked (buffer , size );
198
+ return 0 ;
199
+ }
200
+
126
201
static int write_tar_entry (struct archiver_args * args ,
127
- const unsigned char * sha1 , const char * path , size_t pathlen ,
128
- unsigned int mode , void * buffer , unsigned long size )
202
+ const unsigned char * sha1 ,
203
+ const char * path , size_t pathlen ,
204
+ unsigned int mode )
129
205
{
130
206
struct ustar_header header ;
131
207
struct strbuf ext_header = STRBUF_INIT ;
208
+ unsigned int old_mode = mode ;
209
+ unsigned long size ;
210
+ void * buffer ;
132
211
int err = 0 ;
133
212
134
213
memset (& header , 0 , sizeof (header ));
135
214
136
- if (!sha1 ) {
137
- * header .typeflag = TYPEFLAG_GLOBAL_HEADER ;
138
- mode = 0100666 ;
139
- strcpy (header .name , "pax_global_header" );
140
- } else if (!path ) {
141
- * header .typeflag = TYPEFLAG_EXT_HEADER ;
142
- mode = 0100666 ;
143
- sprintf (header .name , "%s.paxheader" , sha1_to_hex (sha1 ));
215
+ if (S_ISDIR (mode ) || S_ISGITLINK (mode )) {
216
+ * header .typeflag = TYPEFLAG_DIR ;
217
+ mode = (mode | 0777 ) & ~tar_umask ;
218
+ } else if (S_ISLNK (mode )) {
219
+ * header .typeflag = TYPEFLAG_LNK ;
220
+ mode |= 0777 ;
221
+ } else if (S_ISREG (mode )) {
222
+ * header .typeflag = TYPEFLAG_REG ;
223
+ mode = (mode | ((mode & 0100 ) ? 0777 : 0666 )) & ~tar_umask ;
144
224
} else {
145
- if (S_ISDIR (mode ) || S_ISGITLINK (mode )) {
146
- * header .typeflag = TYPEFLAG_DIR ;
147
- mode = (mode | 0777 ) & ~tar_umask ;
148
- } else if (S_ISLNK (mode )) {
149
- * header .typeflag = TYPEFLAG_LNK ;
150
- mode |= 0777 ;
151
- } else if (S_ISREG (mode )) {
152
- * header .typeflag = TYPEFLAG_REG ;
153
- mode = (mode | ((mode & 0100 ) ? 0777 : 0666 )) & ~tar_umask ;
225
+ return error ("unsupported file mode: 0%o (SHA1: %s)" ,
226
+ mode , sha1_to_hex (sha1 ));
227
+ }
228
+ if (pathlen > sizeof (header .name )) {
229
+ size_t plen = get_path_prefix (path , pathlen ,
230
+ sizeof (header .prefix ));
231
+ size_t rest = pathlen - plen - 1 ;
232
+ if (plen > 0 && rest <= sizeof (header .name )) {
233
+ memcpy (header .prefix , path , plen );
234
+ memcpy (header .name , path + plen + 1 , rest );
154
235
} else {
155
- return error ("unsupported file mode: 0%o (SHA1: %s)" ,
156
- mode , sha1_to_hex (sha1 ));
236
+ sprintf (header .name , "%s.data" ,
237
+ sha1_to_hex (sha1 ));
238
+ strbuf_append_ext_header (& ext_header , "path" ,
239
+ path , pathlen );
157
240
}
158
- if ( pathlen > sizeof ( header . name )) {
159
- size_t plen = get_path_prefix ( path , pathlen ,
160
- sizeof ( header . prefix ));
161
- size_t rest = pathlen - plen - 1 ;
162
- if ( plen > 0 && rest <= sizeof ( header . name )) {
163
- memcpy ( header . prefix , path , plen );
164
- memcpy ( header . name , path + plen + 1 , rest ) ;
165
- } else {
166
- sprintf ( header . name , "%s.data" ,
167
- sha1_to_hex ( sha1 ) );
168
- strbuf_append_ext_header ( & ext_header , "path" ,
169
- path , pathlen );
170
- }
171
- } else
172
- memcpy ( header . name , path , pathlen ) ;
241
+ } else
242
+ memcpy ( header . name , path , pathlen );
243
+
244
+ if ( S_ISREG ( mode ) && ! args -> convert &&
245
+ sha1_object_info ( sha1 , & size ) == OBJ_BLOB &&
246
+ size > big_file_threshold )
247
+ buffer = NULL ;
248
+ else if ( S_ISLNK ( mode ) || S_ISREG ( mode )) {
249
+ enum object_type type ;
250
+ buffer = sha1_file_to_archive ( args , path , sha1 , old_mode , & type , & size );
251
+ if (! buffer )
252
+ return error ( "cannot read %s" , sha1_to_hex ( sha1 ) );
253
+ } else {
254
+ buffer = NULL ;
255
+ size = 0 ;
173
256
}
174
257
175
- if (S_ISLNK (mode ) && buffer ) {
258
+ if (S_ISLNK (mode )) {
176
259
if (size > sizeof (header .linkname )) {
177
260
sprintf (header .linkname , "see %s.paxheader" ,
178
261
sha1_to_hex (sha1 ));
@@ -182,44 +265,44 @@ static int write_tar_entry(struct archiver_args *args,
182
265
memcpy (header .linkname , buffer , size );
183
266
}
184
267
185
- sprintf (header .mode , "%07o" , mode & 07777 );
186
- sprintf (header .size , "%011lo" , S_ISREG (mode ) ? size : 0 );
187
- sprintf (header .mtime , "%011lo" , (unsigned long ) args -> time );
188
-
189
- sprintf (header .uid , "%07o" , 0 );
190
- sprintf (header .gid , "%07o" , 0 );
191
- strlcpy (header .uname , "root" , sizeof (header .uname ));
192
- strlcpy (header .gname , "root" , sizeof (header .gname ));
193
- sprintf (header .devmajor , "%07o" , 0 );
194
- sprintf (header .devminor , "%07o" , 0 );
195
-
196
- memcpy (header .magic , "ustar" , 6 );
197
- memcpy (header .version , "00" , 2 );
198
-
199
- sprintf (header .chksum , "%07o" , ustar_header_chksum (& header ));
268
+ prepare_header (args , & header , mode , size );
200
269
201
270
if (ext_header .len > 0 ) {
202
- err = write_tar_entry (args , sha1 , NULL , 0 , 0 , ext_header .buf ,
203
- ext_header .len );
204
- if (err )
271
+ err = write_extended_header (args , sha1 , ext_header .buf ,
272
+ ext_header .len );
273
+ if (err ) {
274
+ free (buffer );
205
275
return err ;
276
+ }
206
277
}
207
278
strbuf_release (& ext_header );
208
279
write_blocked (& header , sizeof (header ));
209
- if (S_ISREG (mode ) && buffer && size > 0 )
210
- write_blocked (buffer , size );
280
+ if (S_ISREG (mode ) && size > 0 ) {
281
+ if (buffer )
282
+ write_blocked (buffer , size );
283
+ else
284
+ err = stream_blocked (sha1 );
285
+ }
286
+ free (buffer );
211
287
return err ;
212
288
}
213
289
214
290
static int write_global_extended_header (struct archiver_args * args )
215
291
{
216
292
const unsigned char * sha1 = args -> commit_sha1 ;
217
293
struct strbuf ext_header = STRBUF_INIT ;
218
- int err ;
294
+ struct ustar_header header ;
295
+ unsigned int mode ;
296
+ int err = 0 ;
219
297
220
298
strbuf_append_ext_header (& ext_header , "comment" , sha1_to_hex (sha1 ), 40 );
221
- err = write_tar_entry (args , NULL , NULL , 0 , 0 , ext_header .buf ,
222
- ext_header .len );
299
+ memset (& header , 0 , sizeof (header ));
300
+ * header .typeflag = TYPEFLAG_GLOBAL_HEADER ;
301
+ mode = 0100666 ;
302
+ strcpy (header .name , "pax_global_header" );
303
+ prepare_header (args , & header , mode , ext_header .len );
304
+ write_blocked (& header , sizeof (header ));
305
+ write_blocked (ext_header .buf , ext_header .len );
223
306
strbuf_release (& ext_header );
224
307
return err ;
225
308
}
0 commit comments