Skip to content

Commit

Permalink
Extract old cpio tapes.
Browse files Browse the repository at this point in the history
  • Loading branch information
larsbrinkhoff committed Aug 20, 2022
1 parent 498b1d0 commit 62cccd9
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 3 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,4 @@ In addition, some mini and micro computer program formats are supported:
- CROSS "ASCII HEX" files.
- Atari DOS executables.
- Imlac "speciall TTY" files.
- Harris HCX/UX cpio.
89 changes: 86 additions & 3 deletions old-cpio.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
/* Copyright (C) 2022 Lars Brinkhoff <lars@nocrew.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>

#define RECORD_SIZE 5120
static uint8_t buffer[2 * RECORD_SIZE];
static uint32_t buf_size = RECORD_SIZE;
static uint8_t *ptr = &buffer[RECORD_SIZE];
static char name[65535];
static int extract = 0;

static uint8_t
read_frame (void)
Expand Down Expand Up @@ -114,12 +134,58 @@ read_octal (uint8_t *data, int size)
return strtoul (tmp, NULL, 8);
}

static void
mkdirs (char *dir)
{
char *p = dir;
for (;;)
{
p = strchr (p, '/');
if (p == NULL)
return;
*p = 0;
mkdir (dir, 0700);
*p++ = '/';
}
}

static FILE *
open_file (char *name, mode_t mode)
{
int fd;

if (*name == '/')
name++;

mkdirs (name);

if (mode & 040000)
{
mkdir (name, mode & 0777);
return NULL;
}

fd = creat (name, mode & 0777);
return fdopen (fd, "w");
}

static void
timestamp (char *name, time_t timestamp)
{
struct timeval tv[2];
tv[0].tv_sec = timestamp;
tv[0].tv_usec = 0;
tv[1] = tv[0];
utimes (name, tv);
}

static void
read_file (void)
{
uint32_t i, mode, uid, gid, links, mtime, name_size, file_size;
uint8_t *data;
uint8_t adjust = 0;
FILE *f = NULL;
time_t t;
char *s;

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

if (file_size & 1)
file_size += adjust;
if (extract)
f = open_file (name, mode);

/* The file data must start on an even boundary. */
if ((ptr - buffer) & 1)
read_data (adjust);
for (i = 0; i < file_size; i++)
{
data = read_data (1);
if (f)
fputc (*data, f);
}
if (f)
{
fclose (f);
timestamp (name, mtime);
}
}

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

}

int main (void)
int main (int argc, char **argv)
{
if (argc == 2 && strcmp (argv[1], "-x") == 0)
{
extract = 1;
umask (0);
}

for (;;)
read_file ();

Expand Down

0 comments on commit 62cccd9

Please sign in to comment.