mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Initial s390-tools-2.0.0 import
This commit is based on the s390-tools-1.39.0 version. Changes on top of s390-tools-1.39.0: - Add MIT license to all source files - Add LICENSE file - Transform REAMDE to README.md (markdown) - Add AUTHORS.md file - Add CONTRIBUTING.md file - Move changelog from README to CHANGELOG.md file Reviewed-by: Stefan Haberland <sth@linux.vnet.ibm.com> Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
This commit is contained in:
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* cpioinit - Tool to create cpio archives
|
||||
*
|
||||
* This tool can be used to create a cpio initrd for the linux kernel.
|
||||
*
|
||||
* The executable init program needs to be specified as parameter.
|
||||
* The cpio archive is printed to stdout.
|
||||
*
|
||||
* Copyright IBM Corp. 2013, 2017
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* Cpio archive new header structure
|
||||
*/
|
||||
struct cpio_newc_header {
|
||||
char c_magic[6];
|
||||
char c_ino[8];
|
||||
char c_mode[8];
|
||||
char c_uid[8];
|
||||
char c_gid[8];
|
||||
char c_nlink[8];
|
||||
char c_mtime[8];
|
||||
char c_filesize[8];
|
||||
char c_devmajor[8];
|
||||
char c_devminor[8];
|
||||
char c_rdevmajor[8];
|
||||
char c_rdevminor[8];
|
||||
char c_namesize[8];
|
||||
char c_check[8];
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure to specify a cpio archive entry
|
||||
*/
|
||||
struct cpio_line {
|
||||
struct cpio_newc_header head;
|
||||
const char *filename;
|
||||
char *data;
|
||||
unsigned int datasize;
|
||||
};
|
||||
|
||||
/*
|
||||
* Fill line with zeros to be aligned to 4 bytes
|
||||
*/
|
||||
static int cpio_fill_aligned(int size)
|
||||
{
|
||||
while (size % 4) {
|
||||
printf("%c", 0);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a cpio_line structure to stdout
|
||||
*/
|
||||
static void cpio_print_ln(struct cpio_line *line)
|
||||
{
|
||||
unsigned int i, lnsize = 0;
|
||||
|
||||
for (i = 0; i < sizeof(struct cpio_newc_header); i++)
|
||||
printf("%c", ((char *)&line->head)[i]);
|
||||
lnsize += sizeof(struct cpio_newc_header);
|
||||
|
||||
if (line->filename != NULL) {
|
||||
printf("%s", line->filename);
|
||||
printf("%c", 0); /* print ending zero */
|
||||
lnsize += strlen(line->filename) + 1;
|
||||
lnsize = cpio_fill_aligned(lnsize);
|
||||
}
|
||||
|
||||
if (line->data != NULL) {
|
||||
for (i = 0; i < line->datasize; i++)
|
||||
printf("%c", line->data[i]);
|
||||
lnsize += line->datasize;
|
||||
lnsize = cpio_fill_aligned(lnsize);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write number in cpio new ascii format into header field with
|
||||
* size of 6 chars
|
||||
*/
|
||||
static void cpio_insert_num6(char *head, int num)
|
||||
{
|
||||
char buf[7];
|
||||
|
||||
/* Need memcpy because snprintf addes zero at the end */
|
||||
snprintf(buf, sizeof(buf), "%06x", num);
|
||||
memcpy(head, buf, 6);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write number in cpio new ascii format into header field with
|
||||
* size of 8 chars
|
||||
*/
|
||||
static void cpio_insert_num8(char *head, int num)
|
||||
{
|
||||
char buf[9];
|
||||
|
||||
/* Need memcpy because snprintf addes zero at the end */
|
||||
snprintf(buf, sizeof(buf), "%08x", num);
|
||||
memcpy(head, buf, 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write basics to cpio_newc_header managing the entry number,
|
||||
* thus each structure write has to call this function once
|
||||
*/
|
||||
static void cpio_header_init(struct cpio_newc_header *head)
|
||||
{
|
||||
static int number;
|
||||
|
||||
cpio_insert_num6(head->c_magic, 0x070701);
|
||||
cpio_insert_num8(head->c_ino, 0x2d1 + number);
|
||||
cpio_insert_num8(head->c_uid, 0);
|
||||
cpio_insert_num8(head->c_gid, 0);
|
||||
cpio_insert_num8(head->c_nlink, number);
|
||||
cpio_insert_num8(head->c_mtime, 0);
|
||||
cpio_insert_num8(head->c_check, 0);
|
||||
cpio_insert_num8(head->c_devmajor, 3);
|
||||
cpio_insert_num8(head->c_devminor, 1);
|
||||
number++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes directory in cpio archive structure to stdout
|
||||
*/
|
||||
static void cpio_write_dir(const char *dir)
|
||||
{
|
||||
struct cpio_line line;
|
||||
|
||||
cpio_header_init(&line.head);
|
||||
cpio_insert_num8(line.head.c_mode, 0x41ed);
|
||||
cpio_insert_num8(line.head.c_filesize, 0);
|
||||
cpio_insert_num8(line.head.c_rdevmajor, 0);
|
||||
cpio_insert_num8(line.head.c_rdevminor, 0);
|
||||
cpio_insert_num8(line.head.c_namesize, strlen(dir) + 1);
|
||||
line.filename = dir;
|
||||
line.data = NULL;
|
||||
cpio_print_ln(&line);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes end of cpio archive to stdout
|
||||
*/
|
||||
static void cpio_write_tail()
|
||||
{
|
||||
struct cpio_line line;
|
||||
int i;
|
||||
|
||||
cpio_header_init(&line.head);
|
||||
cpio_insert_num8(line.head.c_ino, 0);
|
||||
cpio_insert_num8(line.head.c_mode, 0);
|
||||
cpio_insert_num8(line.head.c_filesize, 0);
|
||||
cpio_insert_num8(line.head.c_devmajor, 0);
|
||||
cpio_insert_num8(line.head.c_devminor, 0);
|
||||
cpio_insert_num8(line.head.c_rdevmajor, 0);
|
||||
cpio_insert_num8(line.head.c_rdevminor, 0);
|
||||
cpio_insert_num8(line.head.c_namesize, 11);
|
||||
line.filename = "TRAILER!!!";
|
||||
line.data = NULL;
|
||||
cpio_print_ln(&line);
|
||||
for (i = 0; i < 30; i++)
|
||||
printf("%c", 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes device node in cpio archive structure to stdout
|
||||
*/
|
||||
static void cpio_write_nod(char *name, int major, int minor, int chardev)
|
||||
{
|
||||
struct cpio_line line;
|
||||
|
||||
cpio_header_init(&line.head);
|
||||
if (chardev == 1)
|
||||
cpio_insert_num8(line.head.c_mode, 0x21a4);
|
||||
else
|
||||
cpio_insert_num8(line.head.c_mode, 0x61a4);
|
||||
cpio_insert_num8(line.head.c_filesize, 0);
|
||||
cpio_insert_num8(line.head.c_rdevmajor, major);
|
||||
cpio_insert_num8(line.head.c_rdevminor, minor);
|
||||
cpio_insert_num8(line.head.c_namesize, strlen(name) + 1);
|
||||
line.filename = name;
|
||||
line.data = NULL;
|
||||
cpio_print_ln(&line);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes file in cpio archiv structure to stdout
|
||||
*/
|
||||
static void cpio_write_file(char *name, char *filedata, int filesize)
|
||||
{
|
||||
struct cpio_line line;
|
||||
|
||||
cpio_header_init(&line.head);
|
||||
cpio_insert_num8(line.head.c_mode, 0x81ed);
|
||||
cpio_insert_num8(line.head.c_filesize, filesize);
|
||||
cpio_insert_num8(line.head.c_rdevmajor, 0);
|
||||
cpio_insert_num8(line.head.c_rdevminor, 0);
|
||||
cpio_insert_num8(line.head.c_namesize, strlen(name) + 1);
|
||||
line.filename = name;
|
||||
line.data = filedata;
|
||||
line.datasize = filesize;
|
||||
cpio_print_ln(&line);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read size bytes from file into buffer
|
||||
*/
|
||||
static int read_file(const char *file, char *buf, int size)
|
||||
{
|
||||
int fh;
|
||||
|
||||
fh = open(file, O_RDONLY);
|
||||
if (fh == -1) {
|
||||
fprintf(stderr, "Open %s failed (%s)\n", file, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (read(fh, buf, size) < 0) {
|
||||
fprintf(stderr, "Read %s failed (%s)\n", file, strerror(errno));
|
||||
close(fh);
|
||||
return -1;
|
||||
}
|
||||
close(fh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Program writes a cpio archive to stdout.
|
||||
* - containing device nodes needed to run scsi dumper
|
||||
* - expecting init program as parameter
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char path[10], *filebuffer, *filename;
|
||||
struct stat st;
|
||||
int i;
|
||||
|
||||
/* First read in init file */
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: cpioinit <init program>\n");
|
||||
return -1;
|
||||
}
|
||||
filename = argv[1];
|
||||
if (stat(filename, &st)) {
|
||||
fprintf(stderr, "Cannot open file: %s (%s)\n", filename,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
filebuffer = malloc(st.st_size);
|
||||
if (filebuffer == NULL) {
|
||||
fprintf(stderr, "Malloc %lu bytes failed\n", st.st_size);
|
||||
return -1;
|
||||
}
|
||||
if (read_file(filename, filebuffer, st.st_size))
|
||||
return -1;
|
||||
|
||||
/* Write init */
|
||||
cpio_write_file("init", filebuffer, st.st_size);
|
||||
free(filebuffer);
|
||||
|
||||
/* Define device nodes */
|
||||
cpio_write_dir("dev");
|
||||
cpio_write_dir("proc");
|
||||
cpio_write_dir("sys");
|
||||
cpio_write_dir("mnt");
|
||||
cpio_write_nod("dev/console", 5, 1, 1);
|
||||
cpio_write_nod("dev/null", 1, 3, 1);
|
||||
|
||||
/* Write sda for access via part offset */
|
||||
cpio_write_nod("dev/sda", 8, 0, 0);
|
||||
|
||||
/* Write sda 1 - 15 nodes */
|
||||
for (i = 1; i < 15; i++) {
|
||||
snprintf(path, sizeof(path), "dev/sda%d", i);
|
||||
cpio_write_nod(path, 8, i, 0);
|
||||
}
|
||||
cpio_write_tail();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user