static int duplicate_iop( rtems_libio_t *iop ) { int rv = 0; rtems_libio_t *diop = rtems_libio_allocate(); if (diop != NULL) { int oflag = rtems_libio_to_fcntl_flags( iop->flags ); oflag &= ~O_CREAT; diop->flags |= rtems_libio_fcntl_flags( oflag ); rtems_filesystem_instance_lock( &iop->pathinfo ); rtems_filesystem_location_clone( &diop->pathinfo, &iop->pathinfo ); rtems_filesystem_instance_unlock( &iop->pathinfo ); /* * XXX: We call the open handler here to have a proper open and close pair. * * FIXME: What to do with the path? */ rv = (*diop->pathinfo.handlers->open_h)( diop, NULL, oflag, 0 ); if ( rv == 0 ) { rv = rtems_libio_iop_to_descriptor( diop ); } else { rtems_libio_free( diop ); } } else { rv = -1; } return rv; }
int rtems_bsdnet_makeFdForSocket( void *so, const rtems_filesystem_file_handlers_r *h ) { rtems_libio_t *iop; int fd; iop = rtems_libio_allocate(); if (iop == 0) rtems_set_errno_and_return_minus_one( ENFILE ); fd = iop - rtems_libio_iops; iop->flags |= LIBIO_FLAGS_WRITE | LIBIO_FLAGS_READ; iop->data0 = fd; iop->data1 = so; iop->pathinfo.handlers = h; iop->pathinfo.ops = &rtems_filesystem_operations_default; return fd; }
/* * Create an RTEMS file descriptor for a socket */ static int rtems_bsdnet_makeFdForSocket (void *so) { rtems_libio_t *iop; int fd; iop = rtems_libio_allocate(); if (iop == 0) rtems_set_errno_and_return_minus_one( ENFILE ); fd = iop - rtems_libio_iops; iop->flags |= LIBIO_FLAGS_WRITE | LIBIO_FLAGS_READ; iop->data0 = fd; iop->data1 = so; iop->pathinfo.handlers = &socket_handlers; iop->pathinfo.ops = &rtems_filesystem_operations_default; iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry; rtems_filesystem_location_add_to_mt_entry(&iop->pathinfo); return fd; }
/** * POSIX 1003.1 5.3.1 - Open a File */ int open( const char *path, int oflag, ... ) { int rv = 0; va_list ap; mode_t mode = 0; rtems_libio_t *iop = NULL; va_start( ap, oflag ); mode = va_arg( ap, mode_t ); iop = rtems_libio_allocate(); if ( iop != NULL ) { rv = do_open( iop, path, oflag, mode ); } else { errno = ENFILE; rv = -1; } va_end( ap ); return rv; }
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; rtems_filesystem_location_info_t *loc_to_free = NULL; 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; loc_to_free = &loc; goto done; } loc_to_free = &loc; /* * 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 ); if ( rc ) { if(errno) rc = errno; close( iop - rtems_libio_iops ); /* those are released by close(): */ iop = 0; loc_to_free = NULL; } } /* * Single exit and clean up path. */ done: va_end(ap); if ( rc ) { if ( iop ) rtems_libio_free( iop ); if ( loc_to_free ) rtems_filesystem_freenode( loc_to_free ); rtems_set_errno_and_return_minus_one( rc ); } return iop - rtems_libio_iops; }
int shm_open( const char *name, int oflag, mode_t mode ) { int err = 0; int fd; rtems_libio_t *iop; POSIX_Shm_Control *shm; size_t len; Objects_Get_by_name_error obj_err; unsigned int flags; if ( shm_check_oflag( oflag ) != 0 ) { return -1; } iop = rtems_libio_allocate(); if ( iop == NULL ) { rtems_set_errno_and_return_minus_one( EMFILE ); } _Objects_Allocator_lock(); shm = _POSIX_Shm_Get_by_name( name, &len, &obj_err ); if ( shm == NULL ) { switch ( obj_err ) { case OBJECTS_GET_BY_NAME_INVALID_NAME: err = EINVAL; break; case OBJECTS_GET_BY_NAME_NAME_TOO_LONG: err = ENAMETOOLONG; break; case OBJECTS_GET_BY_NAME_NO_OBJECT: default: shm = shm_allocate(name, len, oflag, mode, &err); break; } } else { /* shm exists */ if ( ( oflag & ( O_EXCL | O_CREAT ) ) == ( O_EXCL | O_CREAT ) ) { /* Request to create failed. */ err = EEXIST; } else if ( !shm_access_ok( shm, oflag ) ) { err = EACCES; } else { ++shm->reference_count; } } _Objects_Allocator_unlock(); if ( err != 0 ) { rtems_libio_free( iop ); rtems_set_errno_and_return_minus_one( err ); } if ( oflag & O_TRUNC ) { err = shm_ftruncate( iop, 0 ); (void) err; /* ignore truncate error */ } fd = rtems_libio_iop_to_descriptor( iop ); iop->data0 = fd; iop->data1 = shm; iop->pathinfo.node_access = shm; iop->pathinfo.handlers = &shm_handlers; iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry; rtems_filesystem_location_add_to_mt_entry( &iop->pathinfo ); flags = LIBIO_FLAGS_CLOSE_ON_EXEC; if ( oflag & O_RDONLY ) { flags |= LIBIO_FLAGS_READ; } else { flags |= LIBIO_FLAGS_READ_WRITE; } rtems_libio_iop_flags_initialize( iop, flags ); return fd; }
static int vfcntl( int fd, int cmd, va_list ap ) { rtems_libio_t *iop; rtems_libio_t *diop; int fd2; int flags; int mask; int ret = 0; rtems_libio_check_fd( fd ); iop = rtems_libio_iop( fd ); rtems_libio_check_is_open(iop); /* * Now process the fcntl(). */ /* * This switch should contain all the cases from POSIX. */ switch ( cmd ) { case F_DUPFD: /* dup */ fd2 = va_arg( ap, int ); if ( fd2 ) diop = rtems_libio_iop( fd2 ); else { /* allocate a file control block */ diop = rtems_libio_allocate(); if ( diop == 0 ) { ret = -1; break; } } diop->handlers = iop->handlers; diop->file_info = iop->file_info; diop->flags = iop->flags; diop->pathinfo = iop->pathinfo; ret = (int) (diop - rtems_libio_iops); break; case F_GETFD: /* get f_flags */ ret = ((iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC) != 0); break; case F_SETFD: /* set f_flags */ /* * Interpret the third argument as the "close on exec()" flag. * If this argument is 1, then the file descriptor is to be closed * if a new process is exec()'ed. Since RTEMS does not support * processes, then we can ignore this one except to make * F_GETFD work. */ if ( va_arg( ap, int ) ) iop->flags |= LIBIO_FLAGS_CLOSE_ON_EXEC; else iop->flags &= ~LIBIO_FLAGS_CLOSE_ON_EXEC; break; case F_GETFL: /* more flags (cloexec) */ ret = rtems_libio_to_fcntl_flags( iop->flags ); break; case F_SETFL: flags = rtems_libio_fcntl_flags( va_arg( ap, int ) ); mask = LIBIO_FLAGS_NO_DELAY | LIBIO_FLAGS_APPEND; /* * XXX If we are turning on append, should we seek to the end? */ iop->flags = (iop->flags & ~mask) | (flags & mask); break; case F_GETLK: errno = ENOTSUP; ret = -1; break; case F_SETLK: errno = ENOTSUP; ret = -1; break; case F_SETLKW: errno = ENOTSUP; ret = -1; break; case F_SETOWN: /* for sockets. */ errno = ENOTSUP; ret = -1; break; case F_GETOWN: /* for sockets. */ errno = ENOTSUP; ret = -1; break; default: errno = EINVAL; ret = -1; break; }