1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1988 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * Ptr args aren't checked for NULL because the program would be a 32 * catastrophic mess anyway. Better to abort than just to return NULL. 33 */ 34 #include "lint.h" 35 #include "file64.h" 36 #include "mtlib.h" 37 #include <stdio.h> 38 #include <string.h> 39 #include <thread.h> 40 #include <synch.h> 41 #include <sys/types.h> 42 #include <unistd.h> 43 #include <limits.h> 44 #include "stdiom.h" 45 #include "mse.h" 46 47 int 48 fputs(const char *ptr, FILE *iop) 49 { 50 ssize_t ndone = 0L, n; 51 unsigned char *cptr, *bufend; 52 rmutex_t *lk; 53 size_t ptrlen; 54 size_t len = 0; 55 int c; 56 57 FLOCKFILE(lk, iop); 58 59 _SET_ORIENTATION_BYTE(iop); 60 61 if (_WRTCHK(iop)) { 62 FUNLOCKFILE(lk); 63 return (EOF); 64 } 65 bufend = _bufend(iop); 66 67 ptrlen = strlen(ptr); 68 if ((iop->_flag & _IONBF) == 0) { 69 for (; ; ptr += len, ptrlen -= len) { 70 while ((n = bufend - (cptr = iop->_ptr)) <= 0) { 71 /* full buf */ 72 if (_xflsbuf(iop) == EOF) { 73 FUNLOCKFILE(lk); 74 return (EOF); 75 } 76 } 77 /* 78 * n: number of available bytes in the buffer of 'iop' 79 * ptrlen: number of remaining bytes in 'ptr' string 80 * 81 * If all remaining bytes in 'ptr' can be copied into 82 * the buffer of 'iop' (ptrlen <= n), 'len' is set to 83 * 'ptrlen'. Otherwise, 'len' is set to 'n'. 84 * Then, copies 'len' bytes from 'ptr' to the buffer 85 * of 'iop'. 86 */ 87 len = (c = (ptrlen <= n)) ? ptrlen : n; 88 (void) memcpy(cptr, ptr, len); 89 iop->_cnt -= len; 90 iop->_ptr += len; 91 if (_needsync(iop, bufend)) 92 _bufsync(iop, bufend); 93 ndone += len; 94 if (c) { 95 /* 96 * All bytes in 'ptr' have been copied into 97 * the buffer of 'iop'. 98 * Flush buffer if line-buffered 99 */ 100 if (iop->_flag & _IOLBF) 101 if (_xflsbuf(iop) == EOF) { 102 FUNLOCKFILE(lk); 103 return (EOF); 104 } 105 FUNLOCKFILE(lk); 106 if (ndone <= INT_MAX) 107 return ((int)ndone); 108 else 109 return (EOF); 110 } 111 } 112 } else { 113 /* write out to an unbuffered file */ 114 ssize_t num_wrote; 115 ssize_t count = (ssize_t)ptrlen; 116 117 while ((num_wrote = _xwrite(iop, ptr, (size_t)count)) != 118 count) { 119 if (num_wrote <= 0) { 120 if (!cancel_active()) 121 iop->_flag |= _IOERR; 122 FUNLOCKFILE(lk); 123 return (EOF); 124 } 125 count -= num_wrote; 126 ptr += num_wrote; 127 } 128 FUNLOCKFILE(lk); 129 if (ptrlen <= INT_MAX) 130 return ((int)ptrlen); 131 else 132 return (EOF); 133 } 134 } 135