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 /* Copyright (c) 2013 OmniTI Computer Consulting, Inc. All rights reserved. */
  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, eflag, plusflag;
  59         const char *echr;
  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 
  81         plusflag = 0;
  82         eflag = 0;
  83         for (echr = type + 1; *echr != '\0'; echr++) {
  84                 switch (*echr) {
  85                 /* UNIX ignores 'b' and treats text and binary the same */
  86                 default:
  87                         break;
  88                 case '+':
  89                         plusflag = 1;
  90                         break;
  91                 case 'e':
  92                         eflag = 1;
  93                         break;
  94                 }
  95         }
  96         if (eflag) {
  97                 /* Subsequent to a mode flag, 'e' indicates O_CLOEXEC */
  98                 oflag = oflag | O_CLOEXEC;
  99         }
 100         if (plusflag) {
 101                 oflag = (oflag & ~(O_RDONLY | O_WRONLY)) | O_RDWR;
 102                 fflag = _IORW;
 103         }
 104 
 105         /* select small or large file open based on flag */
 106         if (largefile) {
 107                 fd = open64(name, oflag, 0666);
 108         } else {
 109                 fd = open(name, oflag, 0666);
 110         }
 111         if (fd < 0)
 112                 return (NULL);
 113 
 114         /* As long as we make sure _flag stays != 0, we don't need to lock */
 115 #ifdef  _LP64
 116         iop->_file = fd;
 117         iop->_flag = (iop->_flag & ~0377) | fflag;
 118 #else
 119         if (fd <= _FILE_FD_MAX) {
 120                 SET_FILE(iop, fd);
 121         } else if (_file_set(iop, fd, type) != 0) {
 122                 /* errno set in _file_set() */
 123                 (void) close(fd);
 124                 return (NULL);
 125         }
 126         iop->_flag = fflag;
 127 #endif  /*      _LP64   */
 128 
 129         if (oflag == (O_WRONLY | O_APPEND | O_CREAT)) { /* type == "a" */
 130                 if (lseek64(fd, (off64_t)0, SEEK_END) < (off64_t)0) {
 131                         (void) close(fd);
 132                         return (NULL);
 133                 }
 134         }
 135 
 136         return (iop);
 137 }