Blame src/meta/tpax_init_cpio_header.c

f66f53
/**************************************************************/
f66f53
/*  tpax: a topological pax implementation                    */
f66f53
/*  Copyright (C) 2020--2024  SysDeer Technologies, LLC       */
f66f53
/*  Released under GPLv2 and GPLv3; see COPYING.TPAX.         */
f66f53
/**************************************************************/
f66f53
f66f53
#include <stdint.h>
f66f53
#include <stdlib.h>
f66f53
#include <string.h>
f66f53
#include <unistd.h>
f66f53
#include <fcntl.h>
f66f53
#include <errno.h>
f66f53
#include <grp.h>
f66f53
#include <pwd.h>
f66f53
#include <sys/stat.h>
f66f53
f66f53
#include <tpax/tpax.h>
f66f53
#include <tpax/tpax_specs.h>
f66f53
#include "tpax_driver_impl.h"
f66f53
f66f53
#ifndef ssizeof
f66f53
#define ssizeof(x) (ssize_t)(sizeof(x))
f66f53
#endif
f66f53
f66f53
#define TPAX_CPIO_PERM_MASK         \
f66f53
	( S_ISUID | S_ISGID          \
f66f53
	| S_IRUSR | S_IWUSR | S_IXUSR \
f66f53
	| S_IRGRP | S_IWGRP | S_IXGRP \
f66f53
	| S_IROTH | S_IWOTH | S_IXOTH )
f66f53
f66f53
static void tpax_octal_write(char * ch, ssize_t len, uint64_t val)
f66f53
{
f66f53
	for (; len; ) {
f66f53
		ch[--len] = val % 8 + '0';
f66f53
		val /= 8;
f66f53
	}
f66f53
}
f66f53
f66f53
int tpax_meta_init_cpio_header(
f66f53
	const char *                    path,
f66f53
	const struct stat *             st,
f66f53
	const char *                    linkname,
f66f53
	int                             cdev,
f66f53
	int                             cino,
f66f53
	int                             cnlink,
f66f53
	struct tpax_cpio_header *       chdr)
f66f53
{
f66f53
	size_t		fnsize;
f66f53
	size_t		lnklen;
f66f53
	size_t		stsize;
f66f53
	int64_t		stmtim;
f66f53
	uint32_t	typeflag;
f66f53
	uint32_t	permbits;
f66f53
	uint32_t	modebits;
f66f53
f66f53
	/* filename size */
f66f53
	fnsize = strlen(path) + 1;
f66f53
f66f53
	/* size & mtime validation */
f66f53
	stsize = S_ISREG(st->st_mode) ? st->st_size : 0;
f66f53
	stmtim = st->st_mtim.tv_sec;
f66f53
f66f53
	if (stsize > 077777777777)
f66f53
		return -1;
f66f53
f66f53
	if ((stmtim < 0) || (stmtim > 077777777777))
f66f53
		return -1;
f66f53
f66f53
	/* linkname validation */
f66f53
	if (S_ISLNK(st->st_mode) && !linkname)
f66f53
		return -1;
f66f53
f66f53
	lnklen = S_ISLNK(st->st_mode)
f66f53
		? strlen(linkname)
f66f53
		: 0;
f66f53
f66f53
	/* typeflag validation */
f66f53
	if (S_ISREG(st->st_mode))
f66f53
		typeflag = TPAX_CPIO_FILEMODE_ISREG;
f66f53
	else if (S_ISLNK(st->st_mode))
f66f53
		typeflag = TPAX_CPIO_FILEMODE_ISLNK;
f66f53
	else if (S_ISDIR(st->st_mode))
f66f53
		typeflag = TPAX_CPIO_FILEMODE_ISDIR;
f66f53
	else if (S_ISCHR(st->st_mode))
f66f53
		typeflag = TPAX_CPIO_FILEMODE_ISCHR;
f66f53
	else if (S_ISBLK(st->st_mode))
f66f53
		typeflag = TPAX_CPIO_FILEMODE_ISBLK;
f66f53
	else if (S_ISFIFO(st->st_mode))
f66f53
		typeflag = TPAX_CPIO_FILEMODE_ISFIFO;
f66f53
	else if (S_ISSOCK(st->st_mode))
f66f53
		typeflag = TPAX_CPIO_FILEMODE_ISSOCK;
f66f53
	else
f66f53
		return -1;
f66f53
f66f53
	/* permbits, modeflag */
f66f53
	permbits = st->st_mode & TPAX_CPIO_PERM_MASK;
f66f53
	modebits = permbits | typeflag;
f66f53
f66f53
	/* one shot */
f66f53
	memset(chdr,0,sizeof(*chdr));
f66f53
f66f53
	/* c_magic */
f66f53
	chdr->c_magic[0] = '0';
f66f53
	chdr->c_magic[1] = '7';
f66f53
	chdr->c_magic[2] = '0';
f66f53
	chdr->c_magic[3] = '7';
f66f53
	chdr->c_magic[4] = '0';
f66f53
	chdr->c_magic[5] = '7';
f66f53
f66f53
	/* c_dev, c_ino */
f66f53
	tpax_octal_write(chdr->c_dev,ssizeof(chdr->c_dev),cdev);
f66f53
	tpax_octal_write(chdr->c_ino,ssizeof(chdr->c_ino),cino);
f66f53
f66f53
	/* c_mode */
f66f53
	tpax_octal_write(chdr->c_mode,ssizeof(chdr->c_mode),modebits);
f66f53
f66f53
	/* c_uid, c_gid */
f66f53
	if ((uint64_t)st->st_uid <= 0777777)
f66f53
		tpax_octal_write(chdr->c_uid,ssizeof(chdr->c_uid),st->st_uid);
f66f53
	else
f66f53
		tpax_octal_write(chdr->c_uid,ssizeof(chdr->c_uid),0);
f66f53
f66f53
	if ((uint64_t)st->st_gid <= 0777777)
f66f53
		tpax_octal_write(chdr->c_gid,ssizeof(chdr->c_gid),st->st_gid);
f66f53
	else
f66f53
		tpax_octal_write(chdr->c_gid,ssizeof(chdr->c_gid),0);
f66f53
f66f53
	/* c_nlink */
f66f53
	tpax_octal_write(chdr->c_nlink,ssizeof(chdr->c_nlink),cnlink);
f66f53
f66f53
	/* c_rdev */
f66f53
	tpax_octal_write(chdr->c_rdev,ssizeof(chdr->c_rdev),st->st_rdev);
f66f53
f66f53
	/* c_mtime */
f66f53
	tpax_octal_write(chdr->c_mtime,ssizeof(chdr->c_mtime),stmtim);
f66f53
f66f53
	/* c_namesize */
f66f53
	tpax_octal_write(chdr->c_namesize,ssizeof(chdr->c_namesize),fnsize);
f66f53
f66f53
	/* c_filesize */
f66f53
	tpax_octal_write(chdr->c_filesize,ssizeof(chdr->c_filesize),lnklen ? lnklen : stsize);
f66f53
f66f53
	/* all done; c_name to be written along with c_filedata */
f66f53
	return 0;
f66f53
}