1*e15daa8bSchristos /* $NetBSD: buffer.c,v 1.1.1.5 2023/08/18 18:36:49 christos Exp $ */
252d7030aSchristos
352d7030aSchristos /*
452d7030aSchristos * Copyright (c) Christos Zoulas 2017.
552d7030aSchristos * All Rights Reserved.
652d7030aSchristos *
752d7030aSchristos * Redistribution and use in source and binary forms, with or without
852d7030aSchristos * modification, are permitted provided that the following conditions
952d7030aSchristos * are met:
1052d7030aSchristos * 1. Redistributions of source code must retain the above copyright
1152d7030aSchristos * notice immediately at the beginning of the file, without modification,
1252d7030aSchristos * this list of conditions, and the following disclaimer.
1352d7030aSchristos * 2. Redistributions in binary form must reproduce the above copyright
1452d7030aSchristos * notice, this list of conditions and the following disclaimer in the
1552d7030aSchristos * documentation and/or other materials provided with the distribution.
1652d7030aSchristos *
1752d7030aSchristos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1852d7030aSchristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1952d7030aSchristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2052d7030aSchristos * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
2152d7030aSchristos * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2252d7030aSchristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2352d7030aSchristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2452d7030aSchristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2552d7030aSchristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2652d7030aSchristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2752d7030aSchristos * SUCH DAMAGE.
2852d7030aSchristos */
2952d7030aSchristos #include "file.h"
3052d7030aSchristos
3152d7030aSchristos #ifndef lint
3252d7030aSchristos #if 0
33*e15daa8bSchristos FILE_RCSID("@(#)$File: buffer.c,v 1.13 2023/07/02 12:48:39 christos Exp $")
3452d7030aSchristos #else
35*e15daa8bSchristos __RCSID("$NetBSD: buffer.c,v 1.1.1.5 2023/08/18 18:36:49 christos Exp $");
3652d7030aSchristos #endif
3752d7030aSchristos #endif /* lint */
3852d7030aSchristos
3952d7030aSchristos #include "magic.h"
4052d7030aSchristos #include <unistd.h>
4152d7030aSchristos #include <string.h>
4252d7030aSchristos #include <stdlib.h>
4352d7030aSchristos #include <sys/stat.h>
4452d7030aSchristos
4552d7030aSchristos void
buffer_init(struct buffer * b,int fd,const struct stat * st,const void * data,size_t len)46dc958920Schristos buffer_init(struct buffer *b, int fd, const struct stat *st, const void *data,
47dc958920Schristos size_t len)
4852d7030aSchristos {
4952d7030aSchristos b->fd = fd;
50dc958920Schristos if (st)
51dc958920Schristos memcpy(&b->st, st, sizeof(b->st));
52dc958920Schristos else if (b->fd == -1 || fstat(b->fd, &b->st) == -1)
5352d7030aSchristos memset(&b->st, 0, sizeof(b->st));
5452d7030aSchristos b->fbuf = data;
5552d7030aSchristos b->flen = len;
5652d7030aSchristos b->eoff = 0;
5752d7030aSchristos b->ebuf = NULL;
5852d7030aSchristos b->elen = 0;
5952d7030aSchristos }
6052d7030aSchristos
6152d7030aSchristos void
buffer_fini(struct buffer * b)6252d7030aSchristos buffer_fini(struct buffer *b)
6352d7030aSchristos {
6452d7030aSchristos free(b->ebuf);
65*e15daa8bSchristos b->ebuf = NULL;
66*e15daa8bSchristos b->elen = 0;
6752d7030aSchristos }
6852d7030aSchristos
6952d7030aSchristos int
buffer_fill(const struct buffer * bb)7052d7030aSchristos buffer_fill(const struct buffer *bb)
7152d7030aSchristos {
7252d7030aSchristos struct buffer *b = CCAST(struct buffer *, bb);
7352d7030aSchristos
7452d7030aSchristos if (b->elen != 0)
7503c288bbSchristos return b->elen == FILE_BADSIZE ? -1 : 0;
7652d7030aSchristos
7752d7030aSchristos if (!S_ISREG(b->st.st_mode))
7852d7030aSchristos goto out;
7952d7030aSchristos
80dc958920Schristos b->elen = CAST(size_t, b->st.st_size) < b->flen ?
81dc958920Schristos CAST(size_t, b->st.st_size) : b->flen;
82*e15daa8bSchristos if (b->elen == 0) {
83*e15daa8bSchristos free(b->ebuf);
84*e15daa8bSchristos b->ebuf = NULL;
85*e15daa8bSchristos return 0;
86*e15daa8bSchristos }
8752d7030aSchristos if ((b->ebuf = malloc(b->elen)) == NULL)
8852d7030aSchristos goto out;
8952d7030aSchristos
9052d7030aSchristos b->eoff = b->st.st_size - b->elen;
9152d7030aSchristos if (pread(b->fd, b->ebuf, b->elen, b->eoff) == -1) {
9252d7030aSchristos free(b->ebuf);
93eff51ed2Schristos b->ebuf = NULL;
9452d7030aSchristos goto out;
9552d7030aSchristos }
9652d7030aSchristos
9752d7030aSchristos return 0;
9852d7030aSchristos out:
9903c288bbSchristos b->elen = FILE_BADSIZE;
10052d7030aSchristos return -1;
10152d7030aSchristos }
102