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