xref: /netbsd-src/external/bsd/file/dist/src/buffer.c (revision e15daa8be9575f7ad2ca804c7c7c2d7f8e182d98)
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