summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc/port/stdio
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libc/port/stdio')
-rw-r--r--usr/src/lib/libc/port/stdio/_endopen.c46
-rw-r--r--usr/src/lib/libc/port/stdio/_filbuf.c14
-rw-r--r--usr/src/lib/libc/port/stdio/_findbuf.c14
-rw-r--r--usr/src/lib/libc/port/stdio/_flsbuf.c14
-rw-r--r--usr/src/lib/libc/port/stdio/fdopen.c34
-rw-r--r--usr/src/lib/libc/port/stdio/fileno.c7
-rw-r--r--usr/src/lib/libc/port/stdio/flush.c295
-rw-r--r--usr/src/lib/libc/port/stdio/fputs.c16
-rw-r--r--usr/src/lib/libc/port/stdio/popen.c44
-rw-r--r--usr/src/lib/libc/port/stdio/setbuf.c14
-rw-r--r--usr/src/lib/libc/port/stdio/setvbuf.c21
-rw-r--r--usr/src/lib/libc/port/stdio/vscanf.c14
-rw-r--r--usr/src/lib/libc/port/stdio/vwscanf.c11
13 files changed, 340 insertions, 204 deletions
diff --git a/usr/src/lib/libc/port/stdio/_endopen.c b/usr/src/lib/libc/port/stdio/_endopen.c
index a0236497a0..e58a779cc5 100644
--- a/usr/src/lib/libc/port/stdio/_endopen.c
+++ b/usr/src/lib/libc/port/stdio/_endopen.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -66,9 +65,8 @@
FILE *
_endopen(const char *name, const char *type, FILE *iop, int largefile)
{
- int oflag, fd;
+ int oflag, fd, fflag;
char plus;
- rmutex_t *lk;
if (iop == NULL)
return (NULL);
@@ -78,19 +76,24 @@ _endopen(const char *name, const char *type, FILE *iop, int largefile)
return (NULL);
case 'r':
oflag = O_RDONLY;
+ fflag = _IOREAD;
break;
case 'w':
oflag = O_WRONLY | O_TRUNC | O_CREAT;
+ fflag = _IOWRT;
break;
case 'a':
oflag = O_WRONLY | O_APPEND | O_CREAT;
+ fflag = _IOWRT;
break;
}
/* UNIX ignores 'b' and treats text and binary the same */
if ((plus = type[1]) == 'b')
plus = type[2];
- if (plus == '+')
+ if (plus == '+') {
oflag = (oflag & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
+ fflag = _IORW;
+ }
/* select small or large file open based on flag */
if (largefile) {
@@ -101,36 +104,21 @@ _endopen(const char *name, const char *type, FILE *iop, int largefile)
if (fd < 0)
return (NULL);
+ /* As long as we make sure _flag stays != 0, we don't need to lock */
#ifdef _LP64
iop->_file = fd;
+ iop->_flag = (iop->_flag & ~0377) | fflag;
#else
- if (fd > UCHAR_MAX) {
+ if (fd <= _FILE_FD_MAX) {
+ SET_FILE(iop, fd);
+ } else if (_file_set(iop, fd, type) != 0) {
+ /* errno set in _file_set() */
(void) close(fd);
- errno = EMFILE;
return (NULL);
}
- iop->_file = (unsigned char)fd; /* assume fits in unsigned char */
+ iop->_flag = fflag;
#endif /* _LP64 */
- FLOCKFILE(lk, iop); /* this lock may be unnecessary */
-
-#ifdef _LP64
- iop->_flag &= ~0377; /* clear lower 8-bits */
- if (plus == '+')
- iop->_flag |= _IORW;
- else if (type[0] == 'r')
- iop->_flag |= _IOREAD;
- else
- iop->_flag |= _IOWRT;
-#else
- if (plus == '+')
- iop->_flag = _IORW;
- else if (type[0] == 'r')
- iop->_flag = _IOREAD;
- else
- iop->_flag = _IOWRT;
-#endif /* _LP64 */
- FUNLOCKFILE(lk);
if (oflag == (O_WRONLY | O_APPEND | O_CREAT)) { /* type == "a" */
if (lseek64(fd, (off64_t)0, SEEK_END) < (off64_t)0) {
(void) close(fd);
diff --git a/usr/src/lib/libc/port/stdio/_filbuf.c b/usr/src/lib/libc/port/stdio/_filbuf.c
index 19605a7ef7..a1c4591e46 100644
--- a/usr/src/lib/libc/port/stdio/_filbuf.c
+++ b/usr/src/lib/libc/port/stdio/_filbuf.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,16 +18,17 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#pragma weak _filbuf = __filbuf
@@ -117,7 +117,7 @@ _filbuf(FILE *iop)
nbyte = 1;
else
nbyte = endbuf - iop->_base;
- if ((res = read(iop->_file, (char *)iop->_base, nbyte)) > 0) {
+ if ((res = read(GET_FD(iop), (char *)iop->_base, nbyte)) > 0) {
iop->_cnt = res - 1;
return (*iop->_ptr++);
}
diff --git a/usr/src/lib/libc/port/stdio/_findbuf.c b/usr/src/lib/libc/port/stdio/_findbuf.c
index d44b22817c..cbb323c3eb 100644
--- a/usr/src/lib/libc/port/stdio/_findbuf.c
+++ b/usr/src/lib/libc/port/stdio/_findbuf.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,16 +18,17 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#define _LARGEFILE64_SOURCE 1
@@ -51,7 +51,7 @@
Uchar *
_findbuf(FILE *iop)
{
- int fd = iop->_file;
+ int fd = GET_FD(iop);
Uchar *buf;
int size = BUFSIZ;
Uchar *endbuf;
diff --git a/usr/src/lib/libc/port/stdio/_flsbuf.c b/usr/src/lib/libc/port/stdio/_flsbuf.c
index ad4683a868..a3f6e9cf68 100644
--- a/usr/src/lib/libc/port/stdio/_flsbuf.c
+++ b/usr/src/lib/libc/port/stdio/_flsbuf.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,16 +18,17 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#pragma weak _flsbuf = __flsbuf
#include "synonyms.h"
@@ -71,7 +71,7 @@ _flsbuf(int ch, FILE *iop) /* flush (write) buffer, save ch, */
case _IONBF | _IOWRT: /* okay to do no-buffered case */
iop->_cnt = 0;
uch = (unsigned char)ch;
- if (write(iop->_file, (char *)&uch, 1) != 1)
+ if (write(GET_FD(iop), (char *)&uch, 1) != 1)
iop->_flag |= _IOERR;
goto out;
}
diff --git a/usr/src/lib/libc/port/stdio/fdopen.c b/usr/src/lib/libc/port/stdio/fdopen.c
index c0908f5f89..4865ec9a39 100644
--- a/usr/src/lib/libc/port/stdio/fdopen.c
+++ b/usr/src/lib/libc/port/stdio/fdopen.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -25,11 +24,10 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
+#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Unix routine to do an "fopen" on file descriptor
@@ -62,28 +60,14 @@ fdopen(int fd, const char *type) /* associate file desc. with stream */
char plus;
unsigned char flag;
-
/* Sets EBADF for bad fds */
if (fcntl(fd, F_GETFD) == -1)
return (NULL);
-#ifdef _LP64
if ((iop = _findiop()) == 0) {
errno = ENOMEM;
return (NULL);
}
- iop->_file = fd;
-#else
- if (fd > UCHAR_MAX) {
- errno = EMFILE;
- return (NULL);
- }
- if ((iop = _findiop()) == 0) {
- errno = ENOMEM;
- return (NULL);
- }
- iop->_file = (unsigned char)fd;
-#endif /* _LP64 */
switch (type[0]) {
default:
@@ -106,5 +90,17 @@ fdopen(int fd, const char *type) /* associate file desc. with stream */
flag = _IORW;
iop->_flag = flag;
+#ifdef _LP64
+ iop->_file = fd;
+#else
+ if (fd <= _FILE_FD_MAX) {
+ SET_FILE(iop, fd);
+ } else if (_file_set(iop, fd, type) != 0) {
+ /* errno set by _file_set () */
+ iop->_flag = 0; /* release iop */
+ return (NULL);
+ }
+#endif /* _LP64 */
+
return (iop);
}
diff --git a/usr/src/lib/libc/port/stdio/fileno.c b/usr/src/lib/libc/port/stdio/fileno.c
index 21fc215eba..643ee4cb01 100644
--- a/usr/src/lib/libc/port/stdio/fileno.c
+++ b/usr/src/lib/libc/port/stdio/fileno.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -44,5 +43,5 @@
int
_fileno(FILE *iop)
{
- return (iop->_file);
+ return (GET_FD(iop));
}
diff --git a/usr/src/lib/libc/port/stdio/flush.c b/usr/src/lib/libc/port/stdio/flush.c
index e0bdb699cd..02cb43249e 100644
--- a/usr/src/lib/libc/port/stdio/flush.c
+++ b/usr/src/lib/libc/port/stdio/flush.c
@@ -33,6 +33,7 @@
#include "synonyms.h"
#include "mtlib.h"
#include "file64.h"
+#include "../gen/_libc_gettext.h"
#define _iob __iob
@@ -48,6 +49,7 @@
#include <sys/stat.h>
#include <stddef.h>
#include <errno.h>
+#include <fcntl.h>
#undef end
@@ -63,6 +65,8 @@
#define FPDECL(fp) FILE *fp
#define FIRSTFP(lp, fp) fp = lp->iobp
#define NEXTFP(fp) fp++
+#define FPLOCK(fp) &fp->_lock
+#define FPSTATE(fp) &fp->_state
#define xFILE FILE
@@ -72,6 +76,10 @@
#define FIRSTFP(lp, fp) x##fp = lp->iobp; \
fp = x##fp ? &x##fp->_iob : &_iob[0]
#define NEXTFP(fp) (x##fp ? fp = &(++x##fp)->_iob : ++fp)
+#define FPLOCK(fp) x##fp ? \
+ &x##fp->xlock : &_xftab[IOPIND(fp)]._lock
+#define FPSTATE(fp) x##fp ? \
+ &x##fp->xstate : &_xftab[IOPIND(fp)]._state
/* The extended 32-bit file structure for use in link buffers */
typedef struct xFILE {
@@ -135,19 +143,11 @@ static struct _link_ *lastlink = NULL;
static int fcloses;
static int nchunks;
-static rwlock_t _first_link_lock = DEFAULTRWLOCK;
+static mutex_t _first_link_lock = DEFAULTMUTEX;
-static int _fflush_u_iops(void);
+static int _fflush_l_iops(void);
static FILE *getiop(FILE *, rmutex_t *, mbstate_t *);
-#define GETIOP(fp, lk, mb) {FILE *ret; \
- if ((ret = getiop((fp), __libc_threaded? (lk): NULL, (mb))) != NULL) { \
- if (__libc_threaded) \
- (void) __rw_unlock(&_first_link_lock); \
- return (ret); \
- }; \
- }
-
/*
* All functions that understand the linked list of iob's follow.
*/
@@ -164,7 +164,7 @@ __cleanup(void) /* called at process end to flush ouput streams */
void
stdio_locks()
{
- (void) __rw_wrlock(&_first_link_lock);
+ (void) __mutex_lock(&_first_link_lock);
/*
* XXX: We should acquire all of the iob locks here.
*/
@@ -176,7 +176,7 @@ stdio_unlocks()
/*
* XXX: We should release all of the iob locks here.
*/
- (void) __rw_unlock(&_first_link_lock);
+ (void) __mutex_unlock(&_first_link_lock);
}
void
@@ -185,22 +185,43 @@ _flushlbf(void) /* fflush() all line-buffered streams */
FPDECL(fp);
int i;
struct _link_ *lp;
+ /* Allow compiler to optimize the loop */
+ int threaded = __libc_threaded;
- if (__libc_threaded)
- (void) __rw_rdlock(&_first_link_lock);
+ if (threaded)
+ (void) __mutex_lock(&_first_link_lock);
lp = &__first_link;
do {
FIRSTFP(lp, fp);
for (i = lp->niob; --i >= 0; NEXTFP(fp)) {
- if ((fp->_flag & (_IOLBF | _IOWRT)) ==
- (_IOLBF | _IOWRT))
- (void) _fflush_u(fp);
+ /*
+ * The additional _IONBF check guards againsts
+ * allocated but uninitialized iops (see _findiop).
+ * We also automatically skip non allocated iop's.
+ * Don't block on locks.
+ */
+ if ((fp->_flag & (_IOLBF | _IOWRT | _IONBF)) ==
+ (_IOLBF | _IOWRT)) {
+ if (threaded) {
+ rmutex_t *lk = FPLOCK(fp);
+ if (rmutex_trylock(lk) != 0)
+ continue;
+ /* Recheck after locking */
+ if ((fp->_flag & (_IOLBF | _IOWRT)) ==
+ (_IOLBF | _IOWRT)) {
+ (void) _fflush_u(fp);
+ }
+ (void) rmutex_unlock(lk);
+ } else {
+ (void) _fflush_u(fp);
+ }
+ }
}
} while ((lp = lp->next) != NULL);
- if (__libc_threaded)
- (void) __rw_unlock(&_first_link_lock);
+ if (threaded)
+ (void) __mutex_unlock(&_first_link_lock);
}
/* allocate an unused stream; NULL if cannot */
@@ -232,9 +253,10 @@ _findiop(void)
struct _link_ *hdr;
FPDECL(fp);
int i;
+ int threaded = __libc_threaded;
- if (__libc_threaded)
- (void) __rw_wrlock(&_first_link_lock);
+ if (threaded)
+ (void) __mutex_lock(&_first_link_lock);
if (lastlink == NULL) {
rescan:
@@ -258,13 +280,18 @@ rescan:
FIRSTFP(lp, fp);
for (i = lp->niob; --i >= 0; NEXTFP(fp)) {
-#ifdef _LP64
- GETIOP(fp, &fp->_lock, &fp->_state);
-#else
- GETIOP(fp,
- xfp ? &xfp->xlock : &_xftab[IOPIND(fp)]._lock,
- xfp ? &xfp->xstate : &_xftab[IOPIND(fp)]._state);
-#endif /* _LP64 */
+ FILE *ret;
+ if (threaded) {
+ ret = getiop(fp, FPLOCK(fp), FPSTATE(fp));
+ if (ret != NULL) {
+ (void) __mutex_unlock(&_first_link_lock);
+ return (ret);
+ }
+ } else {
+ ret = getiop(fp, NULL, FPSTATE(fp));
+ if (ret != NULL)
+ return (ret);
+ }
}
} while ((lastlink = lp = lp->next) != NULL);
@@ -288,8 +315,8 @@ rescan:
* Need to allocate another and put it in the linked list.
*/
if ((pkgp = malloc(sizeof (Pkg))) == NULL) {
- if (__libc_threaded)
- (void) __rw_unlock(&_first_link_lock);
+ if (threaded)
+ (void) __mutex_unlock(&_first_link_lock);
return (NULL);
}
@@ -355,8 +382,8 @@ rescan:
fp->_ptr = 0;
fp->_base = 0;
fp->_flag = 0377; /* claim the fp by setting low 8 bits */
- if (__libc_threaded)
- (void) __rw_unlock(&_first_link_lock);
+ if (threaded)
+ (void) __mutex_unlock(&_first_link_lock);
return (fp);
}
@@ -369,7 +396,7 @@ isseekable(FILE *iop)
save_errno = errno;
- if (fstat64(iop->_file, &fstatbuf) != 0) {
+ if (fstat64(GET_FD(iop), &fstatbuf) != 0) {
/*
* when we don't know what it is we'll
* do the old behaviour and flush
@@ -452,8 +479,8 @@ _setbufend(FILE *iop, Uchar *end) /* set the end pointer for this iop */
* old _bufend macro. This is *so* broken, fileno()
* is not the proper index.
*/
- if (iop->_file < _NFILE)
- _bufendtab[iop->_file] = end;
+ if (iop->_magic < _NFILE)
+ _bufendtab[iop->_magic] = end;
}
@@ -523,8 +550,9 @@ _xflsbuf(FILE *iop)
_bufsync(iop, bufend);
if (n > 0) {
+ int fd = GET_FD(iop);
while ((num_wrote =
- write(iop->_file, base, (size_t)n)) != n) {
+ write(fd, base, (size_t)n)) != n) {
if (num_wrote <= 0) {
iop->_flag |= _IOERR;
return (EOF);
@@ -548,56 +576,86 @@ fflush(FILE *iop)
res = _fflush_u(iop);
FUNLOCKFILE(lk);
} else {
- res = _fflush_u_iops(); /* flush all iops */
+ res = _fflush_l_iops(); /* flush all iops */
}
return (res);
}
static int
-_fflush_u_iops(void) /* flush all buffers */
+_fflush_l_iops(void) /* flush all buffers */
{
FPDECL(iop);
int i;
struct _link_ *lp;
int res = 0;
+ rmutex_t *lk;
+ /* Allow the compiler to optimize the load out of the loop */
+ int threaded = __libc_threaded;
- if (__libc_threaded)
- (void) __rw_rdlock(&_first_link_lock);
+ if (threaded)
+ (void) __mutex_lock(&_first_link_lock);
lp = &__first_link;
do {
/*
- * Don't grab the locks for these file pointers
- * since they are supposed to be flushed anyway
- * It could also be the case in which the 2nd
- * portion (base and lock) are not initialized
+ * We need to grab the file locks or file corruption
+ * will happen. But we first check the flags field
+ * knowing that when it is 0, it isn't allocated and
+ * cannot be allocated while we're holding the
+ * _first_link_lock. And when _IONBF is set (also the
+ * case when _flag is 0377, or alloc in progress), we
+ * also ignore it.
+ *
+ * Ignore locked streams; it will appear as if
+ * concurrent updates happened after fflush(NULL). Note
+ * that we even attempt to lock if the locking is set to
+ * "by caller". We don't want to penalize callers of
+ * __fsetlocking() by not flushing their files. Note: if
+ * __fsetlocking() callers don't employ any locking, they
+ * may still face corruption in fflush(NULL); but that's
+ * no change from earlier releases.
*/
FIRSTFP(lp, iop);
for (i = lp->niob; --i >= 0; NEXTFP(iop)) {
- if (!(iop->_flag & _IONBF)) {
- /*
- * don't need to worry about the _IORW case
- * since the iop will also marked with _IOREAD
- * or _IOWRT whichever we are really doing
- */
- if (iop->_flag & _IOWRT) { /* flush write buffers */
- res |= _fflush_u(iop);
- } else if (iop->_flag & _IOREAD) {
+ unsigned int flag = iop->_flag;
+
+ /* flag 0, flag 0377, or _IONBF set */
+ if (flag == 0 || (flag & _IONBF) != 0)
+ continue;
+
+ if (threaded) {
+ lk = FPLOCK(iop);
+ if (rmutex_trylock(lk) != 0)
+ continue;
+ }
+
+ if (!(iop->_flag & _IONBF)) {
/*
- * flush seekable read buffers
- * don't flush non-seekable read buffers
+ * don't need to worry about the _IORW case
+ * since the iop will also marked with _IOREAD
+ * or _IOWRT whichever we are really doing
*/
- if (GET_SEEKABLE(iop)) {
- res |= _fflush_u(iop);
- }
+ if (iop->_flag & _IOWRT) {
+ /* Flush write buffers */
+ res |= _fflush_u(iop);
+ } else if (iop->_flag & _IOREAD) {
+ /*
+ * flush seekable read buffers
+ * don't flush non-seekable read buffers
+ */
+ if (GET_SEEKABLE(iop)) {
+ res |= _fflush_u(iop);
+ }
+ }
}
- }
+ if (threaded)
+ (void) rmutex_unlock(lk);
}
} while ((lp = lp->next) != NULL);
- if (__libc_threaded)
- (void) __rw_unlock(&_first_link_lock);
+ if (threaded)
+ (void) __mutex_unlock(&_first_link_lock);
return (res);
}
@@ -609,7 +667,7 @@ _fflush_u(FILE *iop)
/* this portion is always assumed locked */
if (!(iop->_flag & _IOWRT)) {
- (void) lseek64(iop->_file, -iop->_cnt, SEEK_CUR);
+ (void) lseek64(GET_FD(iop), -iop->_cnt, SEEK_CUR);
iop->_cnt = 0;
/* needed for ungetc & multibyte pushbacks */
iop->_ptr = iop->_base;
@@ -647,7 +705,7 @@ fclose(FILE *iop)
/* Is not unbuffered and opened for read and/or write ? */
if (!(iop->_flag & _IONBF) && (iop->_flag & (_IOWRT | _IOREAD | _IORW)))
res = _fflush_u(iop);
- if (close(iop->_file) < 0)
+ if (close(GET_FD(iop)) < 0)
res = EOF;
if (iop->_flag & _IOMYBUF) {
(void) free((char *)iop->_base - PUSHBACK);
@@ -659,10 +717,10 @@ fclose(FILE *iop)
FUNLOCKFILE(lk);
if (__libc_threaded)
- (void) __rw_wrlock(&_first_link_lock);
+ (void) __mutex_lock(&_first_link_lock);
fcloses++;
if (__libc_threaded)
- (void) __rw_unlock(&_first_link_lock);
+ (void) __mutex_unlock(&_first_link_lock);
return (res);
}
@@ -679,7 +737,7 @@ close_fd(FILE *iop)
/* Is not unbuffered and opened for read and/or write ? */
if (!(iop->_flag & _IONBF) && (iop->_flag & (_IOWRT | _IOREAD | _IORW)))
res = _fflush_u(iop);
- if (close(iop->_file) < 0)
+ if (close(GET_FD(iop)) < 0)
res = EOF;
if (iop->_flag & _IOMYBUF) {
(void) free((char *)iop->_base - PUSHBACK);
@@ -736,4 +794,109 @@ _getmbstate(FILE *iop)
return (NULL);
}
+
+/*
+ * More 32-bit only functions.
+ * They lookup/set large fd's for extended FILE support.
+ */
+
+/*
+ * The negative value indicates that Extended fd FILE's has not
+ * been enabled by the user.
+ */
+static int bad_fd = -1;
+
+int
+_file_get(FILE *iop)
+{
+ int altfd;
+
+ /*
+ * Failure indicates a FILE * not allocated through stdio;
+ * it means the flag values are probably bogus and that if
+ * a file descriptor is set, it's in _magic.
+ * Inline getxfdat() for performance reasons.
+ */
+ if (STDIOP(iop))
+ altfd = _xftab[IOPIND(iop)]._altfd;
+ else if (VALIDXFILE(FILEx(iop)))
+ altfd = FILEx(iop)->_xdat._altfd;
+ else
+ return (iop->_magic);
+ /*
+ * if this is not an internal extended FILE then check
+ * if _file is being changed from underneath us.
+ * It should not be because if
+ * it is then then we lose our ability to guard against
+ * silent data corruption.
+ */
+ if (!iop->__xf_nocheck && bad_fd > -1 && iop->_magic != bad_fd) {
+ /* LINTED: variable format specifier */
+ (void) fprintf(stderr, _libc_gettext(
+ "Application violated extended FILE safety mechanism.\n"
+ "Please read the man page for extendedFILE.\nAborting\n"));
+ abort();
+ }
+ return (altfd);
+}
+
+int
+_file_set(FILE *iop, int fd, const char *type)
+{
+ struct xFILEdata *dat;
+ int Fflag;
+
+ /* Already known to contain at least one byte */
+ while (*++type != '\0')
+ ;
+
+ Fflag = type[-1] == 'F';
+ if (!Fflag && bad_fd < 0) {
+ errno = EMFILE;
+ return (-1);
+ }
+
+ dat = getxfdat(iop);
+ iop->__extendedfd = 1;
+ iop->__xf_nocheck = Fflag;
+ dat->_altfd = fd;
+ iop->_magic = (unsigned char)bad_fd;
+ return (0);
+}
+
+/*
+ * Activates extended fd's in FILE's
+ */
+
+static const int tries[] = {196, 120, 60, 3};
+#define NTRIES (sizeof (tries)/sizeof (int))
+
+int
+enable_extended_FILE_stdio(int fd, int action)
+{
+ int i;
+
+ if (action < 0)
+ action = SIGABRT; /* default signal */
+
+ if (fd < 0) {
+ /*
+ * search for an available fd and make it the badfd
+ */
+ for (i = 0; i < NTRIES; i++) {
+ fd = fcntl(tries[i], F_BADFD, action);
+ if (fd >= 0)
+ break;
+ }
+ if (fd < 0) /* failed to find an available fd */
+ return (-1);
+ } else {
+ /* caller requests that fd be the chosen badfd */
+ int nfd = fcntl(fd, F_BADFD, action);
+ if (nfd < 0 || nfd != fd)
+ return (-1);
+ }
+ bad_fd = fd;
+ return (0);
+}
#endif
diff --git a/usr/src/lib/libc/port/stdio/fputs.c b/usr/src/lib/libc/port/stdio/fputs.c
index 58da9af2bc..1ab3c57be5 100644
--- a/usr/src/lib/libc/port/stdio/fputs.c
+++ b/usr/src/lib/libc/port/stdio/fputs.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,16 +18,17 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
/*
* Ptr args aren't checked for NULL because the program would be a
@@ -118,9 +118,9 @@ fputs(const char *ptr, FILE *iop)
/* write out to an unbuffered file */
ssize_t num_wrote;
ssize_t count = (ssize_t)ptrlen;
+ int fd = GET_FD(iop);
- while ((num_wrote = write(iop->_file, ptr,
- (size_t)count)) != count) {
+ while ((num_wrote = write(fd, ptr, (size_t)count)) != count) {
if (num_wrote <= 0) {
iop->_flag |= _IOERR;
FUNLOCKFILE(lk);
diff --git a/usr/src/lib/libc/port/stdio/popen.c b/usr/src/lib/libc/port/stdio/popen.c
index c181f8abd8..6168a8c13b 100644
--- a/usr/src/lib/libc/port/stdio/popen.c
+++ b/usr/src/lib/libc/port/stdio/popen.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,16 +18,17 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#pragma weak pclose = _pclose
#pragma weak popen = _popen
@@ -55,10 +55,6 @@
#define RDR 0
#define WTR 1
-#ifndef _LP64
-#define MAX_FD (1 << (NBBY * (unsigned)sizeof (_lastbuf->_file))) /* now 256 */
-#endif /* _LP64 */
-
static int _insert_nolock(pid_t, int);
extern int __xpg4; /* defined in _xpg4.c; 0 if not xpg4-compiled program */
@@ -96,16 +92,6 @@ popen(const char *cmd, const char *mode)
if (pipe(p) < 0)
return (NULL);
-#ifndef _LP64
- /* check that the fd's are in range for a struct FILE */
- if ((p[WTR] >= MAX_FD) || (p[RDR] >= MAX_FD)) {
- (void) close(p[WTR]);
- (void) close(p[RDR]);
- errno = EMFILE;
- return (NULL);
- }
-#endif /* _LP64 */
-
shpath = __xpg4? xpg4_path : sun_path;
if (access(shpath, X_OK)) /* XPG4 Requirement: */
shpath = ""; /* force child to fail immediately */
@@ -115,12 +101,19 @@ popen(const char *cmd, const char *mode)
/* myside and yourside reverse roles in child */
stdio = tst(0, 1);
+ /* This will fail more quickly if we run out of fds */
+ if ((iop = fdopen(myside, mode)) == NULL) {
+ (void) close(yourside);
+ (void) close(myside);
+ return (NULL);
+ }
+
lmutex_lock(&popen_lock);
/* in the child, close all pipes from other popen's */
if ((error = posix_spawn_file_actions_init(&fact)) != 0) {
lmutex_unlock(&popen_lock);
- (void) close(myside);
+ (void) fclose(iop);
(void) close(yourside);
errno = error;
return (NULL);
@@ -140,7 +133,7 @@ popen(const char *cmd, const char *mode)
if (error) {
lmutex_unlock(&popen_lock);
(void) posix_spawn_file_actions_destroy(&fact);
- (void) close(myside);
+ (void) fclose(iop);
(void) close(yourside);
errno = error;
return (NULL);
@@ -156,17 +149,12 @@ popen(const char *cmd, const char *mode)
(void) close(yourside);
if ((errno = error) != 0 || _insert_nolock(pid, myside) == -1) {
lmutex_unlock(&popen_lock);
- (void) close(myside);
+ (void) fclose(iop);
return (NULL);
}
lmutex_unlock(&popen_lock);
- if ((iop = fdopen(myside, mode)) == NULL) {
- (void) _delete(myside);
- (void) close(myside);
- return (NULL);
- }
_SET_ORIENTATION_BYTE(iop);
return (iop);
diff --git a/usr/src/lib/libc/port/stdio/setbuf.c b/usr/src/lib/libc/port/stdio/setbuf.c
index 7c96d0feb7..efd2bea743 100644
--- a/usr/src/lib/libc/port/stdio/setbuf.c
+++ b/usr/src/lib/libc/port/stdio/setbuf.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,16 +18,17 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#include "synonyms.h"
#include "file64.h"
@@ -45,7 +45,7 @@ void
setbuf(FILE *iop, char *abuf)
{
Uchar *buf = (Uchar *)abuf;
- int fno = iop->_file; /* file number */
+ int fno = GET_FD(iop); /* file number */
int size = BUFSIZ - _SMBFSZ;
Uchar *temp;
rmutex_t *lk;
diff --git a/usr/src/lib/libc/port/stdio/setvbuf.c b/usr/src/lib/libc/port/stdio/setvbuf.c
index 7a7b3957e2..40a075637f 100644
--- a/usr/src/lib/libc/port/stdio/setvbuf.c
+++ b/usr/src/lib/libc/port/stdio/setvbuf.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,16 +18,17 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#include "synonyms.h"
#include "file64.h"
@@ -48,6 +48,7 @@ setvbuf(FILE *iop, char *abuf, int type, size_t size)
Uchar *temp;
int sflag = iop->_flag & _IOMYBUF;
rmutex_t *lk;
+ int fd = GET_FD(iop);
FLOCKFILE(lk, iop);
iop->_flag &= ~(_IOMYBUF | _IONBF | _IOLBF);
@@ -56,14 +57,14 @@ setvbuf(FILE *iop, char *abuf, int type, size_t size)
case _IONBF:
iop->_flag |= _IONBF; /* file is unbuffered */
#ifndef _STDIO_ALLOCATE
- if (iop->_file < 2) {
+ if (fd < 2) {
/* use special buffer for std{in,out} */
- buf = (iop->_file == 0) ? _sibuf : _sobuf;
+ buf = (fd == 0) ? _sibuf : _sobuf;
size = BUFSIZ;
} else /* needed for ifdef */
#endif
- if (iop->_file < _NFILE) {
- buf = _smbuf[iop->_file];
+ if (fd < _NFILE) {
+ buf = _smbuf[fd];
size = _SMBFSZ - PUSHBACK;
} else
if ((buf = malloc(_SMBFSZ * sizeof (Uchar))) != NULL) {
diff --git a/usr/src/lib/libc/port/stdio/vscanf.c b/usr/src/lib/libc/port/stdio/vscanf.c
index 986feae37a..1ca2e8db2d 100644
--- a/usr/src/lib/libc/port/stdio/vscanf.c
+++ b/usr/src/lib/libc/port/stdio/vscanf.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,16 +18,17 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */
+#pragma ident "%Z%%M% %I% %E% SMI"
+
#ifndef _C89_INTMAX32
#pragma weak vscanf = _vscanf
@@ -125,7 +125,7 @@ vsscanf(const char *str, const char *fmt, va_list ap)
strbuf._flag = _IOREAD | _IOWRT;
strbuf._ptr = strbuf._base = (unsigned char *)str;
strbuf._cnt = strlen(str);
- strbuf._file = _NFILE;
+ SET_FILE(&strbuf, _NFILE);
/*
* Mark the stream so that routines called by __doscan_u()
diff --git a/usr/src/lib/libc/port/stdio/vwscanf.c b/usr/src/lib/libc/port/stdio/vwscanf.c
index 40f21ada91..684163a496 100644
--- a/usr/src/lib/libc/port/stdio/vwscanf.c
+++ b/usr/src/lib/libc/port/stdio/vwscanf.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,8 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -132,7 +132,8 @@ vswscanf(const wchar_t *wstr, const wchar_t *fmt, va_list ap)
strbuf._flag = _IOREAD | _IOWRT;
strbuf._ptr = strbuf._base = (unsigned char *)tmp_buf;
strbuf._cnt = strlen(tmp_buf);
- strbuf._file = _NFILE;
+ SET_FILE(&strbuf, _NFILE);
+
/* Probably the following is not required. */
/* _setorientation(&strbuf, _WC_MODE); */