changeset 0:cd351af3a8d2 migout

import source
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Thu, 27 Mar 2008 20:03:52 -0400
parents
children ed5fa956dbd5
files .hgignore Makefile base85.c base85.h common.c common.h die.c die.h fake-sendmail migout.c settings.h split.c split.h test_migout types.h
diffstat 15 files changed, 723 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.hgignore	Thu Mar 27 20:03:52 2008 -0400
@@ -0,0 +1,7 @@
+^botbackup$
+^testgmail$
+^tmp$
+\.o$
+^test_base85$
+^split$
+^migout$
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Makefile	Thu Mar 27 20:03:52 2008 -0400
@@ -0,0 +1,17 @@
+CC=gcc
+CFLAGS=-Wall -g -D_FILE_OFFSET_BITS=64
+
+CFLAGS_LINK=-ldm
+
+BINS=migout
+
+all: $(BINS)
+
+clean:
+	rm -rf *.o $(BINS)
+
+migout: migout.o die.o common.o split.o base85.o
+	$(CC) $(CFLAGS) $(CFLAGS_LINK) -o $@ $^
+
+%.o: %.c
+	$(CC) $(CFLAGS) -c -o $@ $<
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/base85.c	Thu Mar 27 20:03:52 2008 -0400
@@ -0,0 +1,33 @@
+#include "types.h"
+#include "base85.h"
+
+int base85_encode(u8 *in, u8 *out, int inlen)
+{
+	u32 t;
+	u8 *src = in;
+	u8 *dst = out;
+
+	while (in + inlen > src) {
+		t = ((u32) src[0] << 24) |
+		    ((u32) src[1] << 16) |
+		    ((u32) src[2] << 8)  |
+		    ((u32) src[3]);
+		src += 4;
+
+		/* compression of all zero group */
+		if (!t) {
+			*dst = 'z';
+			dst++;
+			continue;
+		}
+
+		dst[4] = (t % 85) + 33;   t /= 85;
+		dst[3] = (t % 85) + 33;   t /= 85;
+		dst[2] = (t % 85) + 33;   t /= 85;
+		dst[1] = (t % 85) + 33;   t /= 85;
+		dst[0] = t + 33;
+		dst += 5;
+	}
+
+	return (int) (dst - out);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/base85.h	Thu Mar 27 20:03:52 2008 -0400
@@ -0,0 +1,8 @@
+#ifndef __BASE85_H
+#define __BASE85_H
+
+#include "types.h"
+
+extern int base85_encode(u8 *in, u8 *out, int inlen);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common.c	Thu Mar 27 20:03:52 2008 -0400
@@ -0,0 +1,293 @@
+#include <xfs/dmapi.h>
+
+#include "types.h"
+#include "die.h"
+#include "common.h"
+
+#include "settings.h"
+
+#define	SMTP_MSG	"SMTP DMAPI session"
+
+/* borrowed from xfstest repo */
+static int session_compare(const void *a, const void *b)
+{
+	return(*((dm_sessid_t *)a) - *((dm_sessid_t *)b));
+}
+
+/* borrowed from xfstest repo */
+static void find_session(dm_sessid_t *session)
+{
+	char		buffer[DM_SESSION_INFO_LEN];
+	dm_sessid_t	*sidbuf = NULL;
+	dm_sessid_t	new_session;
+	u_int		allocelem = 0;
+	u_int		nelem;
+	size_t		rlen;
+	int		error;
+	u_int		i;
+
+	/* Retrieve the list of all active sessions on the host. */
+
+	nelem = 100;		/* a reasonable first guess */
+	do {
+		if (allocelem < nelem) {
+			allocelem = nelem;
+			sidbuf = realloc(sidbuf, nelem * sizeof(*sidbuf));
+			if (sidbuf == NULL) {
+				fprintf(stderr, "realloc of %d bytes failed\n",
+					nelem * sizeof(*sidbuf));
+				exit(1);
+			}
+		}
+		error = dm_getall_sessions(allocelem, sidbuf, &nelem);
+	} while (error < 0 && errno == E2BIG);
+
+	/* If an error occurred, translate it into something meaningful. */
+
+	if (error < 0) {
+		fprintf(stderr, "unexpected dm_getall_sessions failure, %s\n",
+			strerror(errno));
+		free(sidbuf);
+		exit(1);
+	}
+
+	/* We have the list of all active sessions.  Scan the list looking
+	   for an existing "test" session that we can use.  The list must
+	   first be sorted in case other processes happen to be creating test
+	   sessions at the same time; we need to make sure that we pick the one
+	   with the lowest session ID.
+	*/
+
+	qsort(sidbuf, nelem, sizeof(sidbuf[0]), session_compare);
+
+	for (i = 0; i < nelem; i++) {
+		error = dm_query_session(sidbuf[i], sizeof(buffer),
+				buffer, &rlen);
+		if (error < 0) {
+			fprintf(stderr, "unexpected dm_query_session "
+				"failure, %s\n", strerror(errno));
+			free(sidbuf);
+			exit(1);
+		}
+
+		if (!strncmp(buffer, SMTP_MSG, sizeof(SMTP_MSG)))
+			break;
+	}
+	if (i < nelem) {
+		*session = (dm_sessid_t)sidbuf[i];
+		free(sidbuf);
+		return;
+	}
+
+	/* No test session exists, so we have to create one ourselves. */
+
+	if (dm_create_session(DM_NO_SESSION, SMTP_MSG, &new_session) != 0) {
+		fprintf(stderr, "dm_create_session failed, %s\n",
+			strerror(errno));
+		free(sidbuf);
+		exit(1);
+	}
+
+	/* Now re-retrieve the list of active sessions. */
+
+	do {
+		if (allocelem < nelem) {
+			allocelem = nelem;
+			sidbuf = realloc(sidbuf, nelem * sizeof(*sidbuf));
+			if (sidbuf == NULL) {
+				fprintf(stderr, "realloc of %d bytes failed\n",
+					nelem * sizeof(*sidbuf));
+				exit(1);
+			}
+		}
+		error = dm_getall_sessions(allocelem, sidbuf, &nelem);
+	} while (error < 0 && errno == E2BIG);
+
+	if (error < 0) {
+		fprintf(stderr, "dm_getall_sessions failed, %s\n",
+			strerror(errno));
+		free(sidbuf);
+		exit(1);
+	}
+
+	/* Sort the session ID list into ascending ID order, then find the
+	   test session with the lowest session ID.  We better find at
+	   least one since we created one!
+	*/
+
+	qsort(sidbuf, nelem, sizeof(sidbuf[0]), session_compare);
+
+	for (i = 0; i < nelem; i++) {
+		error = dm_query_session(sidbuf[i], sizeof(buffer),
+				buffer, &rlen);
+		if (error < 0) {
+			fprintf(stderr, "dm_query_session failed, %s\n",
+				strerror(errno));
+			free(sidbuf);
+			exit(1);
+		}
+		if (!strncmp(buffer, SMTP_MSG, sizeof(SMTP_MSG)))
+			break;
+	}
+	if (i == nelem) {
+		fprintf(stderr, "can't find the session we created\n");
+		free(sidbuf);
+		exit(1);
+	}
+	*session = (dm_sessid_t)sidbuf[i];
+	free(sidbuf);
+
+	/* If the session we are going to use is not the one we created,
+	   then we need to get rid of the created one.
+	*/
+
+	if (*session != new_session) {
+		if ((new_session) != 0) {
+			fprintf(stderr, "dm_destroy_session failed, %s\n",
+				strerror(errno));
+			exit(1);
+		}
+	}
+}
+
+int setup_dmapi(dm_sessid_t *sid)
+{
+	char *c;
+
+	if (dm_init_service(&c) == -1) {
+		warn("cannot init dmapi");
+		return 1;
+	}
+
+	if (strcmp(c, DM_VER_STR_CONTENTS)) {
+		warn("wrong version of dmapi");
+		return 1;
+	}
+
+	find_session(sid);
+	return 0;
+}
+
+int get_dmchange(dm_sessid_t sid, u8 *handle, size_t hlen, dm_token_t token, unsigned int *change)
+{
+	int err;
+	dm_stat_t stat;
+
+	err = dm_get_fileattr(sid, handle, hlen, token, DM_AT_CFLAG, &stat);
+	if (err == -1) {
+		warn("could not get fileattr");
+		return 1;
+	}
+
+	*change = stat.dt_change;
+	return 0;
+}
+
+int lock_file(dm_sessid_t sid, u8 *handle, size_t hlen, int right, dm_token_t *token)
+{
+	int err;
+
+	err = dm_create_userevent(sid, 0, NULL, token);
+	if (err == -1) {
+		warn("cannot create user event for session");
+		return 1;
+	}
+
+	err = dm_request_right(sid, handle, hlen, *token, DM_RR_WAIT, right);
+	if (err == -1) {
+		warn("cannot obtain requested right");
+		return 1;
+	}
+
+	return 0;
+}
+
+void unlock_file(dm_sessid_t sid, dm_token_t token)
+{
+	int err;
+
+	err = dm_respond_event(sid, token, DM_RESP_CONTINUE, 0, 0, 0);
+	if (err == -1)
+		warn("cannot respond to event/release token");
+}
+
+int save_dataloc(dm_sessid_t sid, u8 *handle, ssize_t hlen, dm_token_t token)
+{
+	dm_attrname_t attrname;
+	int err;
+
+	memcpy(&attrname.an_chars[0], "dhanloc", 8);
+	err = dm_set_dmattr(sid, handle, hlen, token, &attrname, 0, hlen, handle);
+	if (err) {
+		warn("can't set data location");
+		return 1;
+	}
+
+	memcpy(&attrname.an_chars[0], "dhanlen", 8);
+	err = dm_set_dmattr(sid, handle, hlen, token, &attrname, 0, sizeof(hlen), (void*)&hlen);
+	if (err) {
+		warn("can't set data location length");
+		return 1;
+	}
+
+	return 0;
+}
+
+int set_man_regions(dm_sessid_t sid, u8 *handle, size_t hlen, dm_token_t token, dm_size_t fsize, dm_off_t *off)
+{
+	dm_off_t rroff = 0;
+	dm_size_t rlen;
+	dm_region_t reg;
+	unsigned int exact;
+	int err;
+
+	if (fsize > FENCEPOST_SIZE) {
+		err = dm_probe_hole(sid, handle, hlen, token, FENCEPOST_SIZE, 0, &rroff, &rlen);
+		if (err) {
+			warn("could not probe hole in file");
+			return 1;
+		}
+	}
+
+	*off = rroff;
+
+	reg.rg_offset = rroff;
+	reg.rg_size = 0;
+	reg.rg_flags = DM_REGION_READ | DM_REGION_WRITE | DM_REGION_TRUNCATE;
+
+	err = dm_set_region(sid, handle, hlen, token, 1, &reg, &exact);
+	if (err) {
+		warn("could not set managed region");
+		return 1;
+	}
+
+	return 0;
+}
+
+int make_nonres(dm_sessid_t sid, u8 *handle, size_t hlen, dm_token_t token, dm_off_t off)
+{
+	int err;
+
+	err = dm_punch_hole(sid, handle, hlen, token, off, 0);
+	if (err) {
+		warn("could not punch hole in file");
+		return 1;
+	}
+
+	return 0;
+}
+
+void clear_man_regions(dm_sessid_t sid, u8 *handle, size_t hlen, dm_token_t token)
+{
+	dm_region_t reg;
+	unsigned int exact;
+	int err;
+
+	reg.rg_offset = 0;
+	reg.rg_size = 0;
+	reg.rg_flags = DM_REGION_NOEVENT;
+
+	err = dm_set_region(sid, handle, hlen, token, 1, &reg, &exact);
+	if (err)
+		warn("could not clear managed regions from file");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common.h	Thu Mar 27 20:03:52 2008 -0400
@@ -0,0 +1,17 @@
+#ifndef __COMMON_H
+#define __COMMON_H
+
+#include <xfs/dmapi.h>
+
+#include "types.h"
+
+extern int setup_dmapi(dm_sessid_t *sid);
+extern int get_dmchange(dm_sessid_t sid, u8 *handle, size_t hlen, dm_token_t token, unsigned int *change);
+extern int lock_file(dm_sessid_t sid, u8 *handle, size_t hlen, int flag, dm_token_t *token);
+extern void unlock_file(dm_sessid_t sid, dm_token_t token);
+extern int save_dataloc(dm_sessid_t sid, u8 *handle, ssize_t hlen, dm_token_t token);
+extern int set_man_regions(dm_sessid_t sid, u8 *handle, size_t hlen, dm_token_t token, dm_size_t fsize, dm_off_t *off);
+extern int make_nonres(dm_sessid_t sid, u8 *handle, size_t hlen, dm_token_t token, dm_off_t off);
+extern void clear_man_regions(dm_sessid_t sid, u8 *handle, size_t hlen, dm_token_t token);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/die.c	Thu Mar 27 20:03:52 2008 -0400
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "die.h"
+
+void do_warn(char *msg, int line, char *file)
+{
+	fprintf(stderr, "fatal: %s:%d:%s\n", file, line, msg);
+}
+
+void do_die(char *msg, int line, char *file)
+{
+	do_warn(msg, line, file);
+	exit(1);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/die.h	Thu Mar 27 20:03:52 2008 -0400
@@ -0,0 +1,10 @@
+#ifndef __DIE_H
+#define __DIE_H
+
+#define die(msg)	do_die(msg, __LINE__, __FILE__)
+#define warn(msg)	do_warn(msg, __LINE__, __FILE__)
+
+extern void do_die(char *msg, int line, char *file);
+extern void do_warn(char *msg, int line, char *file);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fake-sendmail	Thu Mar 27 20:03:52 2008 -0400
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+cat > /tmp/mbox.$$
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/migout.c	Thu Mar 27 20:03:52 2008 -0400
@@ -0,0 +1,138 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <xfs/dmapi.h>
+
+#include "types.h"
+#include "die.h"
+#include "common.h"
+#include "split.h"
+
+#include "settings.h"
+
+#define IBUFSIZE		1024
+
+static inline u8 hex2bin(char c)
+{
+	if (c > '9')
+		return c - 'a' + 10;
+	return c - '0';
+}
+
+int extract_fields(char *buf, u8 *handle, size_t *hlen, dm_size_t *fsize)
+{
+	size_t off;
+
+	*hlen = atoi(buf);
+
+	if (*hlen > HANDLE_MAX_SIZE) {
+		warn("handle length over maximum");
+		return 1;
+	}
+
+	while(*buf++ != '\t')
+		;
+
+	for(off=0; off < *hlen; off++, buf+=2) {
+		*handle = hex2bin(buf[0]) << 4 |
+		          hex2bin(buf[1]);
+		handle++;
+	}
+
+	buf +=2; /* skip space & tab */
+
+	*fsize = atoi(buf);
+
+	return 0;
+}
+
+int mig_files(dm_sessid_t sid)
+{
+	size_t hlen;
+	dm_size_t fsize;
+	dm_off_t off;
+	dm_token_t token;
+	int err;
+	char ibuf[IBUFSIZE];
+	u8 handle[HANDLE_MAX_SIZE];
+	unsigned int change_start, change_end;
+
+	while(fgets(ibuf, IBUFSIZE, stdin)) {
+		err = extract_fields(ibuf, handle, &hlen, &fsize);
+		if (err) {
+			warn("mangled line");
+			continue;
+		}
+
+		fprintf(stderr, "> handle (len=%d, size=%llu)\n", hlen, fsize);
+
+		err = get_dmchange(sid, handle, hlen, DM_NO_TOKEN, &change_start);
+		if (err) {
+			warn("failed to get the dmapi change indicator");
+			continue;
+		}
+
+		err = save_filedata(sid, handle, hlen, fsize);
+		if (err) {
+			warn("could not save file data");
+			continue;
+		}
+
+		err = lock_file(sid, handle, hlen, DM_RIGHT_EXCL, &token);
+		if (err) {
+			warn("could not get exclusive file lock");
+			continue;
+		}
+
+		err = get_dmchange(sid, handle, hlen, token, &change_end);
+		if (err) {
+			unlock_file(sid, token);
+			warn("failed to get the dmapi change indicator");
+			continue;
+		}
+		if (change_start != change_end) {
+			unlock_file(sid, token);
+			warn("file changed during stageout, ignoring");
+			continue;
+		}
+
+		err = save_dataloc(sid, handle, hlen, token);
+		if (err) {
+			unlock_file(sid, token);
+			warn("could not save data location");
+			continue;
+		}
+
+		err = set_man_regions(sid, handle, hlen, token, fsize, &off);
+		if (err) {
+			unlock_file(sid, token);
+			warn("could not set managed regions");
+			continue;
+		}
+
+		err = make_nonres(sid, handle, hlen, token, off);
+		if (err)
+			clear_man_regions(sid, handle, hlen, token);
+
+		unlock_file(sid, token);
+	}
+
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	dm_sessid_t sid;
+	int err;
+
+	if (setup_dmapi(&sid))
+		die("Cannot initialize dmapi session");
+
+	err = mig_files(sid);
+
+	if (dm_destroy_session(sid))
+		warn("Cannot shutdown dmapi session");
+
+	return err;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/settings.h	Thu Mar 27 20:03:52 2008 -0400
@@ -0,0 +1,15 @@
+#define IMAP_USER		"storage@example.com"
+#define IMAP_SERVER		"imap.example.com"
+
+#define SMTP_USER		"storage@example.com"
+#define SMTP_MAX_FILESIZE	(10 * 1024 * 1024)
+
+#define FROM_ADDRESS		"storage@example.com"
+
+#define SENDMAIL_PATH		"/usr/sbin/sendmail"
+//#define SENDMAIL_PATH		"./fake-sendmail"
+
+#define FENCEPOST_SIZE		8192
+
+#define HANDLE_MAX_SIZE		64
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/split.c	Thu Mar 27 20:03:52 2008 -0400
@@ -0,0 +1,116 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "settings.h"
+
+#include "base85.h"
+#include "split.h"
+#include "die.h"
+
+#define INFILE		"infile"
+#define CHUNKSIZE	(SMTP_MAX_FILESIZE * 4 / 5)
+
+int do_dm_read_invis(dm_sessid_t sid, u8 *handle, size_t hlen, char *buf, int len, dm_off_t start)
+{
+	int ret;
+	int off = 0;
+
+	do {
+		ret = dm_read_invis(sid, handle, hlen, DM_NO_TOKEN, start + off, len - off, buf + off);
+		if (ret > 0)
+			off += ret;
+		if (ret <= 0)
+			break;
+	} while(off < len);
+
+	return (ret < 0 ? ret : off);
+}
+
+void dump_buffer(FILE *sendmail, char *buf, char *obuf, int len)
+{
+	int i;
+
+	len = base85_encode((u8*)buf, (u8*)obuf, len);
+
+	for(i = 0; i < len; ) {
+		fprintf(sendmail, "%c", obuf[i++]);
+		if (i % 76 == 0)
+			fprintf(sendmail, "\n");
+	}
+	fprintf(sendmail, "\n\n");
+}
+
+static inline char bin2hex(u8 u)
+{
+	if (u >= 10)
+		return u - 10 + 'a';
+	return u + '0';
+}
+
+static void printable_handle(u8 *handle, size_t hlen, char *ascii)
+{
+	size_t i;
+
+	for(i=0; i<hlen; i++) {
+		ascii[i*2]   = bin2hex(handle[i] >> 4);
+		ascii[i*2+1] = bin2hex(handle[i] & 0xf);
+	}
+
+	ascii[i*2] = '\0';
+}
+
+int save_filedata(dm_sessid_t sid, u8 *handle, size_t hlen, dm_size_t fsize)
+{
+	FILE *sendmail;
+	int mbox;
+	char *buf, *obuf;
+	char asciihandle[HANDLE_MAX_SIZE];
+	int len;
+
+	buf = malloc(CHUNKSIZE);
+	obuf = malloc(CHUNKSIZE * 5 / 4);
+	if (!buf || !obuf) {
+		warn("could not allocate buffers");
+		return 1;
+	}
+
+	printable_handle(handle, hlen, asciihandle);
+
+	for(mbox=0; ; mbox++) {
+		/*
+		 * Read first to break out of the loop in case we're done
+		 */
+		len = do_dm_read_invis(sid, handle, hlen, buf, CHUNKSIZE, CHUNKSIZE * mbox);
+		if (len <= 0)
+			break;
+
+		sendmail = popen(SENDMAIL_PATH " -t \"" SMTP_USER "\"", "w");
+		if (!sendmail) {
+			warn("could not spawn sendmail");
+			return 1;
+		}
+
+		fprintf(sendmail, "From " FROM_ADDRESS " / %s\n", asciihandle);
+		fprintf(sendmail, "From: " FROM_ADDRESS "\n");
+		fprintf(sendmail, "To: " SMTP_USER "\n");
+		fprintf(sendmail, "Subject: %s, part %d\n", asciihandle, mbox);
+		fprintf(sendmail, "X-DM-Handle: %s\n", asciihandle);
+		fprintf(sendmail, "X-DM-Part: %d\n", mbox);
+		fprintf(sendmail, "X-DM-Part-Length: %d\n", len);
+		fprintf(sendmail, "\n");
+
+		dump_buffer(sendmail, buf, obuf, len);
+		fclose(sendmail);
+	}
+
+	return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/split.h	Thu Mar 27 20:03:52 2008 -0400
@@ -0,0 +1,10 @@
+#ifndef __SPLIT_H
+#define __SPLIT_H
+
+#include <xfs/dmapi.h>
+
+#include "types.h"
+
+extern int save_filedata(dm_sessid_t sid, u8 *handle, size_t hlen, dm_size_t fsize);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test_migout	Thu Mar 27 20:03:52 2008 -0400
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+DEV=/dev/hda6
+MNT=/mnt/xfs_scratch
+S1=/home/jeffpc/xfs-cmds/xfstests/dmapi/src/suite1/cmd
+SHSM=/home/jeffpc/xfs-cmds/xfstests/dmapi/src/sample_hsm
+MYHSM=/home/jeffpc/myprogs/xfs_smtp_hsm
+
+set -x
+umount $MNT
+mkfs.xfs -f $DEV
+mount $DEV $MNT -o dmapi,mtpt=$MNT
+
+cp /tmp/t $MNT/large
+
+fshandle=`$S1/path_to_fshandle $MNT`
+$S1/get_config_events $fshandle
+
+while true ; do
+	$SHSM/migfind -s 5k $MNT > /tmp/dmapi-list
+	[ -s /tmp/dmapi-list ] && break
+	sleep 45
+done
+
+cat /tmp/dmapi-list
+
+read n
+
+$MYHSM/migout < /tmp/dmapi-list
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/types.h	Thu Mar 27 20:03:52 2008 -0400
@@ -0,0 +1,10 @@
+#ifndef __TYPES_H
+#define __TYPES_H
+
+#include <inttypes.h>
+#include <sys/types.h>
+
+typedef uint8_t u8;
+typedef uint32_t u32;
+
+#endif