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; }
static int duplicate2_iop( rtems_libio_t *iop, int fd2 ) { rtems_libio_t *iop2; int rv = 0; rtems_libio_check_fd( fd2 ); iop2 = rtems_libio_iop( fd2 ); if (iop != iop2) { int oflag; if ((iop2->flags & LIBIO_FLAGS_OPEN) != 0) { rv = (*iop2->pathinfo.handlers->close_h)( iop2 ); } if (rv == 0) { oflag = rtems_libio_to_fcntl_flags( iop->flags ); oflag &= ~O_CREAT; iop2->flags |= rtems_libio_fcntl_flags( oflag ); rtems_filesystem_instance_lock( &iop->pathinfo ); rtems_filesystem_location_clone( &iop2->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 = (*iop2->pathinfo.handlers->open_h)( iop2, NULL, oflag, 0 ); if ( rv == 0 ) { rv = fd2; } } } 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; }
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; }