Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/stdio/fread.c
39476 views
1
/*-
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* Copyright (c) 1990, 1993
5
* The Regents of the University of California. All rights reserved.
6
*
7
* This code is derived from software contributed to Berkeley by
8
* Chris Torek.
9
*
10
* Redistribution and use in source and binary forms, with or without
11
* modification, are permitted provided that the following conditions
12
* are met:
13
* 1. Redistributions of source code must retain the above copyright
14
* notice, this list of conditions and the following disclaimer.
15
* 2. Redistributions in binary form must reproduce the above copyright
16
* notice, this list of conditions and the following disclaimer in the
17
* documentation and/or other materials provided with the distribution.
18
* 3. Neither the name of the University nor the names of its contributors
19
* may be used to endorse or promote products derived from this software
20
* without specific prior written permission.
21
*
22
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
* SUCH DAMAGE.
33
*/
34
35
#include "namespace.h"
36
#include <errno.h>
37
#include <stdint.h>
38
#include <stdio.h>
39
#include <string.h>
40
#include <ssp/ssp.h>
41
#include "un-namespace.h"
42
#include "local.h"
43
#include "libc_private.h"
44
45
/*
46
* MT-safe version
47
*/
48
49
size_t
50
__ssp_real(fread)(void * __restrict buf, size_t size, size_t count,
51
FILE * __restrict fp)
52
{
53
size_t ret;
54
55
FLOCKFILE_CANCELSAFE(fp);
56
ret = __fread(buf, size, count, fp);
57
FUNLOCKFILE_CANCELSAFE();
58
return (ret);
59
}
60
61
size_t
62
__fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
63
{
64
size_t resid;
65
char *p;
66
int r;
67
size_t total;
68
69
/*
70
* ANSI and SUSv2 require a return value of 0 if size or count are 0.
71
*/
72
if ((count == 0) || (size == 0))
73
return (0);
74
75
/*
76
* Check for integer overflow. As an optimization, first check that
77
* at least one of {count, size} is at least 2^16, since if both
78
* values are less than that, their product can't possible overflow
79
* (size_t is always at least 32 bits on FreeBSD).
80
*/
81
if (((count | size) > 0xFFFF) &&
82
(count > SIZE_MAX / size)) {
83
errno = EINVAL;
84
fp->_flags |= __SERR;
85
return (0);
86
}
87
88
/*
89
* Compute the (now required to not overflow) number of bytes to
90
* read and actually do the work.
91
*/
92
resid = count * size;
93
ORIENT(fp, -1);
94
if (fp->_r < 0)
95
fp->_r = 0;
96
total = resid;
97
p = buf;
98
99
/*
100
* If we're unbuffered we know that the buffer in fp is empty so
101
* we can read directly into buf. This is much faster than a
102
* series of one byte reads into fp->_nbuf.
103
*/
104
if ((fp->_flags & __SNBF) != 0 && buf != NULL) {
105
while (resid > 0) {
106
/* set up the buffer */
107
fp->_bf._base = fp->_p = p;
108
fp->_bf._size = resid;
109
110
if (__srefill(fp)) {
111
/* no more input: return partial result */
112
count = (total - resid) / size;
113
break;
114
}
115
p += fp->_r;
116
resid -= fp->_r;
117
}
118
119
/* restore the old buffer (see __smakebuf) */
120
fp->_bf._base = fp->_p = fp->_nbuf;
121
fp->_bf._size = 1;
122
fp->_r = 0;
123
124
return (count);
125
}
126
127
while (resid > (r = fp->_r)) {
128
if (r != 0) {
129
(void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
130
fp->_p += r;
131
/* fp->_r = 0 ... done in __srefill */
132
p += r;
133
resid -= r;
134
}
135
if (__srefill(fp)) {
136
/* no more input: return partial result */
137
return ((total - resid) / size);
138
}
139
}
140
(void)memcpy((void *)p, (void *)fp->_p, resid);
141
fp->_r -= resid;
142
fp->_p += resid;
143
return (count);
144
}
145
146
__weak_reference(__fread, fread_unlocked);
147
148