stdio: provide _unlocked variants of fflush, fputc, fputs, fread, fwrite
fflush_unlocked is currently desired in ports by sysutils/metalog, and redefined as the locked fflush. fputc_unlocked, fputs_unlocked, fread_unlocked, and fwrite_unlocked are currently desired in ports by devel/elfutils, and redefined as the locked fputs, fread, and fwrite respectively. Reviewed by: kib MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D23336
This commit is contained in:
parent
f2c462994d
commit
12fe218f0b
@ -346,7 +346,12 @@ int putchar_unlocked(int);
|
||||
void clearerr_unlocked(FILE *);
|
||||
int feof_unlocked(FILE *);
|
||||
int ferror_unlocked(FILE *);
|
||||
int fflush_unlocked(FILE *);
|
||||
int fileno_unlocked(FILE *);
|
||||
int fputs_unlocked(const char * __restrict, FILE * __restrict);
|
||||
size_t fread_unlocked(void * __restrict, size_t, size_t, FILE * __restrict);
|
||||
size_t fwrite_unlocked(const void * __restrict, size_t, size_t,
|
||||
FILE * __restrict);
|
||||
#endif
|
||||
|
||||
#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 500
|
||||
@ -507,10 +512,11 @@ extern int __isthreaded;
|
||||
* See ISO/IEC 9945-1 ANSI/IEEE Std 1003.1 Second Edition 1996-07-12
|
||||
* B.8.2.7 for the rationale behind the *_unlocked() macros.
|
||||
*/
|
||||
#define clearerr_unlocked(p) __sclearerr(p)
|
||||
#define feof_unlocked(p) __sfeof(p)
|
||||
#define ferror_unlocked(p) __sferror(p)
|
||||
#define clearerr_unlocked(p) __sclearerr(p)
|
||||
#define fileno_unlocked(p) __sfileno(p)
|
||||
#define fputc_unlocked(s, p) __sputc(s, p)
|
||||
#endif
|
||||
#if __POSIX_VISIBLE >= 199506
|
||||
#define getc_unlocked(fp) __sgetc(fp)
|
||||
|
@ -48,13 +48,17 @@ MLINKS+=ferror.3 ferror_unlocked.3 \
|
||||
ferror.3 clearerr.3 ferror.3 clearerr_unlocked.3 \
|
||||
ferror.3 feof.3 ferror.3 feof_unlocked.3 \
|
||||
ferror.3 fileno.3 ferror.3 fileno_unlocked.3
|
||||
MLINKS+=fflush.3 fpurge.3
|
||||
MLINKS+=fflush.3 fflush_unlocked.3 \
|
||||
fflush.3 fpurge.3
|
||||
MLINKS+=fgets.3 gets.3
|
||||
MLINKS+=fgets.3 gets_s.3
|
||||
MLINKS+=flockfile.3 ftrylockfile.3 flockfile.3 funlockfile.3
|
||||
MLINKS+=fopen.3 fdopen.3 fopen.3 freopen.3 fopen.3 fmemopen.3
|
||||
MLINKS+=fputs.3 puts.3
|
||||
MLINKS+=fread.3 fwrite.3
|
||||
MLINKS+=fputs.3 fputs_unlocked.3 \
|
||||
fputs.3 puts.3
|
||||
MLINKS+=fread.3 fread_unlocked.3 \
|
||||
fread.3 fwrite.3 \
|
||||
fread.3 fwrite_unlocked.3
|
||||
MLINKS+=fseek.3 fgetpos.3 fseek.3 fseeko.3 fseek.3 fsetpos.3 fseek.3 ftell.3 \
|
||||
fseek.3 ftello.3 fseek.3 rewind.3
|
||||
MLINKS+=funopen.3 fropen.3 funopen.3 fwopen.3
|
||||
|
@ -172,6 +172,10 @@ FBSD_1.5 {
|
||||
};
|
||||
|
||||
FBSD_1.6 {
|
||||
fflush_unlocked;
|
||||
fputs_unlocked;
|
||||
fread_unlocked;
|
||||
fwrite_unlocked;
|
||||
mkostempsat;
|
||||
};
|
||||
|
||||
|
@ -32,11 +32,12 @@
|
||||
.\" @(#)fflush.3 8.1 (Berkeley) 6/4/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 25, 2017
|
||||
.Dd January 23, 2020
|
||||
.Dt FFLUSH 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm fflush ,
|
||||
.Nm fflush_unlocked ,
|
||||
.Nm fpurge
|
||||
.Nd flush a stream
|
||||
.Sh LIBRARY
|
||||
@ -46,6 +47,8 @@
|
||||
.Ft int
|
||||
.Fn fflush "FILE *stream"
|
||||
.Ft int
|
||||
.Fn fflush_unlocked "FILE *stream"
|
||||
.Ft int
|
||||
.Fn fpurge "FILE *stream"
|
||||
.Sh DESCRIPTION
|
||||
The function
|
||||
@ -64,6 +67,16 @@ flushes
|
||||
.Em all
|
||||
open output streams.
|
||||
.Pp
|
||||
The
|
||||
.Fn fflush_unlocked
|
||||
function is equivalent to
|
||||
.Fn fflush ,
|
||||
except that the caller is responsible for locking the stream with
|
||||
.Xr flockfile 3
|
||||
before calling it.
|
||||
This function may be used to avoid the overhead of locking the stream and to
|
||||
prevent races when multiple threads are operating on the same stream.
|
||||
.Pp
|
||||
The function
|
||||
.Fn fpurge
|
||||
erases any input or output buffered in the given
|
||||
|
@ -100,6 +100,8 @@ __fflush(FILE *fp)
|
||||
return (retval);
|
||||
}
|
||||
|
||||
__weak_reference(__fflush, fflush_unlocked);
|
||||
|
||||
int
|
||||
__sflush(FILE *fp)
|
||||
{
|
||||
|
@ -44,6 +44,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include "local.h"
|
||||
#include "libc_private.h"
|
||||
|
||||
#undef fputc_unlocked
|
||||
|
||||
int
|
||||
fputc(int c, FILE *fp)
|
||||
{
|
||||
|
@ -32,11 +32,12 @@
|
||||
.\" @(#)fputs.3 8.1 (Berkeley) 6/4/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 4, 1993
|
||||
.Dd January 23, 2020
|
||||
.Dt FPUTS 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm fputs ,
|
||||
.Nm fputs_unlocked ,
|
||||
.Nm puts
|
||||
.Nd output a line to a stream
|
||||
.Sh LIBRARY
|
||||
@ -46,6 +47,8 @@
|
||||
.Ft int
|
||||
.Fn fputs "const char *str" "FILE *stream"
|
||||
.Ft int
|
||||
.Fn fputs_unlocked "const char *str" "FILE *stream"
|
||||
.Ft int
|
||||
.Fn puts "const char *str"
|
||||
.Sh DESCRIPTION
|
||||
The function
|
||||
@ -58,6 +61,16 @@ to the stream pointed to by
|
||||
.\" .Dv NUL
|
||||
.\" character is not written.
|
||||
.Pp
|
||||
The
|
||||
.Fn fputs_unlocked
|
||||
function is equivalent to
|
||||
.Fn fputs ,
|
||||
except that the caller is responsible for locking the stream with
|
||||
.Xr flockfile 3
|
||||
before calling it.
|
||||
This function may be used to avoid the overhead of locking the stream and to
|
||||
prevent races when multiple threads are operating on the same stream.
|
||||
.Pp
|
||||
The function
|
||||
.Fn puts
|
||||
writes the string
|
||||
|
@ -51,7 +51,7 @@ __FBSDID("$FreeBSD$");
|
||||
* Write the given string to the given file.
|
||||
*/
|
||||
int
|
||||
fputs(const char * __restrict s, FILE * __restrict fp)
|
||||
fputs_unlocked(const char * __restrict s, FILE * __restrict fp)
|
||||
{
|
||||
int retval;
|
||||
struct __suio uio;
|
||||
@ -61,11 +61,20 @@ fputs(const char * __restrict s, FILE * __restrict fp)
|
||||
uio.uio_resid = iov.iov_len = strlen(s);
|
||||
uio.uio_iov = &iov;
|
||||
uio.uio_iovcnt = 1;
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ORIENT(fp, -1);
|
||||
retval = __sfvwrite(fp, &uio);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
if (retval == 0)
|
||||
return (iov.iov_len > INT_MAX ? INT_MAX : iov.iov_len);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
int
|
||||
fputs(const char * __restrict s, FILE * __restrict fp)
|
||||
{
|
||||
int retval;
|
||||
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
retval = fputs_unlocked(s, fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (retval);
|
||||
}
|
||||
|
@ -32,12 +32,14 @@
|
||||
.\" @(#)fread.3 8.2 (Berkeley) 3/8/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 8, 1994
|
||||
.Dd January 23, 2020
|
||||
.Dt FREAD 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm fread ,
|
||||
.Nm fwrite
|
||||
.Nm fread_unlocked ,
|
||||
.Nm fwrite ,
|
||||
.Nm fwrite_unlocked
|
||||
.Nd binary stream input/output
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
@ -46,7 +48,11 @@
|
||||
.Ft size_t
|
||||
.Fn fread "void * restrict ptr" "size_t size" "size_t nmemb" "FILE * restrict stream"
|
||||
.Ft size_t
|
||||
.Fn fread_unlocked "void * restrict ptr" "size_t size" "size_t nmemb" "FILE * restrict stream"
|
||||
.Ft size_t
|
||||
.Fn fwrite "const void * restrict ptr" "size_t size" "size_t nmemb" "FILE * restrict stream"
|
||||
.Ft size_t
|
||||
.Fn fwrite_unlocked "const void * restrict ptr" "size_t size" "size_t nmemb" "FILE * restrict stream"
|
||||
.Sh DESCRIPTION
|
||||
The function
|
||||
.Fn fread
|
||||
@ -69,6 +75,21 @@ bytes long, to the stream pointed to by
|
||||
.Fa stream ,
|
||||
obtaining them from the location given by
|
||||
.Fa ptr .
|
||||
.Pp
|
||||
The
|
||||
.Fn fread_unlocked
|
||||
and
|
||||
.Fn fwrite_unlocked
|
||||
functions are equivalent to
|
||||
.Fn fread
|
||||
and
|
||||
.Fn fwrite
|
||||
respectively, except that the caller is responsible for locking the stream
|
||||
with
|
||||
.Xr flockfile 3
|
||||
before calling them.
|
||||
These functions may be used to avoid the overhead of locking the stream
|
||||
and to prevent races when multiple threads are operating on the same stream.
|
||||
.Sh RETURN VALUES
|
||||
The functions
|
||||
.Fn fread
|
||||
|
@ -115,3 +115,5 @@ __fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
|
||||
fp->_p += resid;
|
||||
return (count);
|
||||
}
|
||||
|
||||
__weak_reference(__fread, fread_unlocked);
|
||||
|
@ -52,7 +52,8 @@ __FBSDID("$FreeBSD$");
|
||||
* Return the number of whole objects written.
|
||||
*/
|
||||
size_t
|
||||
fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
|
||||
fwrite_unlocked(const void * __restrict buf, size_t size, size_t count,
|
||||
FILE * __restrict fp)
|
||||
{
|
||||
size_t n;
|
||||
struct __suio uio;
|
||||
@ -84,7 +85,6 @@ fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict
|
||||
uio.uio_iov = &iov;
|
||||
uio.uio_iovcnt = 1;
|
||||
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ORIENT(fp, -1);
|
||||
/*
|
||||
* The usual case is success (__sfvwrite returns 0);
|
||||
@ -93,6 +93,17 @@ fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict
|
||||
*/
|
||||
if (__sfvwrite(fp, &uio) != 0)
|
||||
count = (n - uio.uio_resid) / size;
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (count);
|
||||
}
|
||||
|
||||
size_t
|
||||
fwrite(const void * __restrict buf, size_t size, size_t count,
|
||||
FILE * __restrict fp)
|
||||
{
|
||||
size_t n;
|
||||
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
n = fwrite_unlocked(buf, size, count, fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (n);
|
||||
}
|
||||
|
@ -32,11 +32,12 @@
|
||||
.\" @(#)putc.3 8.1 (Berkeley) 6/4/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd January 10, 2003
|
||||
.Dd January 23, 2020
|
||||
.Dt PUTC 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm fputc ,
|
||||
.Nm fputc_unlocked ,
|
||||
.Nm putc ,
|
||||
.Nm putc_unlocked ,
|
||||
.Nm putchar ,
|
||||
@ -50,6 +51,8 @@
|
||||
.Ft int
|
||||
.Fn fputc "int c" "FILE *stream"
|
||||
.Ft int
|
||||
.Fn fputc_unlocked "int c" "FILE *stream"
|
||||
.Ft int
|
||||
.Fn putc "int c" "FILE *stream"
|
||||
.Ft int
|
||||
.Fn putc_unlocked "int c" "FILE *stream"
|
||||
@ -97,11 +100,13 @@ to the named output
|
||||
.Fa stream .
|
||||
.Pp
|
||||
The
|
||||
.Fn putc_unlocked
|
||||
.Fn fputc_unlocked ,
|
||||
.Fn putc_unlocked ,
|
||||
and
|
||||
.Fn putchar_unlocked
|
||||
functions are equivalent to
|
||||
.Fn putc
|
||||
.Fn fputc ,
|
||||
.Fn putc ,
|
||||
and
|
||||
.Fn putchar
|
||||
respectively,
|
||||
|
Loading…
Reference in New Issue
Block a user