xref: /netbsd-src/external/bsd/file/dist/src/buffer.c (revision dc958920d95b669c2a61806f127b489440aee7e5)
1*dc958920Schristos /*	$NetBSD: buffer.c,v 1.1.1.2 2019/05/22 17:19:56 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*dc958920Schristos FILE_RCSID("@(#)$File: buffer.c,v 1.6 2019/05/07 02:27:11 christos Exp $")
3452d7030aSchristos #else
35*dc958920Schristos __RCSID("$NetBSD: buffer.c,v 1.1.1.2 2019/05/22 17:19:56 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
46*dc958920Schristos buffer_init(struct buffer *b, int fd, const struct stat *st, const void *data,
47*dc958920Schristos     size_t len)
4852d7030aSchristos {
4952d7030aSchristos 	b->fd = fd;
50*dc958920Schristos 	if (st)
51*dc958920Schristos 		memcpy(&b->st, st, sizeof(b->st));
52*dc958920Schristos 	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
6252d7030aSchristos buffer_fini(struct buffer *b)
6352d7030aSchristos {
6452d7030aSchristos 	free(b->ebuf);
6552d7030aSchristos }
6652d7030aSchristos 
6752d7030aSchristos int
6852d7030aSchristos buffer_fill(const struct buffer *bb)
6952d7030aSchristos {
7052d7030aSchristos 	struct buffer *b = CCAST(struct buffer *, bb);
7152d7030aSchristos 
7252d7030aSchristos 	if (b->elen != 0)
73*dc958920Schristos 		return b->elen == CAST(size_t, ~0) ? -1 : 0;
7452d7030aSchristos 
7552d7030aSchristos 	if (!S_ISREG(b->st.st_mode))
7652d7030aSchristos 		goto out;
7752d7030aSchristos 
78*dc958920Schristos 	b->elen =  CAST(size_t, b->st.st_size) < b->flen ?
79*dc958920Schristos 	    CAST(size_t, b->st.st_size) : b->flen;
8052d7030aSchristos 	if ((b->ebuf = malloc(b->elen)) == NULL)
8152d7030aSchristos 		goto out;
8252d7030aSchristos 
8352d7030aSchristos 	b->eoff = b->st.st_size - b->elen;
8452d7030aSchristos 	if (pread(b->fd, b->ebuf, b->elen, b->eoff) == -1) {
8552d7030aSchristos 		free(b->ebuf);
8652d7030aSchristos 		goto out;
8752d7030aSchristos 	}
8852d7030aSchristos 
8952d7030aSchristos 	return 0;
9052d7030aSchristos out:
91*dc958920Schristos 	b->elen = CAST(size_t, ~0);
9252d7030aSchristos 	return -1;
9352d7030aSchristos }
94