176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * cpio.c
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Write a compressed CPIO file
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdio.h>
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h>
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <inttypes.h>
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdbool.h>
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <zlib.h>
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "upload_backend.h"
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "ctime.h"
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint cpio_pad(struct upload_backend *be)
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    static char pad[4];		/* Up to 4 zero bytes */
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (be->dbytes & 3)
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return write_data(be, pad, -be->dbytes & 3);
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    else
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	return 0;
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint cpio_hdr(struct upload_backend *be, uint32_t mode, size_t datalen,
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	     const char *filename)
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    static uint32_t inode = 2;
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    char hdr[6+13*8+1];
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int nlen = strlen(filename)+1;
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int rv = 0;
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    cpio_pad(be);
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    sprintf(hdr, "%06o%08x%08x%08x%08x%08x%08x%08zx%08x%08x%08x%08x%08x%08x",
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    070701,		/* c_magic */
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    inode++,		/* c_ino */
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    mode,		/* c_mode */
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    0,			/* c_uid */
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    0,			/* c_gid */
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    1,			/* c_nlink */
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    be->now,		/* c_mtime */
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    datalen,		/* c_filesize */
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    0,			/* c_maj */
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    0,			/* c_min */
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    0,			/* c_rmaj */
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    0,			/* c_rmin */
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    nlen,		/* c_namesize */
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman	    0);			/* c_chksum */
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    rv |= write_data(be, hdr, 6+13*8);
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    rv |= write_data(be, filename, nlen);
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    rv |= cpio_pad(be);
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return rv;
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint cpio_mkdir(struct upload_backend *be, const char *filename)
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return cpio_hdr(be, MODE_DIR, 0, filename);
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint cpio_writefile(struct upload_backend *be, const char *filename,
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman		   const void *data, size_t len)
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    int rv;
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    rv = cpio_hdr(be, MODE_FILE, len, filename);
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    rv |= write_data(be, data, len);
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    rv |= cpio_pad(be);
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return rv;
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint cpio_close(struct upload_backend *be)
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return cpio_hdr(be, 0, 0, "TRAILER!!!");
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
76