Skip to content

Commit 62cccd9

Browse files
committed
Extract old cpio tapes.
1 parent 498b1d0 commit 62cccd9

File tree

2 files changed

+87
-3
lines changed

2 files changed

+87
-3
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,4 @@ In addition, some mini and micro computer program formats are supported:
6666
- CROSS "ASCII HEX" files.
6767
- Atari DOS executables.
6868
- Imlac "speciall TTY" files.
69+
- Harris HCX/UX cpio.

old-cpio.c

+86-3
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,34 @@
1+
/* Copyright (C) 2022 Lars Brinkhoff <[email protected]>
2+
3+
This program is free software: you can redistribute it and/or modify
4+
it under the terms of the GNU General Public License as published by
5+
the Free Software Foundation, either version 2 of the License, or
6+
(at your option) any later version.
7+
8+
This program is distributed in the hope that it will be useful,
9+
but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
GNU General Public License for more details.
12+
13+
You should have received a copy of the GNU General Public License
14+
along with this program. If not, see <http://www.gnu.org/licenses/>. */
15+
116
#include <time.h>
217
#include <stdio.h>
318
#include <stdlib.h>
419
#include <stdint.h>
520
#include <string.h>
21+
#include <fcntl.h>
22+
#include <sys/stat.h>
23+
#include <sys/time.h>
24+
#include <sys/types.h>
625

726
#define RECORD_SIZE 5120
827
static uint8_t buffer[2 * RECORD_SIZE];
928
static uint32_t buf_size = RECORD_SIZE;
1029
static uint8_t *ptr = &buffer[RECORD_SIZE];
1130
static char name[65535];
31+
static int extract = 0;
1232

1333
static uint8_t
1434
read_frame (void)
@@ -114,12 +134,58 @@ read_octal (uint8_t *data, int size)
114134
return strtoul (tmp, NULL, 8);
115135
}
116136

137+
static void
138+
mkdirs (char *dir)
139+
{
140+
char *p = dir;
141+
for (;;)
142+
{
143+
p = strchr (p, '/');
144+
if (p == NULL)
145+
return;
146+
*p = 0;
147+
mkdir (dir, 0700);
148+
*p++ = '/';
149+
}
150+
}
151+
152+
static FILE *
153+
open_file (char *name, mode_t mode)
154+
{
155+
int fd;
156+
157+
if (*name == '/')
158+
name++;
159+
160+
mkdirs (name);
161+
162+
if (mode & 040000)
163+
{
164+
mkdir (name, mode & 0777);
165+
return NULL;
166+
}
167+
168+
fd = creat (name, mode & 0777);
169+
return fdopen (fd, "w");
170+
}
171+
172+
static void
173+
timestamp (char *name, time_t timestamp)
174+
{
175+
struct timeval tv[2];
176+
tv[0].tv_sec = timestamp;
177+
tv[0].tv_usec = 0;
178+
tv[1] = tv[0];
179+
utimes (name, tv);
180+
}
181+
117182
static void
118183
read_file (void)
119184
{
120185
uint32_t i, mode, uid, gid, links, mtime, name_size, file_size;
121186
uint8_t *data;
122187
uint8_t adjust = 0;
188+
FILE *f = NULL;
123189
time_t t;
124190
char *s;
125191

@@ -172,11 +238,22 @@ read_file (void)
172238
printf ("%06o %3u %5u %5u %7u %s %s\n",
173239
mode, links, uid, gid, file_size, s, name);
174240

175-
if (file_size & 1)
176-
file_size += adjust;
241+
if (extract)
242+
f = open_file (name, mode);
243+
244+
/* The file data must start on an even boundary. */
245+
if ((ptr - buffer) & 1)
246+
read_data (adjust);
177247
for (i = 0; i < file_size; i++)
178248
{
179249
data = read_data (1);
250+
if (f)
251+
fputc (*data, f);
252+
}
253+
if (f)
254+
{
255+
fclose (f);
256+
timestamp (name, mtime);
180257
}
181258
}
182259

@@ -186,8 +263,14 @@ read_file (void)
186263

187264
}
188265

189-
int main (void)
266+
int main (int argc, char **argv)
190267
{
268+
if (argc == 2 && strcmp (argv[1], "-x") == 0)
269+
{
270+
extract = 1;
271+
umask (0);
272+
}
273+
191274
for (;;)
192275
read_file ();
193276

0 commit comments

Comments
 (0)