Files
rtems/cpukit/libcsupport/src/open.c
Joel Sherrill 6f43d82ecb 2001-04-24 Joel Sherrill <joel@OARcorp.com>
* libc/libio.c (rtems_libio_allocate): Make sure size and offset
	fields are cleared on each file open.  Before this field was cleared,
	this resulted in the value from the last time that IOP was used
	being still in place.  Discovered by  Andrew Bythell
	<abythell@nortelnetworks.com>.
	* libc/open.c: Remove redundant setting of iop->offset.
2001-04-24 23:10:04 +00:00

209 lines
5.5 KiB
C

/*
* open() - POSIX 1003.1 5.3.1 - Open a File
*
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include <rtems/libio_.h>
#include <unistd.h>
/*
* Returns file descriptor on success or -1 and errno set to one of the
* following:
*
* EACCESS - Seach permission is denied on a component of the path prefix,
* or the file exists and the permissions specified by the
* flags are denied, or the file does not exist and write
* permission is denied for the parent directory of the file
* to be created, or O_TRUNC is specified and write permission
* is denied.
* EEXIST - O_CREAT and O_EXCL are set and the named file exists.
* EINTR - The open( operation was interrupted by a signal.
* EINVAL - This implementation does not support synchronized IO for this
* file.
* EISDIR - The named file is a directory and the flags argument
* specified write or read/write access.
* EMFILE - Too many file descriptors are in used by this process.
* ENAMETOOLONG -
* The length of the path exceeds PATH_MAX or a pathname
* component is longer than NAME_MAX while POSIX_NO_TRUNC
* is in effect.
* ENFILE - Too many files are open in the system.
* ENOENT - O_CREAT is not set and and the anmed file does not exist,
* or O_CREAT is set and eitehr the path prefix does not exist
* or the path argument points to an empty string.
* ENOSPC - The directory or file system that would contain the new file
* cannot be extended.
* ENOTDIR - A component of the path prefix is not a directory.
* ENXIO - O_NONBLOCK is set, the named file is a FIFO, O_WRONLY is
* set, and no process has the file open for reading.
* EROFS - The named file resides on a read-only file system and either
* O_WRONLY, O_RDWR, O_CREAT (if the file does not exist), or
* O_TRUNC is set in the flags argument.
*/
int open(
const char *pathname,
int flags,
...
)
{
va_list ap;
int mode;
int rc;
rtems_libio_t *iop = 0;
int status;
rtems_filesystem_location_info_t loc;
int eval_flags;
/*
* Set the Evaluation flags
*/
eval_flags = 0;
status = flags + 1;
if ( ( status & _FREAD ) == _FREAD )
eval_flags |= RTEMS_LIBIO_PERMS_READ;
if ( ( status & _FWRITE ) == _FWRITE )
eval_flags |= RTEMS_LIBIO_PERMS_WRITE;
va_start(ap, flags);
mode = va_arg( ap, int );
/*
* NOTE: This comment is OBSOLETE. The proper way to do this now
* would be to support a magic mounted file system.
*
* Additional external I/O handlers would be supported by adding
* code to pick apart the pathname appropriately. The networking
* code does not require changes here since network file
* descriptors are obtained using socket(), not open().
*/
/* allocate a file control block */
iop = rtems_libio_allocate();
if ( iop == 0 ) {
rc = ENFILE;
goto done;
}
/*
* See if the file exists.
*/
status = rtems_filesystem_evaluate_path(
pathname, eval_flags, &loc, TRUE );
if ( status == -1 ) {
if ( errno != ENOENT ) {
rc = errno;
goto done;
}
/* If the file does not exist and we are not trying to create it--> error */
if ( !(flags & O_CREAT) ) {
rc = ENOENT;
goto done;
}
/* Create the node for the new regular file */
rc = mknod( pathname, S_IFREG | mode, 0LL );
if ( rc ) {
rc = errno;
goto done;
}
/* Sanity check to see if the file name exists after the mknod() */
status = rtems_filesystem_evaluate_path( pathname, 0x0, &loc, TRUE );
if ( status != 0 ) { /* The file did not exist */
rc = EACCES;
goto done;
}
} else if ((flags & (O_EXCL|O_CREAT)) == (O_EXCL|O_CREAT)) {
/* We were trying to create a file that already exists */
rc = EEXIST;
goto done;
}
/*
* Fill in the file control block based on the loc structure
* returned by successful path evaluation.
*/
iop->handlers = loc.handlers;
iop->file_info = loc.node_access;
iop->flags |= rtems_libio_fcntl_flags( flags );
iop->pathinfo = loc;
if ( !iop->handlers->open_h ) {
rc = ENOTSUP;
goto done;
}
rc = (*iop->handlers->open_h)( iop, pathname, flags, mode );
if ( rc )
goto done;
/*
* Optionally truncate the file.
*/
if ( (flags & O_TRUNC) == O_TRUNC ) {
rc = ftruncate( iop - rtems_libio_iops, 0 );
}
/*
* Single exit and clean up path.
*/
done:
va_end(ap);
if ( rc ) {
if ( iop )
rtems_libio_free( iop );
set_errno_and_return_minus_one( rc );
}
rtems_filesystem_freenode( &loc );
return iop - rtems_libio_iops;
}
/*
* _open_r
*
* This is the Newlib dependent reentrant version of open().
*/
#if defined(RTEMS_NEWLIB)
#include <reent.h>
int _open_r(
struct _reent *ptr,
const char *buf,
int flags,
int mode
)
{
return open( buf, flags, mode );
}
#endif