xref: /freebsd/contrib/file/src/buffer.c (revision 898496ee09ed2b7d25f6807edc4515628196ec0a)
158a0f0d0SEitan Adler /*
258a0f0d0SEitan Adler  * Copyright (c) Christos Zoulas 2017.
358a0f0d0SEitan Adler  * All Rights Reserved.
458a0f0d0SEitan Adler  *
558a0f0d0SEitan Adler  * Redistribution and use in source and binary forms, with or without
658a0f0d0SEitan Adler  * modification, are permitted provided that the following conditions
758a0f0d0SEitan Adler  * are met:
858a0f0d0SEitan Adler  * 1. Redistributions of source code must retain the above copyright
958a0f0d0SEitan Adler  *    notice immediately at the beginning of the file, without modification,
1058a0f0d0SEitan Adler  *    this list of conditions, and the following disclaimer.
1158a0f0d0SEitan Adler  * 2. Redistributions in binary form must reproduce the above copyright
1258a0f0d0SEitan Adler  *    notice, this list of conditions and the following disclaimer in the
1358a0f0d0SEitan Adler  *    documentation and/or other materials provided with the distribution.
1458a0f0d0SEitan Adler  *
1558a0f0d0SEitan Adler  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1658a0f0d0SEitan Adler  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1758a0f0d0SEitan Adler  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1858a0f0d0SEitan Adler  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
1958a0f0d0SEitan Adler  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2058a0f0d0SEitan Adler  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2158a0f0d0SEitan Adler  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2258a0f0d0SEitan Adler  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2358a0f0d0SEitan Adler  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2458a0f0d0SEitan Adler  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2558a0f0d0SEitan Adler  * SUCH DAMAGE.
2658a0f0d0SEitan Adler  */
2758a0f0d0SEitan Adler #include "file.h"
2858a0f0d0SEitan Adler 
2958a0f0d0SEitan Adler #ifndef	lint
30*898496eeSXin LI FILE_RCSID("@(#)$File: buffer.c,v 1.13 2023/07/02 12:48:39 christos Exp $")
3158a0f0d0SEitan Adler #endif	/* lint */
3258a0f0d0SEitan Adler 
3358a0f0d0SEitan Adler #include "magic.h"
3458a0f0d0SEitan Adler #include <unistd.h>
3558a0f0d0SEitan Adler #include <string.h>
3658a0f0d0SEitan Adler #include <stdlib.h>
3758a0f0d0SEitan Adler #include <sys/stat.h>
3858a0f0d0SEitan Adler 
3958a0f0d0SEitan Adler void
buffer_init(struct buffer * b,int fd,const struct stat * st,const void * data,size_t len)4048c779cdSXin LI buffer_init(struct buffer *b, int fd, const struct stat *st, const void *data,
4148c779cdSXin LI     size_t len)
4258a0f0d0SEitan Adler {
4358a0f0d0SEitan Adler 	b->fd = fd;
4448c779cdSXin LI 	if (st)
4548c779cdSXin LI 		memcpy(&b->st, st, sizeof(b->st));
4648c779cdSXin LI 	else if (b->fd == -1 || fstat(b->fd, &b->st) == -1)
4758a0f0d0SEitan Adler 		memset(&b->st, 0, sizeof(b->st));
4858a0f0d0SEitan Adler 	b->fbuf = data;
4958a0f0d0SEitan Adler 	b->flen = len;
5058a0f0d0SEitan Adler 	b->eoff = 0;
5158a0f0d0SEitan Adler 	b->ebuf = NULL;
5258a0f0d0SEitan Adler 	b->elen = 0;
5358a0f0d0SEitan Adler }
5458a0f0d0SEitan Adler 
5558a0f0d0SEitan Adler void
buffer_fini(struct buffer * b)5658a0f0d0SEitan Adler buffer_fini(struct buffer *b)
5758a0f0d0SEitan Adler {
5858a0f0d0SEitan Adler 	free(b->ebuf);
59*898496eeSXin LI 	b->ebuf = NULL;
60*898496eeSXin LI 	b->elen = 0;
6158a0f0d0SEitan Adler }
6258a0f0d0SEitan Adler 
6358a0f0d0SEitan Adler int
buffer_fill(const struct buffer * bb)6458a0f0d0SEitan Adler buffer_fill(const struct buffer *bb)
6558a0f0d0SEitan Adler {
6658a0f0d0SEitan Adler 	struct buffer *b = CCAST(struct buffer *, bb);
6758a0f0d0SEitan Adler 
6858a0f0d0SEitan Adler 	if (b->elen != 0)
692726a701SXin LI 		return b->elen == FILE_BADSIZE ? -1 : 0;
7058a0f0d0SEitan Adler 
7158a0f0d0SEitan Adler 	if (!S_ISREG(b->st.st_mode))
7258a0f0d0SEitan Adler 		goto out;
7358a0f0d0SEitan Adler 
7448c779cdSXin LI 	b->elen = CAST(size_t, b->st.st_size) < b->flen ?
7548c779cdSXin LI 	    CAST(size_t, b->st.st_size) : b->flen;
76*898496eeSXin LI 	if (b->elen == 0) {
77*898496eeSXin LI 		free(b->ebuf);
78*898496eeSXin LI 		b->ebuf = NULL;
79*898496eeSXin LI 		return 0;
80*898496eeSXin LI 	}
8158a0f0d0SEitan Adler 	if ((b->ebuf = malloc(b->elen)) == NULL)
8258a0f0d0SEitan Adler 		goto out;
8358a0f0d0SEitan Adler 
8458a0f0d0SEitan Adler 	b->eoff = b->st.st_size - b->elen;
8558a0f0d0SEitan Adler 	if (pread(b->fd, b->ebuf, b->elen, b->eoff) == -1) {
8658a0f0d0SEitan Adler 		free(b->ebuf);
87d38c30c0SXin LI 		b->ebuf = NULL;
8858a0f0d0SEitan Adler 		goto out;
8958a0f0d0SEitan Adler 	}
9058a0f0d0SEitan Adler 
9158a0f0d0SEitan Adler 	return 0;
9258a0f0d0SEitan Adler out:
932726a701SXin LI 	b->elen = FILE_BADSIZE;
9458a0f0d0SEitan Adler 	return -1;
9558a0f0d0SEitan Adler }
96