xref: /illumos-gate/usr/src/lib/libc/port/stdio/_endopen.c (revision 571575105382b90dc07db52b51d687862849dd05)
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  #pragma ident	"%Z%%M%	%I%	%E% SMI"
31  
32  /*
33   *	This routine is a special case, in that it is aware of
34   *	both small and large file interfaces. It must be built
35   *	in the small compilation environment.
36   */
37  
38  #include "lint.h"
39  #include "file64.h"
40  #include <mtlib.h>
41  #include <sys/types.h>
42  #include <stdio.h>
43  #include <fcntl.h>
44  #include <unistd.h>
45  #include <limits.h>
46  #include <thread.h>
47  #include <synch.h>
48  #include "stdiom.h"
49  #include <errno.h>
50  
51  /*
52   * open UNIX file name, associate with iop
53   */
54  
55  FILE *
56  _endopen(const char *name, const char *type, FILE *iop, int largefile)
57  {
58  	int oflag, fd, fflag;
59  	char plus;
60  
61  	if (iop == NULL)
62  		return (NULL);
63  	switch (type[0]) {
64  	default:
65  		errno = EINVAL;
66  		return (NULL);
67  	case 'r':
68  		oflag = O_RDONLY;
69  		fflag = _IOREAD;
70  		break;
71  	case 'w':
72  		oflag = O_WRONLY | O_TRUNC | O_CREAT;
73  		fflag = _IOWRT;
74  		break;
75  	case 'a':
76  		oflag = O_WRONLY | O_APPEND | O_CREAT;
77  		fflag = _IOWRT;
78  		break;
79  	}
80  	/* UNIX ignores 'b' and treats text and binary the same */
81  	if ((plus = type[1]) == 'b')
82  		plus = type[2];
83  	if (plus == '+') {
84  		oflag = (oflag & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
85  		fflag = _IORW;
86  	}
87  
88  	/* select small or large file open based on flag */
89  	if (largefile) {
90  		fd = open64(name, oflag, 0666);
91  	} else {
92  		fd = open(name, oflag, 0666);
93  	}
94  	if (fd < 0)
95  		return (NULL);
96  
97  	/* As long as we make sure _flag stays != 0, we don't need to lock */
98  #ifdef	_LP64
99  	iop->_file = fd;
100  	iop->_flag = (iop->_flag & ~0377) | fflag;
101  #else
102  	if (fd <= _FILE_FD_MAX) {
103  		SET_FILE(iop, fd);
104  	} else if (_file_set(iop, fd, type) != 0) {
105  		/* errno set in _file_set() */
106  		(void) close(fd);
107  		return (NULL);
108  	}
109  	iop->_flag = fflag;
110  #endif	/*	_LP64	*/
111  
112  	if (oflag == (O_WRONLY | O_APPEND | O_CREAT)) {	/* type == "a" */
113  		if (lseek64(fd, (off64_t)0, SEEK_END) < (off64_t)0) {
114  			(void) close(fd);
115  			return (NULL);
116  		}
117  	}
118  
119  	return (iop);
120  }
121