[07a3253d] | 1 | /* |
---|
| 2 | * open() - POSIX 1003.1 5.3.1 - Open a File |
---|
| 3 | * |
---|
| 4 | * COPYRIGHT (c) 1989-1998. |
---|
| 5 | * On-Line Applications Research Corporation (OAR). |
---|
| 6 | * Copyright assigned to U.S. Government, 1994. |
---|
| 7 | * |
---|
| 8 | * The license and distribution terms for this file may be |
---|
| 9 | * found in the file LICENSE in this distribution or at |
---|
| 10 | * http://www.OARcorp.com/rtems/license.html. |
---|
| 11 | * |
---|
| 12 | * $Id$ |
---|
| 13 | */ |
---|
| 14 | |
---|
| 15 | #include "libio_.h" |
---|
| 16 | |
---|
| 17 | #include <unistd.h> |
---|
| 18 | |
---|
| 19 | /* |
---|
| 20 | * Returns file descriptor on success or -1 and errno set to one of the |
---|
| 21 | * following: |
---|
| 22 | * |
---|
| 23 | * EACCESS - Seach permission is denied on a component of the path prefix, |
---|
| 24 | * or the file exists and the permissions specified by the |
---|
| 25 | * flags are denied, or the file does not exist and write |
---|
| 26 | * permission is denied for the parent directory of the file |
---|
| 27 | * to be created, or O_TRUNC is specified and write permission |
---|
| 28 | * is denied. |
---|
| 29 | * EEXIST - O_CREAT and O_EXCL are set and the named file exists. |
---|
| 30 | * EINTR - The open( operation was interrupted by a signal. |
---|
| 31 | * EINVAL - This implementation does not support synchronized IO for this |
---|
| 32 | * file. |
---|
| 33 | * EISDIR - The named file is a directory and the flags argument |
---|
| 34 | * specified write or read/write access. |
---|
| 35 | * EMFILE - Too many file descriptors are in used by this process. |
---|
| 36 | * ENAMETOOLONG - |
---|
| 37 | * The length of the path exceeds PATH_MAX or a pathname |
---|
| 38 | * component is longer than NAME_MAX while POSIX_NO_TRUNC |
---|
| 39 | * is in effect. |
---|
| 40 | * ENFILE - Too many files are open in the system. |
---|
| 41 | * ENOENT - O_CREAT is not set and and the anmed file does not exist, |
---|
| 42 | * or O_CREAT is set and eitehr the path prefix does not exist |
---|
| 43 | * or the path argument points to an empty string. |
---|
| 44 | * ENOSPC - The directory or file system that would contain the new file |
---|
| 45 | * cannot be extended. |
---|
| 46 | * ENOTDIR - A component of the path prefix is not a directory. |
---|
| 47 | * ENXIO - O_NONBLOCK is set, the named file is a FIFO, O_WRONLY is |
---|
| 48 | * set, and no process has the file open for reading. |
---|
| 49 | * EROFS - The named file resides on a read-only file system and either |
---|
| 50 | * O_WRONLY, O_RDWR, O_CREAT (if the file does not exist), or |
---|
| 51 | * O_TRUNC is set in the flags argument. |
---|
| 52 | */ |
---|
| 53 | |
---|
| 54 | int open( |
---|
| 55 | const char *pathname, |
---|
| 56 | int flags, |
---|
| 57 | ... |
---|
| 58 | ) |
---|
| 59 | { |
---|
| 60 | va_list ap; |
---|
| 61 | int mode; |
---|
| 62 | int rc; |
---|
| 63 | rtems_libio_t *iop = 0; |
---|
| 64 | int status; |
---|
| 65 | rtems_filesystem_location_info_t temp_loc; |
---|
| 66 | int eval_flags; |
---|
| 67 | |
---|
| 68 | |
---|
| 69 | /* |
---|
| 70 | * Set the Evaluation flags |
---|
| 71 | */ |
---|
| 72 | |
---|
| 73 | eval_flags = 0; |
---|
| 74 | status = flags + 1; |
---|
| 75 | if ( ( status & _FREAD ) == _FREAD ) |
---|
| 76 | eval_flags |= RTEMS_LIBIO_PERMS_READ; |
---|
| 77 | if ( ( status & _FWRITE ) == _FWRITE ) |
---|
| 78 | eval_flags |= RTEMS_LIBIO_PERMS_WRITE; |
---|
| 79 | |
---|
| 80 | |
---|
| 81 | va_start(ap, flags); |
---|
| 82 | |
---|
| 83 | mode = va_arg( ap, int ); |
---|
| 84 | |
---|
| 85 | /* |
---|
| 86 | * NOTE: This comment is OBSOLETE. The proper way to do this now |
---|
| 87 | * would be to support a magic mounted file system. |
---|
| 88 | * |
---|
| 89 | * Additional external I/O handlers would be supported by adding |
---|
| 90 | * code to pick apart the pathname appropriately. The networking |
---|
| 91 | * code does not require changes here since network file |
---|
| 92 | * descriptors are obtained using socket(), not open(). |
---|
| 93 | */ |
---|
| 94 | |
---|
| 95 | /* allocate a file control block */ |
---|
| 96 | iop = rtems_libio_allocate(); |
---|
| 97 | if ( iop == 0 ) { |
---|
| 98 | rc = ENFILE; |
---|
| 99 | goto done; |
---|
| 100 | } |
---|
| 101 | |
---|
| 102 | /* |
---|
| 103 | * See if the file exists. |
---|
| 104 | */ |
---|
| 105 | |
---|
[2f87c843] | 106 | status = rtems_filesystem_evaluate_path( |
---|
| 107 | pathname, eval_flags, &temp_loc, TRUE ); |
---|
[07a3253d] | 108 | |
---|
| 109 | if ( status == -1 ) { |
---|
| 110 | if ( errno != ENOENT ) { |
---|
| 111 | rc = errno; |
---|
| 112 | goto done; |
---|
| 113 | } |
---|
| 114 | |
---|
| 115 | /* If the file does not exist and we are not trying to create it--> error */ |
---|
| 116 | if ( !(flags & O_CREAT) ) { |
---|
| 117 | rc = ENOENT; |
---|
| 118 | goto done; |
---|
| 119 | } |
---|
| 120 | |
---|
| 121 | /* Create the node for the new regular file */ |
---|
| 122 | rc = mknod( pathname, S_IFREG | mode, 0LL ); |
---|
| 123 | if ( rc ) { |
---|
| 124 | rc = errno; |
---|
| 125 | goto done; |
---|
| 126 | } |
---|
| 127 | |
---|
| 128 | /* Sanity check to see if the file name exists after the mknod() */ |
---|
| 129 | status = rtems_filesystem_evaluate_path( pathname, 0x0, &temp_loc, TRUE ); |
---|
| 130 | if ( status != 0 ) { /* The file did not exist */ |
---|
| 131 | rc = EACCES; |
---|
| 132 | goto done; |
---|
| 133 | } |
---|
| 134 | |
---|
| 135 | } else if ((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT)) { |
---|
| 136 | /* We were trying to create a file that already exists */ |
---|
| 137 | rc = EEXIST; |
---|
| 138 | goto done; |
---|
| 139 | } |
---|
| 140 | |
---|
| 141 | /* |
---|
| 142 | * Fill in the file control block based on the temp_loc structure |
---|
| 143 | * returned by successful path evaluation. |
---|
| 144 | */ |
---|
| 145 | |
---|
| 146 | iop->handlers = temp_loc.handlers; |
---|
| 147 | iop->file_info = temp_loc.node_access; |
---|
| 148 | iop->flags |= rtems_libio_fcntl_flags( flags ); |
---|
| 149 | iop->pathinfo = temp_loc; |
---|
| 150 | |
---|
| 151 | if ( !iop->handlers->open ) { |
---|
| 152 | rc = ENOTSUP; |
---|
| 153 | goto done; |
---|
| 154 | } |
---|
| 155 | |
---|
| 156 | rc = (*iop->handlers->open)( iop, pathname, flags, mode ); |
---|
| 157 | if ( rc ) |
---|
| 158 | goto done; |
---|
| 159 | |
---|
| 160 | /* |
---|
| 161 | * Optionally truncate the file. |
---|
| 162 | */ |
---|
| 163 | |
---|
| 164 | if ( (flags & O_TRUNC) == O_TRUNC ) { |
---|
| 165 | rc = ftruncate( iop - rtems_libio_iops, 0 ); |
---|
| 166 | } |
---|
| 167 | |
---|
| 168 | /* |
---|
| 169 | * Single exit and clean up path. |
---|
| 170 | */ |
---|
| 171 | |
---|
| 172 | done: |
---|
| 173 | va_end(ap); |
---|
| 174 | |
---|
| 175 | if ( rc ) { |
---|
| 176 | if ( iop ) |
---|
| 177 | rtems_libio_free( iop ); |
---|
| 178 | set_errno_and_return_minus_one( rc ); |
---|
| 179 | } |
---|
| 180 | return iop - rtems_libio_iops; |
---|
| 181 | } |
---|
| 182 | |
---|
| 183 | /* |
---|
| 184 | * _open_r |
---|
| 185 | * |
---|
| 186 | * This is the Newlib dependent reentrant version of open(). |
---|
| 187 | */ |
---|
| 188 | |
---|
| 189 | #if defined(RTEMS_NEWLIB) |
---|
| 190 | |
---|
| 191 | #include <reent.h> |
---|
| 192 | |
---|
| 193 | int _open_r( |
---|
| 194 | struct _reent *ptr, |
---|
| 195 | const char *buf, |
---|
| 196 | int flags, |
---|
| 197 | int mode |
---|
| 198 | ) |
---|
| 199 | { |
---|
| 200 | return open( buf, flags, mode ); |
---|
| 201 | } |
---|
| 202 | #endif |
---|