33#include <stdlib.h>
44#include <stdint.h>
55#include <string.h>
6+ #include <fcntl.h>
7+ #include <sys/stat.h>
8+ #include <sys/time.h>
9+ #include <sys/types.h>
610
711#define RECORD_SIZE 5120
812static uint8_t buffer [2 * RECORD_SIZE ];
913static uint32_t buf_size = RECORD_SIZE ;
1014static uint8_t * ptr = & buffer [RECORD_SIZE ];
1115static char name [65535 ];
16+ static int extract = 0 ;
1217
1318static uint8_t
1419read_frame (void )
@@ -114,12 +119,58 @@ read_octal (uint8_t *data, int size)
114119 return strtoul (tmp , NULL , 8 );
115120}
116121
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+
117167static void
118168read_file (void )
119169{
120170 uint32_t i , mode , uid , gid , links , mtime , name_size , file_size ;
121171 uint8_t * data ;
122172 uint8_t adjust = 0 ;
173+ FILE * f = NULL ;
123174 time_t t ;
124175 char * s ;
125176
@@ -172,11 +223,22 @@ read_file (void)
172223 printf ("%06o %3u %5u %5u %7u %s %s\n" ,
173224 mode , links , uid , gid , file_size , s , name );
174225
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 );
177232 for (i = 0 ; i < file_size ; i ++ )
178233 {
179234 data = read_data (1 );
235+ if (f )
236+ fputc (* data , f );
237+ }
238+ if (f )
239+ {
240+ fclose (f );
241+ timestamp (name , mtime );
180242 }
181243 }
182244
@@ -186,8 +248,14 @@ read_file (void)
186248
187249}
188250
189- int main (void )
251+ int main (int argc , char * * argv )
190252{
253+ if (argc == 2 && strcmp (argv [1 ], "-x" ) == 0 )
254+ {
255+ extract = 1 ;
256+ umask (0 );
257+ }
258+
191259 for (;;)
192260 read_file ();
193261
0 commit comments