xref: /illumos-gate/usr/src/lib/libc/port/stdio/_endopen.c (revision 144dfaa9a648eea321858b34d4941d2268130176)
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  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*	Copyright (c) 1988 AT&T	*/
29 /*	  All Rights Reserved  	*/
30 
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 <sys/feature_tests.h>
39 
40 #define	close		_close
41 #define	lseek		_lseek
42 #define	open		_open
43 #if !defined(_LP64)
44 #define	lseek64		_lseek64
45 #define	open64		_open64
46 #endif
47 
48 #include "lint.h"
49 #include "file64.h"
50 #include <mtlib.h>
51 #include <sys/types.h>
52 #include <stdio.h>
53 #include <fcntl.h>
54 #include <unistd.h>
55 #include <limits.h>
56 #include <thread.h>
57 #include <synch.h>
58 #include "stdiom.h"
59 #include <errno.h>
60 
61 /*
62  * open UNIX file name, associate with iop
63  */
64 
65 FILE *
66 _endopen(const char *name, const char *type, FILE *iop, int largefile)
67 {
68 	int oflag, fd, fflag;
69 	char plus;
70 
71 	if (iop == NULL)
72 		return (NULL);
73 	switch (type[0]) {
74 	default:
75 		errno = EINVAL;
76 		return (NULL);
77 	case 'r':
78 		oflag = O_RDONLY;
79 		fflag = _IOREAD;
80 		break;
81 	case 'w':
82 		oflag = O_WRONLY | O_TRUNC | O_CREAT;
83 		fflag = _IOWRT;
84 		break;
85 	case 'a':
86 		oflag = O_WRONLY | O_APPEND | O_CREAT;
87 		fflag = _IOWRT;
88 		break;
89 	}
90 	/* UNIX ignores 'b' and treats text and binary the same */
91 	if ((plus = type[1]) == 'b')
92 		plus = type[2];
93 	if (plus == '+') {
94 		oflag = (oflag & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
95 		fflag = _IORW;
96 	}
97 
98 	/* select small or large file open based on flag */
99 	if (largefile) {
100 		fd = open64(name, oflag, 0666);
101 	} else {
102 		fd = open(name, oflag, 0666);
103 	}
104 	if (fd < 0)
105 		return (NULL);
106 
107 	/* As long as we make sure _flag stays != 0, we don't need to lock */
108 #ifdef	_LP64
109 	iop->_file = fd;
110 	iop->_flag = (iop->_flag & ~0377) | fflag;
111 #else
112 	if (fd <= _FILE_FD_MAX) {
113 		SET_FILE(iop, fd);
114 	} else if (_file_set(iop, fd, type) != 0) {
115 		/* errno set in _file_set() */
116 		(void) close(fd);
117 		return (NULL);
118 	}
119 	iop->_flag = fflag;
120 #endif	/*	_LP64	*/
121 
122 	if (oflag == (O_WRONLY | O_APPEND | O_CREAT)) {	/* type == "a" */
123 		if (lseek64(fd, (off64_t)0, SEEK_END) < (off64_t)0) {
124 			(void) close(fd);
125 			return (NULL);
126 		}
127 	}
128 
129 	return (iop);
130 }
131