wchar_t * __fgetws_chk (wchar_t *buf, size_t size, int n, _IO_FILE *fp) { _IO_size_t count; wchar_t *result; int old_error; CHECK_FILE (fp, NULL); if (n <= 0) return NULL; _IO_acquire_lock (fp); /* This is very tricky since a file descriptor may be in the non-blocking mode. The error flag doesn't mean much in this case. We return an error only when there is a new error. */ old_error = fp->_IO_file_flags & _IO_ERR_SEEN; fp->_IO_file_flags &= ~_IO_ERR_SEEN; count = _IO_getwline (fp, buf, MIN ((size_t) n - 1, size), L'\n', 1); /* If we read in some bytes and errno is EAGAIN, that error will be reported for next read. */ if (count == 0 || (_IO_ferror_unlocked (fp) && errno != EAGAIN)) result = NULL; else if (count >= size) __chk_fail (); else { buf[count] = '\0'; result = buf; } fp->_IO_file_flags |= old_error; _IO_release_lock (fp); return result; }
/* Print a line on stderr consisting of the text in S, a colon, a space, a message describing the meaning of the contents of `errno' and a newline. If S is NULL or "", the colon and space are omitted. */ void perror (const char *s) { int errnum = errno; FILE *fp; int fd = -1; /* The standard says that 'perror' must not change the orientation of the stream. What is supposed to happen when the stream isn't oriented yet? In this case we'll create a new stream which is using the same underlying file descriptor. */ if (__builtin_expect (_IO_fwide (stderr, 0) != 0, 1) || (fd = fileno (stderr)) == -1 || (fd = __dup (fd)) == -1 || (fp = fdopen (fd, "w+")) == NULL) { if (__glibc_unlikely (fd != -1)) __close (fd); /* Use standard error as is. */ perror_internal (stderr, s, errnum); } else { /* We don't have to do any special hacks regarding the file position. Since the stderr stream wasn't used so far we just write to the descriptor. */ perror_internal (fp, s, errnum); if (_IO_ferror_unlocked (fp)) stderr->_flags |= _IO_ERR_SEEN; /* Close the stream. */ fclose (fp); } }
wchar_t * fgetws (wchar_t *buf, int n, _IO_FILE *fp) { _IO_size_t count; wchar_t *result; int old_error; CHECK_FILE (fp, NULL); if (n <= 0) return NULL; if (__glibc_unlikely (n == 1)) { /* Another irregular case: since we have to store a NUL byte and there is only room for exactly one byte, we don't have to read anything. */ buf[0] = L'\0'; return buf; } _IO_acquire_lock (fp); /* This is very tricky since a file descriptor may be in the non-blocking mode. The error flag doesn't mean much in this case. We return an error only when there is a new error. */ old_error = fp->_IO_file_flags & _IO_ERR_SEEN; fp->_IO_file_flags &= ~_IO_ERR_SEEN; count = _IO_getwline (fp, buf, n - 1, L'\n', 1); /* If we read in some bytes and errno is EAGAIN, that error will be reported for next read. */ if (count == 0 || (_IO_ferror_unlocked (fp) && errno != EAGAIN)) result = NULL; else { buf[count] = '\0'; result = buf; } fp->_IO_file_flags |= old_error; _IO_release_lock (fp); return result; }
int __ferror_unlocked (FILE *fp) { CHECK_FILE (fp, EOF); return _IO_ferror_unlocked (fp); }
_IO_ssize_t _IO_getdelim(char **lineptr, _IO_size_t *n, int delimiter, _IO_FILE *fp) { _IO_ssize_t result; _IO_ssize_t cur_len = 0; _IO_ssize_t len; if (lineptr == NULL || n == NULL) { MAYBE_SET_EINVAL; return -1; } CHECK_FILE (fp, -1); _IO_acquire_lock(fp); if (_IO_ferror_unlocked(fp)) { result = -1; goto unlock_return; } if (*lineptr == NULL || *n == 0) { *n = 120; *lineptr = (char *) malloc(*n); if (*lineptr == NULL) { result = -1; goto unlock_return; } } len = fp->_IO_read_end - fp->_IO_read_ptr; if (len <= 0) { if (__underflow(fp) == EOF) { result = -1; goto unlock_return; } len = fp->_IO_read_end - fp->_IO_read_ptr; } for (;;) { _IO_size_t needed; char *t; t = (char *) memchr((void *) fp->_IO_read_ptr, delimiter, len); if (t != NULL) len = (t - fp->_IO_read_ptr) + 1; if (__glibc_unlikely(len >= SSIZE_MAX - cur_len)) { __set_errno(EOVERFLOW); result = -1; goto unlock_return; } /* Make enough space for len+1 (for final NUL) bytes. */ needed = cur_len + len + 1; if (needed > *n) { char *new_lineptr; if (needed < 2 * *n) needed = 2 * *n; /* Be generous. */ new_lineptr = (char *) realloc(*lineptr, needed); if (new_lineptr == NULL) { result = -1; goto unlock_return; } *lineptr = new_lineptr; *n = needed; } memcpy(*lineptr + cur_len, (void *) fp->_IO_read_ptr, len); fp->_IO_read_ptr += len; cur_len += len; if (t != NULL || __underflow(fp) == EOF) break; len = fp->_IO_read_end - fp->_IO_read_ptr; } (*lineptr)[cur_len] = '\0'; result = cur_len; unlock_return: _IO_release_lock(fp); return result; }