1333917Seadler/*
2333917Seadler * Copyright (c) Christos Zoulas 2017.
3333917Seadler * All Rights Reserved.
4333917Seadler *
5333917Seadler * Redistribution and use in source and binary forms, with or without
6333917Seadler * modification, are permitted provided that the following conditions
7333917Seadler * are met:
8333917Seadler * 1. Redistributions of source code must retain the above copyright
9333917Seadler *    notice immediately at the beginning of the file, without modification,
10333917Seadler *    this list of conditions, and the following disclaimer.
11333917Seadler * 2. Redistributions in binary form must reproduce the above copyright
12333917Seadler *    notice, this list of conditions and the following disclaimer in the
13333917Seadler *    documentation and/or other materials provided with the distribution.
14333917Seadler *
15333917Seadler * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16333917Seadler * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17333917Seadler * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18333917Seadler * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
19333917Seadler * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20333917Seadler * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21333917Seadler * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22333917Seadler * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23333917Seadler * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24333917Seadler * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25333917Seadler * SUCH DAMAGE.
26333917Seadler */
27333917Seadler#include "file.h"
28333917Seadler
29333917Seadler#ifndef	lint
30362844SdelphijFILE_RCSID("@(#)$File: buffer.c,v 1.8 2020/02/16 15:52:49 christos Exp $")
31333917Seadler#endif	/* lint */
32333917Seadler
33333917Seadler#include "magic.h"
34333917Seadler#include <unistd.h>
35333917Seadler#include <string.h>
36333917Seadler#include <stdlib.h>
37333917Seadler#include <sys/stat.h>
38333917Seadler
39333917Seadlervoid
40354939Sdelphijbuffer_init(struct buffer *b, int fd, const struct stat *st, const void *data,
41354939Sdelphij    size_t len)
42333917Seadler{
43333917Seadler	b->fd = fd;
44354939Sdelphij	if (st)
45354939Sdelphij		memcpy(&b->st, st, sizeof(b->st));
46354939Sdelphij	else if (b->fd == -1 || fstat(b->fd, &b->st) == -1)
47333917Seadler		memset(&b->st, 0, sizeof(b->st));
48333917Seadler	b->fbuf = data;
49333917Seadler	b->flen = len;
50333917Seadler	b->eoff = 0;
51333917Seadler	b->ebuf = NULL;
52333917Seadler	b->elen = 0;
53333917Seadler}
54333917Seadler
55333917Seadlervoid
56333917Seadlerbuffer_fini(struct buffer *b)
57333917Seadler{
58333917Seadler	free(b->ebuf);
59333917Seadler}
60333917Seadler
61333917Seadlerint
62333917Seadlerbuffer_fill(const struct buffer *bb)
63333917Seadler{
64333917Seadler	struct buffer *b = CCAST(struct buffer *, bb);
65333917Seadler
66333917Seadler	if (b->elen != 0)
67362844Sdelphij		return b->elen == FILE_BADSIZE ? -1 : 0;
68333917Seadler
69333917Seadler	if (!S_ISREG(b->st.st_mode))
70333917Seadler		goto out;
71333917Seadler
72354939Sdelphij	b->elen =  CAST(size_t, b->st.st_size) < b->flen ?
73354939Sdelphij	    CAST(size_t, b->st.st_size) : b->flen;
74333917Seadler	if ((b->ebuf = malloc(b->elen)) == NULL)
75333917Seadler		goto out;
76333917Seadler
77333917Seadler	b->eoff = b->st.st_size - b->elen;
78333917Seadler	if (pread(b->fd, b->ebuf, b->elen, b->eoff) == -1) {
79333917Seadler		free(b->ebuf);
80360521Sdelphij		b->ebuf = NULL;
81333917Seadler		goto out;
82333917Seadler	}
83333917Seadler
84333917Seadler	return 0;
85333917Seadlerout:
86362844Sdelphij	b->elen = FILE_BADSIZE;
87333917Seadler	return -1;
88333917Seadler}
89