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 close( int fd ) { rtems_libio_t *iop; unsigned int flags; int rc; if ( (uint32_t) fd >= rtems_libio_number_iops ) { rtems_set_errno_and_return_minus_one( EBADF ); } iop = rtems_libio_iop( fd ); flags = rtems_libio_iop_flags( iop ); while ( true ) { unsigned int desired; bool success; if ( ( flags & LIBIO_FLAGS_OPEN ) == 0 ) { rtems_set_errno_and_return_minus_one( EBADF ); } /* The expected flags */ flags &= LIBIO_FLAGS_REFERENCE_INC - 1U; desired = flags & ~LIBIO_FLAGS_OPEN; success = _Atomic_Compare_exchange_uint( &iop->flags, &flags, desired, ATOMIC_ORDER_ACQ_REL, ATOMIC_ORDER_RELAXED ); if ( success ) { break; } if ( ( flags & ~( LIBIO_FLAGS_REFERENCE_INC - 1U ) ) != 0 ) { rtems_set_errno_and_return_minus_one( EBUSY ); } } rc = (*iop->pathinfo.handlers->close_h)( iop ); rtems_libio_free( iop ); return rc; }
int close( int fd ) { rtems_libio_t *iop; int rc; rtems_libio_check_fd(fd); iop = rtems_libio_iop(fd); rtems_libio_check_is_open(iop); iop->flags &= ~LIBIO_FLAGS_OPEN; rc = (*iop->pathinfo.handlers->close_h)( iop ); rtems_libio_free( iop ); return rc; }
int close( int fd ) { rtems_libio_t *iop; rtems_status_code rc; rtems_libio_check_fd(fd); iop = rtems_libio_iop(fd); rtems_libio_check_is_open(iop); rc = RTEMS_SUCCESSFUL; if ( iop->handlers->close_h ) rc = (*iop->handlers->close_h)( iop ); rtems_filesystem_freenode( &iop->pathinfo ); rtems_libio_free( iop ); return rc; }
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; }
static int do_open( rtems_libio_t *iop, const char *path, int oflag, mode_t mode ) { int rv = 0; int fd = rtems_libio_iop_to_descriptor( iop ); int rwflag = oflag + 1; bool read_access = (rwflag & _FREAD) == _FREAD; bool write_access = (rwflag & _FWRITE) == _FWRITE; bool make = (oflag & O_CREAT) == O_CREAT; bool exclusive = (oflag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL); bool truncate = (oflag & O_TRUNC) == O_TRUNC; int eval_flags = RTEMS_FS_FOLLOW_LINK | (read_access ? RTEMS_FS_PERMS_READ : 0) | (write_access ? RTEMS_FS_PERMS_WRITE : 0) | (make ? RTEMS_FS_MAKE : 0) | (exclusive ? RTEMS_FS_EXCLUSIVE : 0); rtems_filesystem_eval_path_context_t ctx; rtems_filesystem_eval_path_start( &ctx, path, eval_flags ); if ( rtems_filesystem_eval_path_has_token( &ctx ) ) { create_regular_file( &ctx, mode ); } if ( write_access ) { const rtems_filesystem_location_info_t *currentloc = rtems_filesystem_eval_path_get_currentloc( &ctx ); mode_t type = rtems_filesystem_location_type( currentloc ); if ( S_ISDIR( type ) ) { rtems_filesystem_eval_path_error( &ctx, EISDIR ); } } iop->flags |= rtems_libio_fcntl_flags( oflag ); rtems_filesystem_eval_path_extract_currentloc( &ctx, &iop->pathinfo ); rtems_filesystem_eval_path_cleanup( &ctx ); rv = (*iop->pathinfo.handlers->open_h)( iop, path, oflag, mode ); if ( rv == 0 ) { if ( truncate ) { rv = ftruncate( fd, 0 ); if ( rv != 0 ) { (*iop->pathinfo.handlers->close_h)( iop ); } } if ( rv == 0 ) { rv = fd; } else { rv = -1; } } if ( rv < 0 ) { rtems_libio_free( iop ); } return rv; }
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; }