Make stdio deferred cancel-safe.
If used with fopen(3)/fdopen(3)-ed FILEs, stdio accurately uses non-cancellable internal versions of the functions, i.e. it seems to be fine with regard to cancellation. But if the funopen(3) and f{r,w}open(3) functions were used to open the FILE, and corresponding user functions create cancellation points (they typically have no other choice), then stdio code at least leaks FILE' lock. The change installs cleanup handler which unlocks FILE. Some minimal restructuring of the code was required to make it use common return place to satisfy hand-rolled pthread_cleanup_pop() requirements. Noted by: eugen Reviewed by: eugen, vangyzen Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D11246
This commit is contained in:
parent
d137278838
commit
fda0a14f47
@ -97,7 +97,7 @@ fdclose(FILE *fp, int *fdp)
|
||||
return (EOF);
|
||||
}
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
r = 0;
|
||||
if (fp->_close != __sclose) {
|
||||
r = EOF;
|
||||
@ -115,7 +115,7 @@ fdclose(FILE *fp, int *fdp)
|
||||
*fdp = fp->_file;
|
||||
r = cleanfile(fp, false);
|
||||
}
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
|
||||
return (r);
|
||||
}
|
||||
@ -130,9 +130,9 @@ fclose(FILE *fp)
|
||||
return (EOF);
|
||||
}
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
r = cleanfile(fp, true);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ fflush(FILE *fp)
|
||||
|
||||
if (fp == NULL)
|
||||
return (_fwalk(sflush_locked));
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
|
||||
/*
|
||||
* There is disagreement about the correct behaviour of fflush()
|
||||
@ -76,7 +76,7 @@ fflush(FILE *fp)
|
||||
retval = 0;
|
||||
else
|
||||
retval = __sflush(fp);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (retval);
|
||||
}
|
||||
|
||||
@ -143,8 +143,8 @@ sflush_locked(FILE *fp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ret = __sflush(fp);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
}
|
||||
|
@ -46,10 +46,10 @@ int
|
||||
fgetc(FILE *fp)
|
||||
{
|
||||
int retval;
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
/* Orientation set by __sgetc() when buffer is empty. */
|
||||
/* ORIENT(fp, -1); */
|
||||
retval = __sgetc(fp);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (retval);
|
||||
}
|
||||
|
@ -85,22 +85,21 @@ char *
|
||||
fgetln(FILE *fp, size_t *lenp)
|
||||
{
|
||||
unsigned char *p;
|
||||
char *ret;
|
||||
size_t len;
|
||||
size_t off;
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ORIENT(fp, -1);
|
||||
/* make sure there is input */
|
||||
if (fp->_r <= 0 && __srefill(fp)) {
|
||||
*lenp = 0;
|
||||
FUNLOCKFILE(fp);
|
||||
return (NULL);
|
||||
ret = NULL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* look for a newline in the input */
|
||||
if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) != NULL) {
|
||||
char *ret;
|
||||
|
||||
/*
|
||||
* Found one. Flag buffer as modified to keep fseek from
|
||||
* `optimising' a backward seek, in case the user stomps on
|
||||
@ -112,8 +111,7 @@ fgetln(FILE *fp, size_t *lenp)
|
||||
fp->_flags |= __SMOD;
|
||||
fp->_r -= len;
|
||||
fp->_p = p;
|
||||
FUNLOCKFILE(fp);
|
||||
return (ret);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -163,12 +161,14 @@ fgetln(FILE *fp, size_t *lenp)
|
||||
#ifdef notdef
|
||||
fp->_lb._base[len] = '\0';
|
||||
#endif
|
||||
FUNLOCKFILE(fp);
|
||||
return ((char *)fp->_lb._base);
|
||||
ret = (char *)fp->_lb._base;
|
||||
end:
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
|
||||
error:
|
||||
*lenp = 0; /* ??? */
|
||||
fp->_flags |= __SERR;
|
||||
FUNLOCKFILE(fp);
|
||||
return (NULL); /* ??? */
|
||||
ret = NULL;
|
||||
goto end;
|
||||
}
|
||||
|
@ -53,17 +53,17 @@ char *
|
||||
fgets(char * __restrict buf, int n, FILE * __restrict fp)
|
||||
{
|
||||
size_t len;
|
||||
char *s;
|
||||
char *s, *ret;
|
||||
unsigned char *p, *t;
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ORIENT(fp, -1);
|
||||
|
||||
if (n <= 0) { /* sanity check */
|
||||
fp->_flags |= __SERR;
|
||||
errno = EINVAL;
|
||||
FUNLOCKFILE(fp);
|
||||
return (NULL);
|
||||
ret = NULL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
s = buf;
|
||||
@ -76,8 +76,8 @@ fgets(char * __restrict buf, int n, FILE * __restrict fp)
|
||||
if (__srefill(fp)) {
|
||||
/* EOF/error: stop with partial or no line */
|
||||
if (!__sfeof(fp) || s == buf) {
|
||||
FUNLOCKFILE(fp);
|
||||
return (NULL);
|
||||
ret = NULL;
|
||||
goto end;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -100,8 +100,8 @@ fgets(char * __restrict buf, int n, FILE * __restrict fp)
|
||||
fp->_p = t;
|
||||
(void)memcpy((void *)s, (void *)p, len);
|
||||
s[len] = 0;
|
||||
FUNLOCKFILE(fp);
|
||||
return (buf);
|
||||
ret = buf;
|
||||
goto end;
|
||||
}
|
||||
fp->_r -= len;
|
||||
fp->_p += len;
|
||||
@ -110,6 +110,8 @@ fgets(char * __restrict buf, int n, FILE * __restrict fp)
|
||||
n -= len;
|
||||
}
|
||||
*s = 0;
|
||||
FUNLOCKFILE(fp);
|
||||
return (buf);
|
||||
ret = buf;
|
||||
end:
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
}
|
||||
|
@ -52,10 +52,10 @@ fgetwc_l(FILE *fp, locale_t locale)
|
||||
wint_t r;
|
||||
FIX_LOCALE(locale);
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ORIENT(fp, 1);
|
||||
r = __fgetwc(fp, locale);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
@ -45,13 +45,14 @@ wchar_t *fgetwln_l(FILE * __restrict, size_t *, locale_t);
|
||||
wchar_t *
|
||||
fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale)
|
||||
{
|
||||
wchar_t *ret;
|
||||
wint_t wc;
|
||||
size_t len;
|
||||
int savserr;
|
||||
|
||||
FIX_LOCALE(locale);
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ORIENT(fp, 1);
|
||||
|
||||
savserr = fp->_flags & __SERR;
|
||||
@ -77,14 +78,16 @@ fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale)
|
||||
if (len == 0)
|
||||
goto error;
|
||||
|
||||
FUNLOCKFILE(fp);
|
||||
*lenp = len;
|
||||
return ((wchar_t *)fp->_lb._base);
|
||||
ret = (wchar_t *)fp->_lb._base;
|
||||
end:
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
|
||||
error:
|
||||
FUNLOCKFILE(fp);
|
||||
*lenp = 0;
|
||||
return (NULL);
|
||||
ret = NULL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
wchar_t *
|
||||
|
@ -46,14 +46,14 @@ wchar_t *
|
||||
fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale)
|
||||
{
|
||||
int sret;
|
||||
wchar_t *wsp;
|
||||
wchar_t *wsp, *ret;
|
||||
size_t nconv;
|
||||
const char *src;
|
||||
unsigned char *nl;
|
||||
FIX_LOCALE(locale);
|
||||
struct xlocale_ctype *l = XLOCALE_CTYPE(locale);
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ORIENT(fp, 1);
|
||||
|
||||
if (n <= 0) {
|
||||
@ -113,12 +113,14 @@ fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale)
|
||||
goto error;
|
||||
ok:
|
||||
*wsp = L'\0';
|
||||
FUNLOCKFILE(fp);
|
||||
ret = ws;
|
||||
end:
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ws);
|
||||
|
||||
error:
|
||||
FUNLOCKFILE(fp);
|
||||
return (NULL);
|
||||
ret = NULL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
wchar_t *
|
||||
|
@ -46,10 +46,10 @@ int
|
||||
fputc(int c, FILE *fp)
|
||||
{
|
||||
int retval;
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
/* Orientation set by __sputc() when buffer is full. */
|
||||
/* ORIENT(fp, -1); */
|
||||
retval = __sputc(c, fp);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (retval);
|
||||
}
|
||||
|
@ -59,10 +59,10 @@ 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(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ORIENT(fp, -1);
|
||||
retval = __sfvwrite(fp, &uio);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
if (retval == 0)
|
||||
return (iov.iov_len > INT_MAX ? INT_MAX : iov.iov_len);
|
||||
return (retval);
|
||||
|
@ -74,10 +74,10 @@ fputwc_l(wchar_t wc, FILE *fp, locale_t locale)
|
||||
wint_t r;
|
||||
FIX_LOCALE(locale);
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ORIENT(fp, 1);
|
||||
r = __fputwc(wc, fp, locale);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
@ -53,11 +53,13 @@ fputws_l(const wchar_t * __restrict ws, FILE * __restrict fp, locale_t locale)
|
||||
const wchar_t *wsp;
|
||||
FIX_LOCALE(locale);
|
||||
struct xlocale_ctype *l = XLOCALE_CTYPE(locale);
|
||||
int ret;
|
||||
|
||||
FLOCKFILE(fp);
|
||||
ret = -1;
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ORIENT(fp, 1);
|
||||
if (prepwrite(fp) != 0)
|
||||
goto error;
|
||||
goto end;
|
||||
uio.uio_iov = &iov;
|
||||
uio.uio_iovcnt = 1;
|
||||
iov.iov_base = buf;
|
||||
@ -66,17 +68,15 @@ fputws_l(const wchar_t * __restrict ws, FILE * __restrict fp, locale_t locale)
|
||||
nbytes = l->__wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf),
|
||||
&fp->_mbstate);
|
||||
if (nbytes == (size_t)-1)
|
||||
goto error;
|
||||
goto end;
|
||||
uio.uio_resid = iov.iov_len = nbytes;
|
||||
if (__sfvwrite(fp, &uio) != 0)
|
||||
goto error;
|
||||
goto end;
|
||||
} while (wsp != NULL);
|
||||
FUNLOCKFILE(fp);
|
||||
return (0);
|
||||
|
||||
error:
|
||||
FUNLOCKFILE(fp);
|
||||
return (-1);
|
||||
ret = 0;
|
||||
end:
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -54,9 +54,9 @@ fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
|
||||
{
|
||||
size_t ret;
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ret = __fread(buf, size, count, fp);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ freopen(const char * __restrict file, const char * __restrict mode,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
|
||||
if (!__sdidinit)
|
||||
__sinit();
|
||||
@ -81,24 +81,24 @@ freopen(const char * __restrict file, const char * __restrict mode,
|
||||
if (file == NULL) {
|
||||
/* See comment below regarding freopen() of closed files. */
|
||||
if (fp->_flags == 0) {
|
||||
FUNLOCKFILE(fp);
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
fp = NULL;
|
||||
goto end;
|
||||
}
|
||||
if ((dflags = _fcntl(fp->_file, F_GETFL)) < 0) {
|
||||
sverrno = errno;
|
||||
fclose(fp);
|
||||
FUNLOCKFILE(fp);
|
||||
errno = sverrno;
|
||||
return (NULL);
|
||||
fp = NULL;
|
||||
goto end;
|
||||
}
|
||||
/* Work around incorrect O_ACCMODE. */
|
||||
if ((dflags & O_ACCMODE) != O_RDWR &&
|
||||
(dflags & (O_ACCMODE | O_EXEC)) != (oflags & O_ACCMODE)) {
|
||||
fclose(fp);
|
||||
FUNLOCKFILE(fp);
|
||||
errno = EBADF;
|
||||
return (NULL);
|
||||
fp = NULL;
|
||||
goto end;
|
||||
}
|
||||
if (fp->_flags & __SWR)
|
||||
(void) __sflush(fp);
|
||||
@ -108,9 +108,9 @@ freopen(const char * __restrict file, const char * __restrict mode,
|
||||
if (_fcntl(fp->_file, F_SETFL, dflags) < 0) {
|
||||
sverrno = errno;
|
||||
fclose(fp);
|
||||
FUNLOCKFILE(fp);
|
||||
errno = sverrno;
|
||||
return (NULL);
|
||||
fp = NULL;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (oflags & O_TRUNC)
|
||||
@ -193,9 +193,9 @@ freopen(const char * __restrict file, const char * __restrict mode,
|
||||
if (isopen)
|
||||
(void) (*fp->_close)(fp->_cookie);
|
||||
fp->_flags = 0; /* set it free */
|
||||
FUNLOCKFILE(fp);
|
||||
errno = sverrno; /* restore in case _close clobbered */
|
||||
return (NULL);
|
||||
fp = NULL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -221,9 +221,9 @@ freopen(const char * __restrict file, const char * __restrict mode,
|
||||
*/
|
||||
if (f > SHRT_MAX) {
|
||||
fp->_flags = 0; /* set it free */
|
||||
FUNLOCKFILE(fp);
|
||||
errno = EMFILE;
|
||||
return (NULL);
|
||||
fp = NULL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
fp->_flags = flags;
|
||||
@ -245,6 +245,7 @@ freopen(const char * __restrict file, const char * __restrict mode,
|
||||
fp->_flags2 |= __S2OAP;
|
||||
(void) _sseek(fp, (fpos_t)0, SEEK_END);
|
||||
}
|
||||
FUNLOCKFILE(fp);
|
||||
end:
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (fp);
|
||||
}
|
||||
|
@ -56,10 +56,10 @@ fscanf(FILE * __restrict fp, char const * __restrict fmt, ...)
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ret = __svfscanf(fp, __get_locale(), fmt, ap);
|
||||
va_end(ap);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
}
|
||||
int
|
||||
@ -70,9 +70,9 @@ fscanf_l(FILE * __restrict fp, locale_t locale, char const * __restrict fmt, ...
|
||||
FIX_LOCALE(locale);
|
||||
|
||||
va_start(ap, fmt);
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ret = __svfscanf(fp, locale, fmt, ap);
|
||||
va_end(ap);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
}
|
||||
|
@ -60,9 +60,9 @@ fseek(FILE *fp, long offset, int whence)
|
||||
if (!__sdidinit)
|
||||
__sinit();
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ret = _fseeko(fp, (off_t)offset, whence, 1);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
if (ret == 0)
|
||||
errno = serrno;
|
||||
return (ret);
|
||||
@ -78,9 +78,9 @@ fseeko(FILE *fp, off_t offset, int whence)
|
||||
if (!__sdidinit)
|
||||
__sinit();
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ret = _fseeko(fp, offset, whence, 0);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
if (ret == 0)
|
||||
errno = serrno;
|
||||
return (ret);
|
||||
|
@ -82,7 +82,7 @@ fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict
|
||||
uio.uio_iov = &iov;
|
||||
uio.uio_iovcnt = 1;
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ORIENT(fp, -1);
|
||||
/*
|
||||
* The usual case is success (__sfvwrite returns 0);
|
||||
@ -91,6 +91,6 @@ 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(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (count);
|
||||
}
|
||||
|
@ -49,11 +49,11 @@ int
|
||||
getc(FILE *fp)
|
||||
{
|
||||
int retval;
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
/* Orientation set by __sgetc() when buffer is empty. */
|
||||
/* ORIENT(fp, -1); */
|
||||
retval = __sgetc(fp);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (retval);
|
||||
}
|
||||
|
||||
|
@ -52,11 +52,11 @@ int
|
||||
getchar(void)
|
||||
{
|
||||
int retval;
|
||||
FLOCKFILE(stdin);
|
||||
FLOCKFILE_CANCELSAFE(stdin);
|
||||
/* Orientation set by __sgetc() when buffer is empty. */
|
||||
/* ORIENT(stdin, -1); */
|
||||
retval = __sgetc(stdin);
|
||||
FUNLOCKFILE(stdin);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (retval);
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ getdelim(char ** __restrict linep, size_t * __restrict linecapp, int delim,
|
||||
u_char *endp;
|
||||
size_t linelen;
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ORIENT(fp, -1);
|
||||
|
||||
if (linep == NULL || linecapp == NULL) {
|
||||
@ -127,9 +127,9 @@ getdelim(char ** __restrict linep, size_t * __restrict linecapp, int delim,
|
||||
/* If fp is at EOF already, we just need space for the NUL. */
|
||||
if (!__sfeof(fp) || expandtofit(linep, 1, linecapp))
|
||||
goto error;
|
||||
FUNLOCKFILE(fp);
|
||||
(*linep)[0] = '\0';
|
||||
return (-1);
|
||||
linelen = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
linelen = 0;
|
||||
@ -150,11 +150,12 @@ getdelim(char ** __restrict linep, size_t * __restrict linecapp, int delim,
|
||||
done:
|
||||
/* Invariant: *linep has space for at least linelen+1 bytes. */
|
||||
(*linep)[linelen] = '\0';
|
||||
FUNLOCKFILE(fp);
|
||||
end:
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (linelen);
|
||||
|
||||
error:
|
||||
fp->_flags |= __SERR;
|
||||
FUNLOCKFILE(fp);
|
||||
return (-1);
|
||||
linelen = -1;
|
||||
goto end;
|
||||
}
|
||||
|
@ -50,27 +50,30 @@ char *
|
||||
gets(char *buf)
|
||||
{
|
||||
int c;
|
||||
char *s;
|
||||
char *s, *ret;
|
||||
static int warned;
|
||||
static const char w[] =
|
||||
"warning: this program uses gets(), which is unsafe.\n";
|
||||
|
||||
FLOCKFILE(stdin);
|
||||
FLOCKFILE_CANCELSAFE(stdin);
|
||||
ORIENT(stdin, -1);
|
||||
if (!warned) {
|
||||
(void) _write(STDERR_FILENO, w, sizeof(w) - 1);
|
||||
warned = 1;
|
||||
}
|
||||
for (s = buf; (c = __sgetc(stdin)) != '\n';)
|
||||
for (s = buf; (c = __sgetc(stdin)) != '\n'; ) {
|
||||
if (c == EOF)
|
||||
if (s == buf) {
|
||||
FUNLOCKFILE(stdin);
|
||||
return (NULL);
|
||||
ret = NULL;
|
||||
goto end;
|
||||
} else
|
||||
break;
|
||||
else
|
||||
*s++ = c;
|
||||
}
|
||||
*s = 0;
|
||||
FUNLOCKFILE(stdin);
|
||||
return (buf);
|
||||
ret = buf;
|
||||
end:
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
}
|
||||
|
@ -38,6 +38,9 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _STDIO_LOCAL_H
|
||||
#define _STDIO_LOCAL_H
|
||||
|
||||
#include <sys/types.h> /* for off_t */
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
@ -138,3 +141,26 @@ __fgetwc(FILE *fp, locale_t locale)
|
||||
if ((fp)->_orientation == 0) \
|
||||
(fp)->_orientation = (o); \
|
||||
} while (0)
|
||||
|
||||
void __stdio_cancel_cleanup(void *);
|
||||
#define FLOCKFILE_CANCELSAFE(fp) \
|
||||
{ \
|
||||
struct _pthread_cleanup_info __cleanup_info__; \
|
||||
if (__isthreaded) { \
|
||||
_FLOCKFILE(fp); \
|
||||
__pthread_cleanup_push_imp( \
|
||||
__stdio_cancel_cleanup, (fp), \
|
||||
&__cleanup_info__); \
|
||||
} else { \
|
||||
__pthread_cleanup_push_imp( \
|
||||
__stdio_cancel_cleanup, NULL, \
|
||||
&__cleanup_info__); \
|
||||
} \
|
||||
{
|
||||
#define FUNLOCKFILE_CANCELSAFE() \
|
||||
(void)0; \
|
||||
} \
|
||||
__pthread_cleanup_pop_imp(1); \
|
||||
}
|
||||
|
||||
#endif /* _STDIO_LOCAL_H */
|
||||
|
@ -67,9 +67,9 @@ perror(const char *s)
|
||||
v++;
|
||||
v->iov_base = "\n";
|
||||
v->iov_len = 1;
|
||||
FLOCKFILE(stderr);
|
||||
FLOCKFILE_CANCELSAFE(stderr);
|
||||
__sflush(stderr);
|
||||
(void)_writev(stderr->_file, iov, (v - iov) + 1);
|
||||
stderr->_flags &= ~__SOFF;
|
||||
FUNLOCKFILE(stderr);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
}
|
||||
|
@ -49,11 +49,11 @@ int
|
||||
putc(int c, FILE *fp)
|
||||
{
|
||||
int retval;
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
/* Orientation set by __sputc() when buffer is full. */
|
||||
/* ORIENT(fp, -1); */
|
||||
retval = __sputc(c, fp);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (retval);
|
||||
}
|
||||
|
||||
|
@ -54,11 +54,11 @@ putchar(int c)
|
||||
int retval;
|
||||
FILE *so = stdout;
|
||||
|
||||
FLOCKFILE(so);
|
||||
FLOCKFILE_CANCELSAFE(so);
|
||||
/* Orientation set by __sputc() when buffer is full. */
|
||||
/* ORIENT(so, -1); */
|
||||
retval = __sputc(c, so);
|
||||
FUNLOCKFILE(so);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (retval);
|
||||
}
|
||||
|
||||
|
@ -62,9 +62,9 @@ puts(char const *s)
|
||||
uio.uio_resid = c + 1;
|
||||
uio.uio_iov = &iov[0];
|
||||
uio.uio_iovcnt = 2;
|
||||
FLOCKFILE(stdout);
|
||||
FLOCKFILE_CANCELSAFE(stdout);
|
||||
ORIENT(stdout, -1);
|
||||
retval = __sfvwrite(stdout, &uio) ? EOF : '\n';
|
||||
FUNLOCKFILE(stdout);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (retval);
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include "un-namespace.h"
|
||||
#include "fvwrite.h"
|
||||
#include "libc_private.h"
|
||||
#include "local.h"
|
||||
|
||||
int
|
||||
putw(int w, FILE *fp)
|
||||
@ -53,8 +54,8 @@ putw(int w, FILE *fp)
|
||||
uio.uio_resid = iov.iov_len = sizeof(w);
|
||||
uio.uio_iov = &iov;
|
||||
uio.uio_iovcnt = 1;
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
retval = __sfvwrite(fp, &uio);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (retval);
|
||||
}
|
||||
|
@ -53,9 +53,9 @@ lflush(FILE *fp)
|
||||
int ret = 0;
|
||||
|
||||
if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) {
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ret = __sflush(fp);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
@ -56,9 +56,9 @@ scanf(char const * __restrict fmt, ...)
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
FLOCKFILE(stdin);
|
||||
FLOCKFILE_CANCELSAFE(stdin);
|
||||
ret = __svfscanf(stdin, __get_locale(), fmt, ap);
|
||||
FUNLOCKFILE(stdin);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
va_end(ap);
|
||||
return (ret);
|
||||
}
|
||||
@ -70,9 +70,9 @@ scanf_l(locale_t locale, char const * __restrict fmt, ...)
|
||||
FIX_LOCALE(locale);
|
||||
|
||||
va_start(ap, fmt);
|
||||
FLOCKFILE(stdin);
|
||||
FLOCKFILE_CANCELSAFE(stdin);
|
||||
ret = __svfscanf(stdin, locale, fmt, ap);
|
||||
FUNLOCKFILE(stdin);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
va_end(ap);
|
||||
return (ret);
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ setvbuf(FILE * __restrict fp, char * __restrict buf, int mode, size_t size)
|
||||
if ((mode != _IOFBF && mode != _IOLBF) || (int)size < 0)
|
||||
return (EOF);
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
/*
|
||||
* Write current buffer, if any. Discard unread input (including
|
||||
* ungetc data), cancel line buffering, and free old buffer if
|
||||
@ -115,8 +115,7 @@ setvbuf(FILE * __restrict fp, char * __restrict buf, int mode, size_t size)
|
||||
fp->_w = 0;
|
||||
fp->_bf._base = fp->_p = fp->_nbuf;
|
||||
fp->_bf._size = 1;
|
||||
FUNLOCKFILE(fp);
|
||||
return (ret);
|
||||
goto end;
|
||||
}
|
||||
flags |= __SMBF;
|
||||
}
|
||||
@ -156,6 +155,7 @@ setvbuf(FILE * __restrict fp, char * __restrict buf, int mode, size_t size)
|
||||
}
|
||||
__cleanup = _cleanup;
|
||||
|
||||
FUNLOCKFILE(fp);
|
||||
end:
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
}
|
||||
|
@ -166,3 +166,11 @@ _sseek(FILE *fp, fpos_t offset, int whence)
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void
|
||||
__stdio_cancel_cleanup(void * arg)
|
||||
{
|
||||
|
||||
if (arg != NULL)
|
||||
_funlockfile((FILE *)arg);
|
||||
}
|
||||
|
@ -94,10 +94,10 @@ ungetc(int c, FILE *fp)
|
||||
|
||||
if (!__sdidinit)
|
||||
__sinit();
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ORIENT(fp, -1);
|
||||
ret = __ungetc(c, fp);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
@ -76,10 +76,10 @@ ungetwc_l(wint_t wc, FILE *fp, locale_t locale)
|
||||
wint_t r;
|
||||
FIX_LOCALE(locale);
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ORIENT(fp, 1);
|
||||
r = __ungetwc(wc, fp, locale);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
@ -274,14 +274,14 @@ vfprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt0,
|
||||
int ret;
|
||||
FIX_LOCALE(locale);
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
/* optimise fprintf(stderr) (and other unbuffered Unix files) */
|
||||
if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
|
||||
fp->_file >= 0)
|
||||
ret = __sbprintf(fp, locale, fmt0, ap);
|
||||
else
|
||||
ret = __vfprintf(fp, locale, fmt0, ap);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
}
|
||||
int
|
||||
|
@ -443,9 +443,9 @@ __vfscanf(FILE *fp, char const *fmt0, va_list ap)
|
||||
{
|
||||
int ret;
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ret = __svfscanf(fp, __get_locale(), fmt0, ap);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
}
|
||||
int
|
||||
@ -454,9 +454,9 @@ vfscanf_l(FILE *fp, locale_t locale, char const *fmt0, va_list ap)
|
||||
int ret;
|
||||
FIX_LOCALE(locale);
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ret = __svfscanf(fp, locale, fmt0, ap);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
@ -356,14 +356,14 @@ vfwprintf_l(FILE * __restrict fp, locale_t locale,
|
||||
{
|
||||
int ret;
|
||||
FIX_LOCALE(locale);
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
/* optimise fprintf(stderr) (and other unbuffered Unix files) */
|
||||
if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
|
||||
fp->_file >= 0)
|
||||
ret = __sbprintf(fp, locale, fmt0, ap);
|
||||
else
|
||||
ret = __vfwprintf(fp, locale, fmt0, ap);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
}
|
||||
int
|
||||
|
@ -428,10 +428,10 @@ vfwscanf_l(FILE * __restrict fp, locale_t locale,
|
||||
int ret;
|
||||
FIX_LOCALE(locale);
|
||||
|
||||
FLOCKFILE(fp);
|
||||
FLOCKFILE_CANCELSAFE(fp);
|
||||
ORIENT(fp, 1);
|
||||
ret = __vfwscanf(fp, locale, fmt, ap);
|
||||
FUNLOCKFILE(fp);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (ret);
|
||||
}
|
||||
int
|
||||
|
@ -54,9 +54,9 @@ vscanf_l(locale_t locale, const char * __restrict fmt, __va_list ap)
|
||||
int retval;
|
||||
FIX_LOCALE(locale);
|
||||
|
||||
FLOCKFILE(stdin);
|
||||
FLOCKFILE_CANCELSAFE(stdin);
|
||||
retval = __svfscanf(stdin, locale, fmt, ap);
|
||||
FUNLOCKFILE(stdin);
|
||||
FUNLOCKFILE_CANCELSAFE();
|
||||
return (retval);
|
||||
}
|
||||
int
|
||||
|
Loading…
Reference in New Issue
Block a user