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