3
3
#include <stdlib.h>
4
4
#include <stdint.h>
5
5
#include <string.h>
6
+ #include <fcntl.h>
7
+ #include <sys/stat.h>
8
+ #include <sys/time.h>
9
+ #include <sys/types.h>
6
10
7
11
#define RECORD_SIZE 5120
8
12
static uint8_t buffer [2 * RECORD_SIZE ];
9
13
static uint32_t buf_size = RECORD_SIZE ;
10
14
static uint8_t * ptr = & buffer [RECORD_SIZE ];
11
15
static char name [65535 ];
16
+ static int extract = 0 ;
12
17
13
18
static uint8_t
14
19
read_frame (void )
@@ -114,12 +119,58 @@ read_octal (uint8_t *data, int size)
114
119
return strtoul (tmp , NULL , 8 );
115
120
}
116
121
122
+ static void
123
+ mkdirs (char * dir )
124
+ {
125
+ char * p = dir ;
126
+ for (;;)
127
+ {
128
+ p = strchr (p , '/' );
129
+ if (p == NULL )
130
+ return ;
131
+ * p = 0 ;
132
+ mkdir (dir , 0700 );
133
+ * p ++ = '/' ;
134
+ }
135
+ }
136
+
137
+ static FILE *
138
+ open_file (char * name , mode_t mode )
139
+ {
140
+ int fd ;
141
+
142
+ if (* name == '/' )
143
+ name ++ ;
144
+
145
+ mkdirs (name );
146
+
147
+ if (mode & 040000 )
148
+ {
149
+ mkdir (name , mode & 0777 );
150
+ return NULL ;
151
+ }
152
+
153
+ fd = creat (name , mode & 0777 );
154
+ return fdopen (fd , "w" );
155
+ }
156
+
157
+ static void
158
+ timestamp (char * name , time_t timestamp )
159
+ {
160
+ struct timeval tv [2 ];
161
+ tv [0 ].tv_sec = timestamp ;
162
+ tv [0 ].tv_usec = 0 ;
163
+ tv [1 ] = tv [0 ];
164
+ utimes (name , tv );
165
+ }
166
+
117
167
static void
118
168
read_file (void )
119
169
{
120
170
uint32_t i , mode , uid , gid , links , mtime , name_size , file_size ;
121
171
uint8_t * data ;
122
172
uint8_t adjust = 0 ;
173
+ FILE * f = NULL ;
123
174
time_t t ;
124
175
char * s ;
125
176
@@ -172,11 +223,22 @@ read_file (void)
172
223
printf ("%06o %3u %5u %5u %7u %s %s\n" ,
173
224
mode , links , uid , gid , file_size , s , name );
174
225
175
- if (file_size & 1 )
176
- file_size += adjust ;
226
+ if (extract )
227
+ f = open_file (name , mode );
228
+
229
+ /* The file data must start on an even boundary. */
230
+ if ((ptr - buffer ) & 1 )
231
+ read_data (adjust );
177
232
for (i = 0 ; i < file_size ; i ++ )
178
233
{
179
234
data = read_data (1 );
235
+ if (f )
236
+ fputc (* data , f );
237
+ }
238
+ if (f )
239
+ {
240
+ fclose (f );
241
+ timestamp (name , mtime );
180
242
}
181
243
}
182
244
@@ -186,8 +248,14 @@ read_file (void)
186
248
187
249
}
188
250
189
- int main (void )
251
+ int main (int argc , char * * argv )
190
252
{
253
+ if (argc == 2 && strcmp (argv [1 ], "-x" ) == 0 )
254
+ {
255
+ extract = 1 ;
256
+ umask (0 );
257
+ }
258
+
191
259
for (;;)
192
260
read_file ();
193
261
0 commit comments