Fix the handle locking in stdio
Fix the handle locking in stdio to use flockfile/funlockfile internally when and where required. Macros in <stdio.h> are updated to automatically call the underlying functions when the process is threaded to obtain the necessary locking. A private mutex is added to protect __sglue, the internal list of FILE handles, and another to protect the one-time initialization. Some routines in libc that use getc() change to use getc_unlocked() as they're either protected by their own lock or aren't thread-safe routines anyway. Based on OpenBSD change by guenther@openbsd.org http://www.mail-archive.com/source-changes@cvs.openbsd.org/msg01015.html Bug: 3446659 Change-Id: Ie82116e358c541718d6709ec45ca6796be5a007b
This commit is contained in:
parent
72f9a5c374
commit
f582340a6a
@ -170,6 +170,7 @@ __END_DECLS
|
|||||||
#define __SOFF 0x1000 /* set iff _offset is in fact correct */
|
#define __SOFF 0x1000 /* set iff _offset is in fact correct */
|
||||||
#define __SMOD 0x2000 /* true => fgetln modified _p text */
|
#define __SMOD 0x2000 /* true => fgetln modified _p text */
|
||||||
#define __SALC 0x4000 /* allocate string space dynamically */
|
#define __SALC 0x4000 /* allocate string space dynamically */
|
||||||
|
#define __SIGN 0x8000 /* ignore this file in _fwalk */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following three definitions are for ANSI C, which took them
|
* The following three definitions are for ANSI C, which took them
|
||||||
@ -406,38 +407,43 @@ static __inline int __sputc(int _c, FILE *_p) {
|
|||||||
#define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF)))
|
#define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF)))
|
||||||
#define __sfileno(p) ((p)->_file)
|
#define __sfileno(p) ((p)->_file)
|
||||||
|
|
||||||
#define feof(p) __sfeof(p)
|
extern int __isthreaded;
|
||||||
#define ferror(p) __sferror(p)
|
|
||||||
|
|
||||||
#ifndef _POSIX_THREADS
|
#define feof(p) (!__isthreaded ? __sfeof(p) : (feof)(p))
|
||||||
#define clearerr(p) __sclearerr(p)
|
#define ferror(p) (!__isthreaded ? __sferror(p) : (ferror)(p))
|
||||||
#endif
|
#define clearerr(p) (!__isthreaded ? __sclearerr(p) : (clearerr)(p))
|
||||||
|
|
||||||
#if __POSIX_VISIBLE
|
#if __POSIX_VISIBLE
|
||||||
#define fileno(p) __sfileno(p)
|
#define fileno(p) (!__isthreaded ? __sfileno(p) : (fileno)(p))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define getc(fp) (!__isthreaded ? __sgetc(fp) : (getc)(fp))
|
||||||
|
|
||||||
|
#if __BSD_VISIBLE
|
||||||
|
/*
|
||||||
|
* The macro implementations of putc and putc_unlocked are not
|
||||||
|
* fully POSIX compliant; they do not set errno on failure
|
||||||
|
*/
|
||||||
|
#define putc(x, fp) (!__isthreaded ? __sputc(x, fp) : (putc)(x, fp))
|
||||||
|
#endif /* __BSD_VISIBLE */
|
||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
#ifndef _POSIX_THREADS
|
#if __POSIX_VISIBLE >= 199506
|
||||||
#define getc(fp) __sgetc(fp)
|
|
||||||
#endif /* _POSIX_THREADS */
|
|
||||||
#define getc_unlocked(fp) __sgetc(fp)
|
#define getc_unlocked(fp) __sgetc(fp)
|
||||||
/*
|
/*
|
||||||
* The macro implementations of putc and putc_unlocked are not
|
* The macro implementations of putc and putc_unlocked are not
|
||||||
* fully POSIX compliant; they do not set errno on failure
|
* fully POSIX compliant; they do not set errno on failure
|
||||||
*/
|
*/
|
||||||
#if __BSD_VISIBLE
|
#if __BSD_VISIBLE
|
||||||
#ifndef _POSIX_THREADS
|
|
||||||
#define putc(x, fp) __sputc(x, fp)
|
|
||||||
#endif /* _POSIX_THREADS */
|
|
||||||
#define putc_unlocked(x, fp) __sputc(x, fp)
|
#define putc_unlocked(x, fp) __sputc(x, fp)
|
||||||
#endif /* __BSD_VISIBLE */
|
#endif /* __BSD_VISIBLE */
|
||||||
|
#endif /* __POSIX_VISIBLE >= 199506 */
|
||||||
#endif /* lint */
|
#endif /* lint */
|
||||||
|
|
||||||
#define getchar() getc(stdin)
|
#define getchar() getc(stdin)
|
||||||
#define putchar(x) putc(x, stdout)
|
#define putchar(x) putc(x, stdout)
|
||||||
#define getchar_unlocked() getc_unlocked(stdin)
|
#define getchar_unlocked() getc_unlocked(stdin)
|
||||||
#define putchar_unlocked(c) putc_unlocked(c, stdout)
|
#define putchar_unlocked(c) putc_unlocked(c, stdout)
|
||||||
|
|
||||||
#ifdef _GNU_SOURCE
|
#ifdef _GNU_SOURCE
|
||||||
/*
|
/*
|
||||||
|
@ -38,7 +38,7 @@ asprintf(char **str, const char *fmt, ...)
|
|||||||
goto err;
|
goto err;
|
||||||
f._bf._size = f._w = 127; /* Leave room for the NUL */
|
f._bf._size = f._w = 127; /* Leave room for the NUL */
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
ret = vfprintf(&f, fmt, ap);
|
ret = __vfprintf(&f, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -32,12 +32,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "local.h"
|
||||||
#undef clearerr
|
#undef clearerr
|
||||||
|
|
||||||
void
|
void
|
||||||
clearerr(FILE *fp)
|
clearerr(FILE *fp)
|
||||||
{
|
{
|
||||||
flockfile(fp);
|
FLOCKFILE(fp);
|
||||||
__sclearerr(fp);
|
__sclearerr(fp);
|
||||||
funlockfile(fp);
|
FUNLOCKFILE(fp);
|
||||||
}
|
}
|
||||||
|
@ -36,9 +36,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "local.h"
|
#include "local.h"
|
||||||
|
|
||||||
/* BIONIC: remove any file lock associated with a FILE* pointer */
|
|
||||||
extern void __fremovelock(FILE *fp);
|
|
||||||
|
|
||||||
int
|
int
|
||||||
fclose(FILE *fp)
|
fclose(FILE *fp)
|
||||||
{
|
{
|
||||||
@ -48,6 +45,7 @@ fclose(FILE *fp)
|
|||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
return (EOF);
|
return (EOF);
|
||||||
}
|
}
|
||||||
|
FLOCKFILE(fp);
|
||||||
WCIO_FREE(fp);
|
WCIO_FREE(fp);
|
||||||
r = fp->_flags & __SWR ? __sflush(fp) : 0;
|
r = fp->_flags & __SWR ? __sflush(fp) : 0;
|
||||||
if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0)
|
if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0)
|
||||||
@ -58,8 +56,8 @@ fclose(FILE *fp)
|
|||||||
FREEUB(fp);
|
FREEUB(fp);
|
||||||
if (HASLB(fp))
|
if (HASLB(fp))
|
||||||
FREELB(fp);
|
FREELB(fp);
|
||||||
fp->_flags = 0; /* Release this FILE for reuse. */
|
|
||||||
fp->_r = fp->_w = 0; /* Mess up if reaccessed. */
|
fp->_r = fp->_w = 0; /* Mess up if reaccessed. */
|
||||||
__fremovelock(fp);
|
fp->_flags = 0; /* Release this FILE for reuse. */
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (r);
|
return (r);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "local.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A subroutine version of the macro feof.
|
* A subroutine version of the macro feof.
|
||||||
@ -41,5 +42,10 @@
|
|||||||
int
|
int
|
||||||
feof(FILE *fp)
|
feof(FILE *fp)
|
||||||
{
|
{
|
||||||
return (__sfeof(fp));
|
int ret;
|
||||||
|
|
||||||
|
FLOCKFILE(fp);
|
||||||
|
ret = __sfeof(fp);
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
|
return (ret);
|
||||||
}
|
}
|
||||||
|
@ -39,14 +39,18 @@
|
|||||||
int
|
int
|
||||||
fflush(FILE *fp)
|
fflush(FILE *fp)
|
||||||
{
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
return (_fwalk(__sflush));
|
return (_fwalk(__sflush_locked));
|
||||||
|
FLOCKFILE(fp);
|
||||||
if ((fp->_flags & (__SWR | __SRW)) == 0) {
|
if ((fp->_flags & (__SWR | __SRW)) == 0) {
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
return (EOF);
|
r = EOF;
|
||||||
}
|
} else
|
||||||
return (__sflush(fp));
|
r = __sflush(fp);
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
|
return (r);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -80,3 +84,14 @@ __sflush(FILE *fp)
|
|||||||
}
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
__sflush_locked(FILE *fp)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
FLOCKFILE(fp);
|
||||||
|
r = __sflush(fp);
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
|
return (r);
|
||||||
|
}
|
||||||
|
@ -36,5 +36,5 @@
|
|||||||
int
|
int
|
||||||
fgetc(FILE *fp)
|
fgetc(FILE *fp)
|
||||||
{
|
{
|
||||||
return (__sgetc(fp));
|
return (getc(fp));
|
||||||
}
|
}
|
||||||
|
@ -71,19 +71,18 @@ char *
|
|||||||
fgetln(FILE *fp, size_t *lenp)
|
fgetln(FILE *fp, size_t *lenp)
|
||||||
{
|
{
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
|
char *ret;
|
||||||
size_t len;
|
size_t len;
|
||||||
size_t off;
|
size_t off;
|
||||||
|
|
||||||
|
FLOCKFILE(fp);
|
||||||
|
|
||||||
/* make sure there is input */
|
/* make sure there is input */
|
||||||
if (fp->_r <= 0 && __srefill(fp)) {
|
if (fp->_r <= 0 && __srefill(fp))
|
||||||
*lenp = 0;
|
goto error;
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* look for a newline in the input */
|
/* look for a newline in the input */
|
||||||
if ((p = memchr((void *)fp->_p, '\n', fp->_r)) != NULL) {
|
if ((p = memchr((void *)fp->_p, '\n', fp->_r)) != NULL) {
|
||||||
char *ret;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Found one. Flag buffer as modified to keep fseek from
|
* Found one. Flag buffer as modified to keep fseek from
|
||||||
* `optimising' a backward seek, in case the user stomps on
|
* `optimising' a backward seek, in case the user stomps on
|
||||||
@ -95,6 +94,7 @@ fgetln(FILE *fp, size_t *lenp)
|
|||||||
fp->_flags |= __SMOD;
|
fp->_flags |= __SMOD;
|
||||||
fp->_r -= len;
|
fp->_r -= len;
|
||||||
fp->_p = p;
|
fp->_p = p;
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,12 +139,15 @@ fgetln(FILE *fp, size_t *lenp)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
*lenp = len;
|
*lenp = len;
|
||||||
|
ret = (char *)fp->_lb._base;
|
||||||
#ifdef notdef
|
#ifdef notdef
|
||||||
fp->_lb._base[len] = '\0';
|
ret[len] = '\0';
|
||||||
#endif
|
#endif
|
||||||
return ((char *)fp->_lb._base);
|
FUNLOCKFILE(fp);
|
||||||
|
return (ret);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
*lenp = 0; /* ??? */
|
*lenp = 0; /* ??? */
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (NULL); /* ??? */
|
return (NULL); /* ??? */
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,7 @@ fgets(char *buf, int n, FILE *fp)
|
|||||||
if (n <= 0) /* sanity check */
|
if (n <= 0) /* sanity check */
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
|
FLOCKFILE(fp);
|
||||||
_SET_ORIENTATION(fp, -1);
|
_SET_ORIENTATION(fp, -1);
|
||||||
s = buf;
|
s = buf;
|
||||||
n--; /* leave space for NUL */
|
n--; /* leave space for NUL */
|
||||||
@ -61,8 +62,10 @@ fgets(char *buf, int n, FILE *fp)
|
|||||||
if (fp->_r <= 0) {
|
if (fp->_r <= 0) {
|
||||||
if (__srefill(fp)) {
|
if (__srefill(fp)) {
|
||||||
/* EOF/error: stop with partial or no line */
|
/* EOF/error: stop with partial or no line */
|
||||||
if (s == buf)
|
if (s == buf) {
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,6 +87,7 @@ fgets(char *buf, int n, FILE *fp)
|
|||||||
fp->_p = t;
|
fp->_p = t;
|
||||||
(void)memcpy((void *)s, (void *)p, len);
|
(void)memcpy((void *)s, (void *)p, len);
|
||||||
s[len] = '\0';
|
s[len] = '\0';
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (buf);
|
return (buf);
|
||||||
}
|
}
|
||||||
fp->_r -= len;
|
fp->_r -= len;
|
||||||
@ -93,5 +97,6 @@ fgets(char *buf, int n, FILE *fp)
|
|||||||
n -= len;
|
n -= len;
|
||||||
}
|
}
|
||||||
*s = '\0';
|
*s = '\0';
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (buf);
|
return (buf);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "local.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A subroutine version of the macro fileno.
|
* A subroutine version of the macro fileno.
|
||||||
@ -41,5 +42,10 @@
|
|||||||
int
|
int
|
||||||
fileno(FILE *fp)
|
fileno(FILE *fp)
|
||||||
{
|
{
|
||||||
return (__sfileno(fp));
|
int ret;
|
||||||
|
|
||||||
|
FLOCKFILE(fp);
|
||||||
|
ret = __sfileno(fp);
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
|
return (ret);
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "local.h"
|
#include "local.h"
|
||||||
#include "glue.h"
|
#include "glue.h"
|
||||||
|
#include "thread_private.h"
|
||||||
|
|
||||||
int __sdidinit;
|
int __sdidinit;
|
||||||
|
|
||||||
@ -54,6 +55,8 @@ int __sdidinit;
|
|||||||
static FILE usual[FOPEN_MAX - 3];
|
static FILE usual[FOPEN_MAX - 3];
|
||||||
static struct __sfileext usualext[FOPEN_MAX - 3];
|
static struct __sfileext usualext[FOPEN_MAX - 3];
|
||||||
static struct glue uglue = { 0, FOPEN_MAX - 3, usual };
|
static struct glue uglue = { 0, FOPEN_MAX - 3, usual };
|
||||||
|
static struct glue *lastglue = &uglue;
|
||||||
|
_THREAD_PRIVATE_MUTEX(__sfp_mutex);
|
||||||
|
|
||||||
static struct __sfileext __sFext[3];
|
static struct __sfileext __sFext[3];
|
||||||
FILE __sF[3] = {
|
FILE __sF[3] = {
|
||||||
@ -104,16 +107,25 @@ __sfp(void)
|
|||||||
|
|
||||||
if (!__sdidinit)
|
if (!__sdidinit)
|
||||||
__sinit();
|
__sinit();
|
||||||
for (g = &__sglue;; g = g->next) {
|
|
||||||
|
_THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex);
|
||||||
|
for (g = &__sglue; g != NULL; g = g->next) {
|
||||||
for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
|
for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
|
||||||
if (fp->_flags == 0)
|
if (fp->_flags == 0)
|
||||||
goto found;
|
goto found;
|
||||||
if (g->next == NULL && (g->next = moreglue(NDYNAMIC)) == NULL)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return (NULL);
|
|
||||||
|
/* release lock while mallocing */
|
||||||
|
_THREAD_PRIVATE_MUTEX_UNLOCK(__sfp_mutex);
|
||||||
|
if ((g = moreglue(NDYNAMIC)) == NULL)
|
||||||
|
return (NULL);
|
||||||
|
_THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex);
|
||||||
|
lastglue->next = g;
|
||||||
|
lastglue = g;
|
||||||
|
fp = g->iobs;
|
||||||
found:
|
found:
|
||||||
fp->_flags = 1; /* reserve this slot; caller sets real flags */
|
fp->_flags = 1; /* reserve this slot; caller sets real flags */
|
||||||
|
_THREAD_PRIVATE_MUTEX_UNLOCK(__sfp_mutex);
|
||||||
fp->_p = NULL; /* no current pointer */
|
fp->_p = NULL; /* no current pointer */
|
||||||
fp->_w = 0; /* nothing to read or write */
|
fp->_w = 0; /* nothing to read or write */
|
||||||
fp->_r = 0;
|
fp->_r = 0;
|
||||||
@ -144,8 +156,12 @@ f_prealloc(void)
|
|||||||
n = getdtablesize() - FOPEN_MAX + 20; /* 20 for slop. */
|
n = getdtablesize() - FOPEN_MAX + 20; /* 20 for slop. */
|
||||||
for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next)
|
for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next)
|
||||||
/* void */;
|
/* void */;
|
||||||
if (n > 0)
|
if (n > 0 && ((g = moreglue(n)) != NULL)) {
|
||||||
g->next = moreglue(n);
|
_THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex);
|
||||||
|
lastglue->next = g;
|
||||||
|
lastglue = g;
|
||||||
|
_THREAD_PRIVATE_MUTEX_UNLOCK(__sfp_mutex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -170,12 +186,18 @@ _cleanup(void)
|
|||||||
void
|
void
|
||||||
__sinit(void)
|
__sinit(void)
|
||||||
{
|
{
|
||||||
|
_THREAD_PRIVATE_MUTEX(__sinit_mutex);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
_THREAD_PRIVATE_MUTEX_LOCK(__sinit_mutex);
|
||||||
|
if (__sdidinit)
|
||||||
|
goto out; /* bail out if caller lost the race */
|
||||||
for (i = 0; i < FOPEN_MAX - 3; i++) {
|
for (i = 0; i < FOPEN_MAX - 3; i++) {
|
||||||
_FILEEXT_SETUP(usual+i, usualext+i);
|
_FILEEXT_SETUP(usual+i, usualext+i);
|
||||||
}
|
}
|
||||||
/* make sure we clean up on exit */
|
/* make sure we clean up on exit */
|
||||||
__atexit_register_cleanup(_cleanup); /* conservative */
|
__atexit_register_cleanup(_cleanup); /* conservative */
|
||||||
__sdidinit = 1;
|
__sdidinit = 1;
|
||||||
|
out:
|
||||||
|
_THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex);
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,9 @@
|
|||||||
int
|
int
|
||||||
fpurge(FILE *fp)
|
fpurge(FILE *fp)
|
||||||
{
|
{
|
||||||
|
FLOCKFILE(fp);
|
||||||
if (!fp->_flags) {
|
if (!fp->_flags) {
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
errno = EBADF;
|
errno = EBADF;
|
||||||
return(EOF);
|
return(EOF);
|
||||||
}
|
}
|
||||||
@ -54,5 +56,6 @@ fpurge(FILE *fp)
|
|||||||
fp->_p = fp->_bf._base;
|
fp->_p = fp->_bf._base;
|
||||||
fp->_r = 0;
|
fp->_r = 0;
|
||||||
fp->_w = fp->_flags & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
|
fp->_w = fp->_flags & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
@ -33,14 +33,9 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "local.h"
|
|
||||||
|
|
||||||
int
|
int
|
||||||
fputc(int c, FILE *fp)
|
fputc(int c, FILE *fp)
|
||||||
{
|
{
|
||||||
if (cantwrite(fp)) {
|
|
||||||
errno = EBADF;
|
|
||||||
return (EOF);
|
|
||||||
}
|
|
||||||
return (putc(c, fp));
|
return (putc(c, fp));
|
||||||
}
|
}
|
||||||
|
@ -44,11 +44,15 @@ fputs(const char *s, FILE *fp)
|
|||||||
{
|
{
|
||||||
struct __suio uio;
|
struct __suio uio;
|
||||||
struct __siov iov;
|
struct __siov iov;
|
||||||
|
int ret;
|
||||||
|
|
||||||
iov.iov_base = (void *)s;
|
iov.iov_base = (void *)s;
|
||||||
iov.iov_len = uio.uio_resid = strlen(s);
|
iov.iov_len = uio.uio_resid = strlen(s);
|
||||||
uio.uio_iov = &iov;
|
uio.uio_iov = &iov;
|
||||||
uio.uio_iovcnt = 1;
|
uio.uio_iovcnt = 1;
|
||||||
|
FLOCKFILE(fp);
|
||||||
_SET_ORIENTATION(fp, -1);
|
_SET_ORIENTATION(fp, -1);
|
||||||
return (__sfvwrite(fp, &uio));
|
ret = __sfvwrite(fp, &uio);
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
|
return (ret);
|
||||||
}
|
}
|
||||||
|
@ -39,9 +39,8 @@
|
|||||||
static int
|
static int
|
||||||
lflush(FILE *fp)
|
lflush(FILE *fp)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
|
if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
|
||||||
return (__sflush(fp));
|
return (__sflush_locked(fp));
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +59,7 @@ fread(void *buf, size_t size, size_t count, FILE *fp)
|
|||||||
*/
|
*/
|
||||||
if ((resid = count * size) == 0)
|
if ((resid = count * size) == 0)
|
||||||
return (0);
|
return (0);
|
||||||
|
FLOCKFILE(fp);
|
||||||
if (fp->_r < 0)
|
if (fp->_r < 0)
|
||||||
fp->_r = 0;
|
fp->_r = 0;
|
||||||
total = resid;
|
total = resid;
|
||||||
@ -79,20 +79,25 @@ fread(void *buf, size_t size, size_t count, FILE *fp)
|
|||||||
fp->_r = 0; /* largely a convenience for callers */
|
fp->_r = 0; /* largely a convenience for callers */
|
||||||
|
|
||||||
/* SysV does not make this test; take it out for compatibility */
|
/* SysV does not make this test; take it out for compatibility */
|
||||||
if (fp->_flags & __SEOF)
|
if (fp->_flags & __SEOF) {
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (EOF);
|
return (EOF);
|
||||||
|
}
|
||||||
|
|
||||||
/* if not already reading, have to be reading and writing */
|
/* if not already reading, have to be reading and writing */
|
||||||
if ((fp->_flags & __SRD) == 0) {
|
if ((fp->_flags & __SRD) == 0) {
|
||||||
if ((fp->_flags & __SRW) == 0) {
|
if ((fp->_flags & __SRW) == 0) {
|
||||||
errno = EBADF;
|
|
||||||
fp->_flags |= __SERR;
|
fp->_flags |= __SERR;
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
|
errno = EBADF;
|
||||||
return (EOF);
|
return (EOF);
|
||||||
}
|
}
|
||||||
/* switch to reading */
|
/* switch to reading */
|
||||||
if (fp->_flags & __SWR) {
|
if (fp->_flags & __SWR) {
|
||||||
if (__sflush(fp))
|
if (__sflush(fp)) {
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (EOF);
|
return (EOF);
|
||||||
|
}
|
||||||
fp->_flags &= ~__SWR;
|
fp->_flags &= ~__SWR;
|
||||||
fp->_w = 0;
|
fp->_w = 0;
|
||||||
fp->_lbfsize = 0;
|
fp->_lbfsize = 0;
|
||||||
@ -116,8 +121,16 @@ fread(void *buf, size_t size, size_t count, FILE *fp)
|
|||||||
* standard.
|
* standard.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (fp->_flags & (__SLBF|__SNBF))
|
if (fp->_flags & (__SLBF|__SNBF)) {
|
||||||
|
/* Ignore this file in _fwalk to deadlock. */
|
||||||
|
fp->_flags |= __SIGN;
|
||||||
(void) _fwalk(lflush);
|
(void) _fwalk(lflush);
|
||||||
|
fp->_flags &= ~__SIGN;
|
||||||
|
|
||||||
|
/* Now flush this file without locking it. */
|
||||||
|
if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
|
||||||
|
__sflush(fp);
|
||||||
|
}
|
||||||
|
|
||||||
while (resid > 0) {
|
while (resid > 0) {
|
||||||
int len = (*fp->_read)(fp->_cookie, p, resid );
|
int len = (*fp->_read)(fp->_cookie, p, resid );
|
||||||
@ -128,11 +141,13 @@ fread(void *buf, size_t size, size_t count, FILE *fp)
|
|||||||
else {
|
else {
|
||||||
fp->_flags |= __SERR;
|
fp->_flags |= __SERR;
|
||||||
}
|
}
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return ((total - resid) / size);
|
return ((total - resid) / size);
|
||||||
}
|
}
|
||||||
p += len;
|
p += len;
|
||||||
resid -= len;
|
resid -= len;
|
||||||
}
|
}
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (count);
|
return (count);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -146,6 +161,7 @@ fread(void *buf, size_t size, size_t count, FILE *fp)
|
|||||||
resid -= r;
|
resid -= r;
|
||||||
if (__srefill(fp)) {
|
if (__srefill(fp)) {
|
||||||
/* no more input: return partial result */
|
/* no more input: return partial result */
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return ((total - resid) / size);
|
return ((total - resid) / size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,5 +170,6 @@ fread(void *buf, size_t size, size_t count, FILE *fp)
|
|||||||
(void)memcpy((void *)p, (void *)fp->_p, resid);
|
(void)memcpy((void *)p, (void *)fp->_p, resid);
|
||||||
fp->_r -= resid;
|
fp->_r -= resid;
|
||||||
fp->_p += resid;
|
fp->_p += resid;
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (count);
|
return (count);
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,8 @@ freopen(const char *file, const char *mode, FILE *fp)
|
|||||||
if (!__sdidinit)
|
if (!__sdidinit)
|
||||||
__sinit();
|
__sinit();
|
||||||
|
|
||||||
|
FLOCKFILE(fp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are actually programs that depend on being able to "freopen"
|
* There are actually programs that depend on being able to "freopen"
|
||||||
* descriptors that weren't originally open. Keep this from breaking.
|
* descriptors that weren't originally open. Keep this from breaking.
|
||||||
@ -120,6 +122,7 @@ freopen(const char *file, const char *mode, FILE *fp)
|
|||||||
|
|
||||||
if (f < 0) { /* did not get it after all */
|
if (f < 0) { /* did not get it after all */
|
||||||
fp->_flags = 0; /* set it free */
|
fp->_flags = 0; /* set it free */
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
errno = sverrno; /* restore in case _close clobbered */
|
errno = sverrno; /* restore in case _close clobbered */
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@ -154,5 +157,6 @@ freopen(const char *file, const char *mode, FILE *fp)
|
|||||||
*/
|
*/
|
||||||
if (oflags & O_APPEND)
|
if (oflags & O_APPEND)
|
||||||
(void) __sseek((void *)fp, (fpos_t)0, SEEK_END);
|
(void) __sseek((void *)fp, (fpos_t)0, SEEK_END);
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (fp);
|
return (fp);
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,7 @@ fseeko(FILE *fp, off_t offset, int whence)
|
|||||||
* Change any SEEK_CUR to SEEK_SET, and check `whence' argument.
|
* Change any SEEK_CUR to SEEK_SET, and check `whence' argument.
|
||||||
* After this, whence is either SEEK_SET or SEEK_END.
|
* After this, whence is either SEEK_SET or SEEK_END.
|
||||||
*/
|
*/
|
||||||
|
FLOCKFILE(fp);
|
||||||
switch (whence) {
|
switch (whence) {
|
||||||
|
|
||||||
case SEEK_CUR:
|
case SEEK_CUR:
|
||||||
@ -83,8 +84,10 @@ fseeko(FILE *fp, off_t offset, int whence)
|
|||||||
curoff = fp->_offset;
|
curoff = fp->_offset;
|
||||||
else {
|
else {
|
||||||
curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR);
|
curoff = (*seekfn)(fp->_cookie, (fpos_t)0, SEEK_CUR);
|
||||||
if (curoff == (fpos_t)-1)
|
if (curoff == (fpos_t)-1) {
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (EOF);
|
return (EOF);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (fp->_flags & __SRD) {
|
if (fp->_flags & __SRD) {
|
||||||
curoff -= fp->_r;
|
curoff -= fp->_r;
|
||||||
@ -105,6 +108,7 @@ fseeko(FILE *fp, off_t offset, int whence)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return (EOF);
|
return (EOF);
|
||||||
}
|
}
|
||||||
@ -189,6 +193,7 @@ fseeko(FILE *fp, off_t offset, int whence)
|
|||||||
if (HASUB(fp))
|
if (HASUB(fp))
|
||||||
FREEUB(fp);
|
FREEUB(fp);
|
||||||
fp->_flags &= ~__SEOF;
|
fp->_flags &= ~__SEOF;
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,6 +220,7 @@ fseeko(FILE *fp, off_t offset, int whence)
|
|||||||
fp->_p += n;
|
fp->_p += n;
|
||||||
fp->_r -= n;
|
fp->_r -= n;
|
||||||
}
|
}
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -224,6 +230,7 @@ fseeko(FILE *fp, off_t offset, int whence)
|
|||||||
dumb:
|
dumb:
|
||||||
if (__sflush(fp) ||
|
if (__sflush(fp) ||
|
||||||
(*seekfn)(fp->_cookie, (fpos_t)offset, whence) == POS_ERR) {
|
(*seekfn)(fp->_cookie, (fpos_t)offset, whence) == POS_ERR) {
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (EOF);
|
return (EOF);
|
||||||
}
|
}
|
||||||
/* success: clear EOF indicator and discard ungetc() data */
|
/* success: clear EOF indicator and discard ungetc() data */
|
||||||
@ -233,6 +240,7 @@ dumb:
|
|||||||
fp->_r = 0;
|
fp->_r = 0;
|
||||||
/* fp->_w = 0; */ /* unnecessary (I think...) */
|
/* fp->_w = 0; */ /* unnecessary (I think...) */
|
||||||
fp->_flags &= ~__SEOF;
|
fp->_flags &= ~__SEOF;
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,20 +45,22 @@ ftello(FILE *fp)
|
|||||||
|
|
||||||
if (fp->_seek == NULL) {
|
if (fp->_seek == NULL) {
|
||||||
errno = ESPIPE; /* historic practice */
|
errno = ESPIPE; /* historic practice */
|
||||||
return ((off_t)-1);
|
pos = -1;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find offset of underlying I/O object, then
|
* Find offset of underlying I/O object, then
|
||||||
* adjust for buffered bytes.
|
* adjust for buffered bytes.
|
||||||
*/
|
*/
|
||||||
|
FLOCKFILE(fp);
|
||||||
__sflush(fp); /* may adjust seek offset on append stream */
|
__sflush(fp); /* may adjust seek offset on append stream */
|
||||||
if (fp->_flags & __SOFF)
|
if (fp->_flags & __SOFF)
|
||||||
pos = fp->_offset;
|
pos = fp->_offset;
|
||||||
else {
|
else {
|
||||||
pos = (*fp->_seek)(fp->_cookie, (fpos_t)0, SEEK_CUR);
|
pos = (*fp->_seek)(fp->_cookie, (fpos_t)0, SEEK_CUR);
|
||||||
if (pos == -1L)
|
if (pos == -1)
|
||||||
return (pos);
|
goto out;
|
||||||
}
|
}
|
||||||
if (fp->_flags & __SRD) {
|
if (fp->_flags & __SRD) {
|
||||||
/*
|
/*
|
||||||
@ -77,6 +79,7 @@ ftello(FILE *fp)
|
|||||||
*/
|
*/
|
||||||
pos += fp->_p - fp->_bf._base;
|
pos += fp->_p - fp->_bf._base;
|
||||||
}
|
}
|
||||||
|
out: FUNLOCKFILE(fp);
|
||||||
return (pos);
|
return (pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,8 +45,9 @@ _fwalk(int (*function)(FILE *))
|
|||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
for (g = &__sglue; g != NULL; g = g->next)
|
for (g = &__sglue; g != NULL; g = g->next)
|
||||||
for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
|
for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) {
|
||||||
if (fp->_flags != 0)
|
if ((fp->_flags != 0) && ((fp->_flags & __SIGN) == 0))
|
||||||
ret |= (*function)(fp);
|
ret |= (*function)(fp);
|
||||||
|
}
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ fwrite(const void *buf, size_t size, size_t count, FILE *fp)
|
|||||||
size_t n;
|
size_t n;
|
||||||
struct __suio uio;
|
struct __suio uio;
|
||||||
struct __siov iov;
|
struct __siov iov;
|
||||||
|
int ret;
|
||||||
|
|
||||||
iov.iov_base = (void *)buf;
|
iov.iov_base = (void *)buf;
|
||||||
uio.uio_resid = iov.iov_len = n = count * size;
|
uio.uio_resid = iov.iov_len = n = count * size;
|
||||||
@ -56,7 +57,10 @@ fwrite(const void *buf, size_t size, size_t count, FILE *fp)
|
|||||||
* skip the divide if this happens, since divides are
|
* skip the divide if this happens, since divides are
|
||||||
* generally slow and since this occurs whenever size==0.
|
* generally slow and since this occurs whenever size==0.
|
||||||
*/
|
*/
|
||||||
if (__sfvwrite(fp, &uio) == 0)
|
FLOCKFILE(fp);
|
||||||
|
ret = __sfvwrite(fp, &uio);
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
|
if (ret == 0)
|
||||||
return (count);
|
return (count);
|
||||||
return ((n - uio.uio_resid) / size);
|
return ((n - uio.uio_resid) / size);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "local.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A subroutine version of the macro getc_unlocked.
|
* A subroutine version of the macro getc_unlocked.
|
||||||
@ -54,8 +55,8 @@ getc(FILE *fp)
|
|||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
flockfile(fp);
|
FLOCKFILE(fp);
|
||||||
c = __sgetc(fp);
|
c = __sgetc(fp);
|
||||||
funlockfile(fp);
|
FUNLOCKFILE(fp);
|
||||||
return (c);
|
return (c);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include "local.h"
|
||||||
|
|
||||||
__warn_references(gets,
|
__warn_references(gets,
|
||||||
"warning: gets() is very unsafe; consider using fgets()");
|
"warning: gets() is very unsafe; consider using fgets()");
|
||||||
@ -42,14 +43,17 @@ gets(char *buf)
|
|||||||
int c;
|
int c;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
for (s = buf; (c = getchar()) != '\n';)
|
FLOCKFILE(stdin);
|
||||||
|
for (s = buf; (c = getchar_unlocked()) != '\n';)
|
||||||
if (c == EOF)
|
if (c == EOF)
|
||||||
if (s == buf)
|
if (s == buf) {
|
||||||
|
FUNLOCKFILE(stdin);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
else
|
} else
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
*s++ = c;
|
*s++ = c;
|
||||||
*s = '\0';
|
*s = '\0';
|
||||||
|
FUNLOCKFILE(stdin);
|
||||||
return (buf);
|
return (buf);
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int __sflush(FILE *);
|
int __sflush(FILE *);
|
||||||
|
int __sflush_locked(FILE *);
|
||||||
FILE *__sfp(void);
|
FILE *__sfp(void);
|
||||||
int __srefill(FILE *);
|
int __srefill(FILE *);
|
||||||
int __sread(void *, char *, int);
|
int __sread(void *, char *, int);
|
||||||
@ -59,6 +60,7 @@ int __swhatbuf(FILE *, size_t *, int *);
|
|||||||
int _fwalk(int (*)(FILE *));
|
int _fwalk(int (*)(FILE *));
|
||||||
int __swsetup(FILE *);
|
int __swsetup(FILE *);
|
||||||
int __sflags(const char *, int *);
|
int __sflags(const char *, int *);
|
||||||
|
int __vfprintf(FILE *, const char *, __va_list);
|
||||||
|
|
||||||
extern void __atexit_register_cleanup(void (*)(void));
|
extern void __atexit_register_cleanup(void (*)(void));
|
||||||
extern int __sdidinit;
|
extern int __sdidinit;
|
||||||
@ -89,3 +91,6 @@ extern int __sdidinit;
|
|||||||
free((char *)(fp)->_lb._base); \
|
free((char *)(fp)->_lb._base); \
|
||||||
(fp)->_lb._base = NULL; \
|
(fp)->_lb._base = NULL; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define FLOCKFILE(fp) do { if (__isthreaded) flockfile(fp); } while (0)
|
||||||
|
#define FUNLOCKFILE(fp) do { if (__isthreaded) funlockfile(fp); } while (0)
|
||||||
|
@ -60,8 +60,8 @@ putc(int c, FILE *fp)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
flockfile(fp);
|
FLOCKFILE(fp);
|
||||||
ret = putc_unlocked(c, fp);
|
ret = putc_unlocked(c, fp);
|
||||||
funlockfile(fp);
|
FUNLOCKFILE(fp);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "local.h"
|
||||||
#include "fvwrite.h"
|
#include "fvwrite.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -44,6 +45,7 @@ puts(const char *s)
|
|||||||
size_t c = strlen(s);
|
size_t c = strlen(s);
|
||||||
struct __suio uio;
|
struct __suio uio;
|
||||||
struct __siov iov[2];
|
struct __siov iov[2];
|
||||||
|
int ret;
|
||||||
|
|
||||||
iov[0].iov_base = (void *)s;
|
iov[0].iov_base = (void *)s;
|
||||||
iov[0].iov_len = c;
|
iov[0].iov_len = c;
|
||||||
@ -52,5 +54,8 @@ puts(const char *s)
|
|||||||
uio.uio_resid = c + 1;
|
uio.uio_resid = c + 1;
|
||||||
uio.uio_iov = &iov[0];
|
uio.uio_iov = &iov[0];
|
||||||
uio.uio_iovcnt = 2;
|
uio.uio_iovcnt = 2;
|
||||||
return (__sfvwrite(stdout, &uio) ? EOF : '\n');
|
FLOCKFILE(stdout);
|
||||||
|
ret = __sfvwrite(stdout, &uio);
|
||||||
|
FUNLOCKFILE(stdout);
|
||||||
|
return (ret ? EOF : '\n');
|
||||||
}
|
}
|
||||||
|
@ -39,9 +39,8 @@
|
|||||||
static int
|
static int
|
||||||
lflush(FILE *fp)
|
lflush(FILE *fp)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
|
if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
|
||||||
return (__sflush(fp));
|
return (__sflush_locked(fp)); /* ignored... */
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,8 +102,16 @@ __srefill(FILE *fp)
|
|||||||
* flush all line buffered output files, per the ANSI C
|
* flush all line buffered output files, per the ANSI C
|
||||||
* standard.
|
* standard.
|
||||||
*/
|
*/
|
||||||
if (fp->_flags & (__SLBF|__SNBF))
|
if (fp->_flags & (__SLBF|__SNBF)) {
|
||||||
|
/* Ignore this file in _fwalk to avoid potential deadlock. */
|
||||||
|
fp->_flags |= __SIGN;
|
||||||
(void) _fwalk(lflush);
|
(void) _fwalk(lflush);
|
||||||
|
fp->_flags &= ~__SIGN;
|
||||||
|
|
||||||
|
/* Now flush this file without locking it. */
|
||||||
|
if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
|
||||||
|
__sflush(fp);
|
||||||
|
}
|
||||||
fp->_p = fp->_bf._base;
|
fp->_p = fp->_bf._base;
|
||||||
fp->_r = (*fp->_read)(fp->_cookie, (char *)fp->_p, fp->_bf._size);
|
fp->_r = (*fp->_read)(fp->_cookie, (char *)fp->_p, fp->_bf._size);
|
||||||
fp->_flags &= ~__SMOD; /* buffer contents are again pristine */
|
fp->_flags &= ~__SMOD; /* buffer contents are again pristine */
|
||||||
|
@ -61,6 +61,7 @@ setvbuf(FILE *fp, char *buf, int mode, size_t size)
|
|||||||
* malloc()ed. We also clear any eof condition, as if this were
|
* malloc()ed. We also clear any eof condition, as if this were
|
||||||
* a seek.
|
* a seek.
|
||||||
*/
|
*/
|
||||||
|
FLOCKFILE(fp);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
(void)__sflush(fp);
|
(void)__sflush(fp);
|
||||||
if (HASUB(fp))
|
if (HASUB(fp))
|
||||||
@ -107,6 +108,7 @@ nbf:
|
|||||||
fp->_w = 0;
|
fp->_w = 0;
|
||||||
fp->_bf._base = fp->_p = fp->_nbuf;
|
fp->_bf._base = fp->_p = fp->_nbuf;
|
||||||
fp->_bf._size = 1;
|
fp->_bf._size = 1;
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
flags |= __SMBF;
|
flags |= __SMBF;
|
||||||
@ -145,6 +147,7 @@ nbf:
|
|||||||
/* begin/continue reading, or stay in intermediate state */
|
/* begin/continue reading, or stay in intermediate state */
|
||||||
fp->_w = 0;
|
fp->_w = 0;
|
||||||
}
|
}
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
__atexit_register_cleanup(_cleanup);
|
__atexit_register_cleanup(_cleanup);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
|
@ -60,7 +60,7 @@ snprintf(char *str, size_t n, const char *fmt, ...)
|
|||||||
f._bf._base = f._p = (unsigned char *)str;
|
f._bf._base = f._p = (unsigned char *)str;
|
||||||
f._bf._size = f._w = n - 1;
|
f._bf._size = f._w = n - 1;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
ret = vfprintf(&f, fmt, ap);
|
ret = __vfprintf(&f, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
*f._p = '\0';
|
*f._p = '\0';
|
||||||
return (ret);
|
return (ret);
|
||||||
|
@ -56,7 +56,7 @@ sprintf(char *str, const char *fmt, ...)
|
|||||||
f._bf._base = f._p = (unsigned char *)str;
|
f._bf._base = f._p = (unsigned char *)str;
|
||||||
f._bf._size = f._w = INT_MAX;
|
f._bf._size = f._w = INT_MAX;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
ret = vfprintf(&f, fmt, ap);
|
ret = __vfprintf(&f, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
*f._p = '\0';
|
*f._p = '\0';
|
||||||
return (ret);
|
return (ret);
|
||||||
|
@ -82,17 +82,20 @@ ungetc(int c, FILE *fp)
|
|||||||
return (EOF);
|
return (EOF);
|
||||||
if (!__sdidinit)
|
if (!__sdidinit)
|
||||||
__sinit();
|
__sinit();
|
||||||
|
FLOCKFILE(fp);
|
||||||
_SET_ORIENTATION(fp, -1);
|
_SET_ORIENTATION(fp, -1);
|
||||||
if ((fp->_flags & __SRD) == 0) {
|
if ((fp->_flags & __SRD) == 0) {
|
||||||
/*
|
/*
|
||||||
* Not already reading: no good unless reading-and-writing.
|
* Not already reading: no good unless reading-and-writing.
|
||||||
* Otherwise, flush any current write stuff.
|
* Otherwise, flush any current write stuff.
|
||||||
*/
|
*/
|
||||||
if ((fp->_flags & __SRW) == 0)
|
if ((fp->_flags & __SRW) == 0) {
|
||||||
|
error: FUNLOCKFILE(fp);
|
||||||
return (EOF);
|
return (EOF);
|
||||||
|
}
|
||||||
if (fp->_flags & __SWR) {
|
if (fp->_flags & __SWR) {
|
||||||
if (__sflush(fp))
|
if (__sflush(fp))
|
||||||
return (EOF);
|
goto error;
|
||||||
fp->_flags &= ~__SWR;
|
fp->_flags &= ~__SWR;
|
||||||
fp->_w = 0;
|
fp->_w = 0;
|
||||||
fp->_lbfsize = 0;
|
fp->_lbfsize = 0;
|
||||||
@ -107,9 +110,10 @@ ungetc(int c, FILE *fp)
|
|||||||
*/
|
*/
|
||||||
if (HASUB(fp)) {
|
if (HASUB(fp)) {
|
||||||
if (fp->_r >= _UB(fp)._size && __submore(fp))
|
if (fp->_r >= _UB(fp)._size && __submore(fp))
|
||||||
return (EOF);
|
goto error;
|
||||||
*--fp->_p = c;
|
*--fp->_p = c;
|
||||||
fp->_r++;
|
inc_ret: fp->_r++;
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (c);
|
return (c);
|
||||||
}
|
}
|
||||||
fp->_flags &= ~__SEOF;
|
fp->_flags &= ~__SEOF;
|
||||||
@ -122,8 +126,7 @@ ungetc(int c, FILE *fp)
|
|||||||
if (fp->_bf._base != NULL && fp->_p > fp->_bf._base &&
|
if (fp->_bf._base != NULL && fp->_p > fp->_bf._base &&
|
||||||
fp->_p[-1] == c) {
|
fp->_p[-1] == c) {
|
||||||
fp->_p--;
|
fp->_p--;
|
||||||
fp->_r++;
|
goto inc_ret;
|
||||||
return (c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -137,5 +140,6 @@ ungetc(int c, FILE *fp)
|
|||||||
fp->_ubuf[sizeof(fp->_ubuf) - 1] = c;
|
fp->_ubuf[sizeof(fp->_ubuf) - 1] = c;
|
||||||
fp->_p = &fp->_ubuf[sizeof(fp->_ubuf) - 1];
|
fp->_p = &fp->_ubuf[sizeof(fp->_ubuf) - 1];
|
||||||
fp->_r = 1;
|
fp->_r = 1;
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (c);
|
return (c);
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ vasprintf(char **str, const char *fmt, __va_list ap)
|
|||||||
if (f._bf._base == NULL)
|
if (f._bf._base == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
f._bf._size = f._w = 127; /* Leave room for the NUL */
|
f._bf._size = f._w = 127; /* Leave room for the NUL */
|
||||||
ret = vfprintf(&f, fmt, ap);
|
ret = __vfprintf(&f, fmt, ap);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
goto err;
|
goto err;
|
||||||
*f._p = '\0';
|
*f._p = '\0';
|
||||||
|
@ -100,8 +100,8 @@ __sbprintf(FILE *fp, const char *fmt, va_list ap)
|
|||||||
fake._lbfsize = 0; /* not actually used, but Just In Case */
|
fake._lbfsize = 0; /* not actually used, but Just In Case */
|
||||||
|
|
||||||
/* do the work, then copy any error status */
|
/* do the work, then copy any error status */
|
||||||
ret = vfprintf(&fake, fmt, ap);
|
ret = __vfprintf(&fake, fmt, ap);
|
||||||
if (ret >= 0 && fflush(&fake))
|
if (ret >= 0 && __sflush(&fake))
|
||||||
ret = EOF;
|
ret = EOF;
|
||||||
if (fake._flags & __SERR)
|
if (fake._flags & __SERR)
|
||||||
fp->_flags |= __SERR;
|
fp->_flags |= __SERR;
|
||||||
@ -157,6 +157,17 @@ static int _my_isnan(double);
|
|||||||
|
|
||||||
int
|
int
|
||||||
vfprintf(FILE *fp, const char *fmt0, __va_list ap)
|
vfprintf(FILE *fp, const char *fmt0, __va_list ap)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
FLOCKFILE(fp);
|
||||||
|
ret = __vfprintf(fp, fmt0, ap);
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
__vfprintf(FILE *fp, const char *fmt0, __va_list ap)
|
||||||
{
|
{
|
||||||
char *fmt; /* format string */
|
char *fmt; /* format string */
|
||||||
int ch; /* character from fmt */
|
int ch; /* character from fmt */
|
||||||
|
@ -117,6 +117,7 @@ VFSCANF(FILE *fp, const char *fmt0, __va_list ap)
|
|||||||
static short basefix[17] =
|
static short basefix[17] =
|
||||||
{ 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
|
{ 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
|
||||||
|
|
||||||
|
FLOCKFILE(fp);
|
||||||
_SET_ORIENTATION(fp, -1);
|
_SET_ORIENTATION(fp, -1);
|
||||||
|
|
||||||
nassigned = 0;
|
nassigned = 0;
|
||||||
@ -124,8 +125,10 @@ VFSCANF(FILE *fp, const char *fmt0, __va_list ap)
|
|||||||
base = 0; /* XXX just to keep gcc happy */
|
base = 0; /* XXX just to keep gcc happy */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
c = *fmt++;
|
c = *fmt++;
|
||||||
if (c == 0)
|
if (c == 0) {
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (nassigned);
|
return (nassigned);
|
||||||
|
}
|
||||||
if (isspace(c)) {
|
if (isspace(c)) {
|
||||||
while ((fp->_r > 0 || __srefill(fp) == 0) &&
|
while ((fp->_r > 0 || __srefill(fp) == 0) &&
|
||||||
isspace(*fp->_p))
|
isspace(*fp->_p))
|
||||||
@ -292,6 +295,7 @@ literal:
|
|||||||
* Disgusting backwards compatibility hacks. XXX
|
* Disgusting backwards compatibility hacks. XXX
|
||||||
*/
|
*/
|
||||||
case '\0': /* compat */
|
case '\0': /* compat */
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (EOF);
|
return (EOF);
|
||||||
|
|
||||||
default: /* compat */
|
default: /* compat */
|
||||||
@ -689,8 +693,10 @@ literal:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
input_failure:
|
input_failure:
|
||||||
return (nassigned ? nassigned : -1);
|
if (nassigned == 0)
|
||||||
|
nassigned = -1;
|
||||||
match_failure:
|
match_failure:
|
||||||
|
FUNLOCKFILE(fp);
|
||||||
return (nassigned);
|
return (nassigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ vsnprintf(char *str, size_t n, const char *fmt, __va_list ap)
|
|||||||
f._flags = __SWR | __SSTR;
|
f._flags = __SWR | __SSTR;
|
||||||
f._bf._base = f._p = (unsigned char *)str;
|
f._bf._base = f._p = (unsigned char *)str;
|
||||||
f._bf._size = f._w = n - 1;
|
f._bf._size = f._w = n - 1;
|
||||||
ret = vfprintf(&f, fmt, ap);
|
ret = __vfprintf(&f, fmt, ap);
|
||||||
*f._p = '\0';
|
*f._p = '\0';
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ vsprintf(char *str, const char *fmt, __va_list ap)
|
|||||||
f._flags = __SWR | __SSTR;
|
f._flags = __SWR | __SSTR;
|
||||||
f._bf._base = f._p = (unsigned char *)str;
|
f._bf._base = f._p = (unsigned char *)str;
|
||||||
f._bf._size = f._w = INT_MAX;
|
f._bf._size = f._w = INT_MAX;
|
||||||
ret = vfprintf(&f, fmt, ap);
|
ret = __vfprintf(&f, fmt, ap);
|
||||||
*f._p = '\0';
|
*f._p = '\0';
|
||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
|
@ -65,20 +65,20 @@ __swbuf(int c, FILE *fp)
|
|||||||
* stuff c into the buffer. If this causes the buffer to fill
|
* stuff c into the buffer. If this causes the buffer to fill
|
||||||
* completely, or if c is '\n' and the file is line buffered,
|
* completely, or if c is '\n' and the file is line buffered,
|
||||||
* flush it (perhaps a second time). The second flush will always
|
* flush it (perhaps a second time). The second flush will always
|
||||||
* happen on unbuffered streams, where _bf._size==1; fflush()
|
* happen on unbuffered streams, where _bf._size==1; __sflush()
|
||||||
* guarantees that putc() will always call wbuf() by setting _w
|
* guarantees that putc() will always call wbuf() by setting _w
|
||||||
* to 0, so we need not do anything else.
|
* to 0, so we need not do anything else.
|
||||||
*/
|
*/
|
||||||
n = fp->_p - fp->_bf._base;
|
n = fp->_p - fp->_bf._base;
|
||||||
if (n >= fp->_bf._size) {
|
if (n >= fp->_bf._size) {
|
||||||
if (fflush(fp))
|
if (__sflush(fp))
|
||||||
return (EOF);
|
return (EOF);
|
||||||
n = 0;
|
n = 0;
|
||||||
}
|
}
|
||||||
fp->_w--;
|
fp->_w--;
|
||||||
*fp->_p++ = c;
|
*fp->_p++ = c;
|
||||||
if (++n == fp->_bf._size || (fp->_flags & __SLBF && c == '\n'))
|
if (++n == fp->_bf._size || (fp->_flags & __SLBF && c == '\n'))
|
||||||
if (fflush(fp))
|
if (__sflush(fp))
|
||||||
return (EOF);
|
return (EOF);
|
||||||
return (c);
|
return (c);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user