2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A/* Copyright (c) 1988 AT&T */
2N/A/* All Rights Reserved */
2N/A
2N/A#pragma ident "%Z%%M% %I% %E% SMI"
2N/A
2N/A#include "lint.h"
2N/A#include "file64.h"
2N/A#include "mtlib.h"
2N/A#include <sys/types.h>
2N/A#include <stdio.h>
2N/A#include <values.h>
2N/A#include <memory.h>
2N/A#include <thread.h>
2N/A#include <synch.h>
2N/A#include <unistd.h>
2N/A#include "stdiom.h"
2N/A#include "mse.h"
2N/A
2N/Asize_t
2N/A_fwrite_unlocked(const void *ptr, size_t size, size_t count, FILE *iop);
2N/A
2N/Asize_t
2N/Afwrite(const void *ptr, size_t size, size_t count, FILE *iop)
2N/A{
2N/A rmutex_t *lk;
2N/A size_t retval;
2N/A
2N/A FLOCKFILE(lk, iop);
2N/A
2N/A _SET_ORIENTATION_BYTE(iop);
2N/A
2N/A retval = _fwrite_unlocked(ptr, size, count, iop);
2N/A FUNLOCKFILE(lk);
2N/A
2N/A return (retval);
2N/A}
2N/A
2N/Asize_t
2N/A_fwrite_unlocked(const void *ptr, size_t size, size_t count, FILE *iop)
2N/A{
2N/A ssize_t s, n;
2N/A unsigned char *dptr = (unsigned char *)ptr;
2N/A unsigned char *bufend;
2N/A
2N/A if (_WRTCHK(iop))
2N/A return (0);
2N/A
2N/A /*
2N/A * This test is here to avoid the expensive multiply
2N/A */
2N/A if (count == 1)
2N/A s = size;
2N/A else if (size == 1)
2N/A s = count;
2N/A else
2N/A s = size * count;
2N/A
2N/A if (iop->_flag & _IOLBF) {
2N/A bufend = _bufend(iop);
2N/A iop->_cnt = iop->_base - iop->_ptr;
2N/A while (s > 0) {
2N/A ssize_t buflen = bufend - iop->_base;
2N/A if (--iop->_cnt >= (-buflen) && *dptr != '\n')
2N/A *iop->_ptr++ = *dptr++;
2N/A else if (__flsbuf(*dptr++, iop) == EOF)
2N/A break;
2N/A s--;
2N/A }
2N/A } else if (iop->_flag & _IONBF) {
2N/A ssize_t bytes;
2N/A ssize_t written = 0;
2N/A char *data;
2N/A
2N/A if (size < 1 || count < 1)
2N/A return (0);
2N/A
2N/A if (iop->_base != iop->_ptr) {
2N/A /*
2N/A * Flush any existing data. Doesn't count towards return
2N/A * value.
2N/A */
2N/A bytes = iop->_ptr - iop->_base;
2N/A data = (char *)iop->_base;
2N/A
2N/A while ((n = write(fileno(iop), data, (size_t)bytes))
2N/A != bytes) {
2N/A if (n == -1) {
2N/A if (!cancel_active())
2N/A iop->_flag |= _IOERR;
2N/A return (0);
2N/A } else {
2N/A data += n;
2N/A bytes -= n;
2N/A }
2N/A }
2N/A iop->_cnt = 0;
2N/A iop->_ptr = iop->_base;
2N/A }
2N/A /*
2N/A * written is in bytes until the return.
2N/A * Then it is divided by size to produce items.
2N/A */
2N/A while ((n = write(fileno(iop), dptr, s)) != s) {
2N/A if (n == -1) {
2N/A if (!cancel_active())
2N/A iop->_flag |= _IOERR;
2N/A return (written / size);
2N/A } else {
2N/A dptr += n;
2N/A s -= n;
2N/A written += n;
2N/A }
2N/A }
2N/A written += n;
2N/A return (written / size);
2N/A } else while (s > 0) {
2N/A if (iop->_cnt < s) {
2N/A if (iop->_cnt > 0) {
2N/A (void) memcpy(iop->_ptr, (void *)dptr,
2N/A iop->_cnt);
2N/A dptr += iop->_cnt;
2N/A iop->_ptr += iop->_cnt;
2N/A s -= iop->_cnt;
2N/A }
2N/A if (_xflsbuf(iop) == EOF)
2N/A break;
2N/A }
2N/A if (iop->_cnt >= s) {
2N/A char *tmp = (char *)iop->_ptr;
2N/A
2N/A switch (s) {
2N/A case 8:
2N/A *tmp++ = *dptr++;
2N/A /*FALLTHRU*/
2N/A case 7:
2N/A *tmp++ = *dptr++;
2N/A /*FALLTHRU*/
2N/A case 6:
2N/A *tmp++ = *dptr++;
2N/A /*FALLTHRU*/
2N/A case 5:
2N/A *tmp++ = *dptr++;
2N/A /*FALLTHRU*/
2N/A case 4:
2N/A *tmp++ = *dptr++;
2N/A /*FALLTHRU*/
2N/A case 3:
2N/A *tmp++ = *dptr++;
2N/A /*FALLTHRU*/
2N/A case 2:
2N/A *tmp++ = *dptr++;
2N/A /*FALLTHRU*/
2N/A case 1:
2N/A *tmp++ = *dptr++;
2N/A break;
2N/A case 0:
2N/A return (count);
2N/A default:
2N/A (void) memcpy(iop->_ptr, (void *)dptr, s);
2N/A }
2N/A iop->_ptr += s;
2N/A iop->_cnt -= s;
2N/A
2N/A return (count);
2N/A }
2N/A }
2N/A
2N/A return (size != 0 ? count - ((s + size - 1) / size) : 0);
2N/A}