/* 
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) Hewlett-Packard (Paul Bame) paul_bame@hp.com
 */
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "palo.h"

int
seekwrite(int fd, char *buf, unsigned size, __u64 where)
{
    char check[1024];
    int n = size < sizeof check ? size : sizeof check;
    int r = 0;
    off_t off;

    if (0) printf("seekwrite(%d, %p, %u, %llu)\n", fd, buf, size, where);

    fsync(fd);
    if (r != -1 && lseek(fd, where, SEEK_SET) != where)
    {
	perror("lseek");
	r = -1;
    }

    if (r != -1 && (r = write(fd, buf, size)) == -1)
    {
	perror("write");
	r = -1;
    }

    if (r != -1 && (off = lseek(fd, 0, SEEK_CUR)) != where + size)
    {
	fprintf(stderr, "position %ld not %u\n", off, where + size);
	r = -1;
    }

    fsync(fd);

    /* readback */
    if (r != -1 && lseek(fd, where, SEEK_SET) != where)
    {
	perror("lseek2");
	r = -1;
    }

    if (r != -1 && read(fd, check, n) != n)
    {
	perror("readback(check)");
	r = -1;
    }

    if (r != -1 && memcmp(check, buf, n) != 0)
    {
	fprintf(stderr, "readback failed!\n");
	r = -1;
    }

    /* leave the file positioned where expected */
    if (r != -1 && lseek(fd, where + size, SEEK_SET) != where + size)
    {
	perror("lseek3");
	r = -1;
    }

    return r;
}

int
seekread(int fd, char *buf, unsigned size, __u64 where)
{
    off_t off;
    int r = 0;
    if (0) printf("seekread(%d, %p, %x, %lld)\n", fd, buf, size, where);

    if (r != -1 && lseek(fd, where, SEEK_SET) != where)
    {
	perror("lseek");
	r = -1;
    }

    if (r != -1 && (r = read(fd, buf, size)) != size)
    {
	perror("read");
	r = -1;
    }

    if (r != -1 && (off = lseek(fd, 0, SEEK_CUR)) != where + size)
    {
	fprintf(stderr, "lseek said %ld not %u\n", off, where + size);
	r = -1;
    }
    if (0) printf("returning %x\n", size);

    return r;
}

int
cat(int out, int in)
{
    char buf[FW_BLOCKSIZE];
    int n;
    unsigned total = 0;

    while ((n = read(in, buf, sizeof buf)) > 0)
    {
	if (n != write(out, buf, n))
		perror("write in cat()");
	total += n;
    }

    if (0) printf("cat() wrote %u bytes\n", total);
    return total;
}

int
fsize(int fd)
{
    struct stat st;

    if (fstat(fd, &st) == -1)
    {
	perror("stat()");
	return -1;
    }
    return st.st_size;
}
