📄 siosup.c
字号:
return( FALSE ) ; else return( TRUE ) ;}#endif /* HAVE_BSDTTY */#endif /* ! HAVE_ISATTY *//* * Initialize stream I/O for a file descriptor. * * Arguments: * fd: file descriptor * dp: descriptor pointer * stream_type: either __SIO_INPUT_STREAM or __SIO_OUTPUT_STREAM * * Returns * 0 if successful * SIO_ERR if the file descriptor is not valid (sets errno) * exits if stream_type is not __SIO_INPUT_STREAM or __SIO_OUTPUT_STREAM */int __sio_init( __sio_descriptor_t *dp, int fd, enum __sio_stream stream_type ){ struct stat st ; memset(dp, 0, sizeof(__sio_descriptor_t)); if ( fd >= __sio_n_descriptors ) { errno = EBADF ; return( SIO_ERR ) ; } if ( fstat( fd, &st ) == -1 ) return( SIO_ERR ) ; switch ( stream_type ) { case __SIO_INPUT_STREAM: if ( init_input_stream( IDP( dp ), fd, &st ) == FAILURE ) return( SIO_ERR ) ; break ; case __SIO_OUTPUT_STREAM: if ( init_output_stream( ODP( dp ), fd, &st ) == FAILURE ) return( SIO_ERR ) ; break ; default: terminate( "SIO __sio_init: bad stream type (internal error).\n" ) ; /* NOTREACHED */ } dp->stream_type = stream_type ; dp->initialized = TRUE ;#ifdef HAVE_FINALIZATION_FUNCTION if ( ! finalizer_installed ) { if ( ! SIO_FINALIZE( sio_cleanup ) ) { char *s = "SIO __sio_init: finalizer installation failed\n" ; (void) write( 2, s, strlen( s ) ) ; } else finalizer_installed = TRUE ; }#endif /* HAVE_FINALIZATION_FUNCTION */ return( 0 ) ;}/* * __sio_writef writes the data in the buffer to the file descriptor. * * It tries to write as much data as possible until either all data * are written or an error occurs. EINTR is the only error that is * ignored. * In case an error occurs but some data were written, that number * is returned instead of SIO_ERR. * * Fields modified: * When successful: start, nextb * When not successful: start * * Return value: * Number of bytes written * SIO_ERR, if write(2) fails and no data were written */ int __sio_writef( __sio_od_t *odp, int fd ){ int b_in_buffer ; int cc_total = 0 ; /* * Make sure we don't exceed the buffer limits * Maybe we should log this ? XXX */ if ( odp->nextb > odp->buf_end ) odp->nextb = odp->buf_end ; b_in_buffer = odp->nextb - odp->start ; if ( b_in_buffer == 0 ) return( 0 ) ; for ( ;; ) { int cc ; cc = write( fd, odp->start, b_in_buffer ) ; if ( cc == b_in_buffer ) { odp->start = odp->nextb = odp->buf ; cc_total += cc ; break ; } else if ( cc == -1 ) { if ( errno == EINTR ) continue ; else /* * If some bytes were written, return that number, otherwise * return SIO_ERR */ return( ( cc_total != 0 ) ? cc_total : SIO_ERR ) ; } else /* some bytes were written */ { odp->start += cc ; /* advance start of buffer */ b_in_buffer -= cc ; /* decrease number bytes left in buffer */ cc_total += cc ; /* count the bytes that were written */ } } return( cc_total ) ;}/* * __sio_readf reads data from the file descriptor into the buffer. * Unlike __sio_writef it does NOT try to read as much data as will fit * in the buffer. It ignores EINTR. * * Returns: # of bytes read or SIO_ERR * * Fields set: * If it does not return SIO_ERR, it sets start, nextb, end * If it returns SIO_ERR, it does not change anything */static int __sio_readf( __sio_id_t *idp, int fd ){ int cc ; /* * First check for a tied fd and flush the stream if necessary * * XXX the return value of __sio_writef is not checked. * Is that right ? */ if ( idp->tied_fd != SIO_NO_TIED_FD ) (void) __sio_writef( &__SIO_OD( idp->tied_fd ), idp->tied_fd ) ;#ifdef HAVE_MMAP if ( idp->memory_mapped ) { mapd_s *mdp = MDP( fd ) ; /* * The functions initial_map and map_unit may fail. * In either case, we switch to buffered I/O. * If initial_map fails, we have read no data, so we * should perform a read(2). * If map_unit fails (for the next unit), we still have * the data in the current unit, so we can return. */ if ( FIRST_TIME( idp ) ) { cc = initial_map( mdp, fd ) ; if ( cc > 0 ) idp->buf = mdp->first_unit.addr ; else { if ( __sio_switch( idp, fd ) == FAILURE ) return( SIO_ERR ) ; cc = -1 ; } } else { struct map_unit *mu_cur, *mu_next ; if ( idp->buf == mdp->first_unit.addr ) { mu_cur = &mdp->first_unit ; mu_next = &mdp->second_unit ; } else { mu_cur = &mdp->second_unit ; mu_next = &mdp->first_unit ; } if ( mu_next->addr != NULL ) { idp->buf = mu_next->addr ; cc = mu_next->valid_bytes ; /* * XXX: Here we may return SIO_ERR even though there * are data in the current unit because the switch * fails (possibly because malloc failed). */ if ( map_unit( mdp, fd, mu_cur ) == FAILURE && __sio_switch( idp, fd ) == FAILURE ) return( SIO_ERR ) ; } else cc = 0 ; } if ( cc >= 0 ) { idp->end = idp->buf + cc ; idp->start = idp->nextb = idp->buf ; return( cc ) ; } }#endif /* HAVE_MMAP */ for ( ;; ) { cc = read( fd, idp->buf, (int) idp->buffer_size ) ; if ( cc == -1 ) if ( errno == EINTR ) continue ; else return( SIO_ERR ) ; else break ; } idp->end = idp->buf + cc ; idp->start = idp->nextb = idp->buf ; return( cc ) ;}/* * __sio_extend_buffer is used by Srdline to extend the buffer * If successful, it returns the number of bytes that have been read. * If it fails (because of end-of-file or I/O error), it returns 0 or -1. * * Fields modified: * idp->start points to the start of the buffer area (which is in the * auxiliary buffer) * Also, if successful, idp->nextb is set to idp->buf, idp->end is modified. */int __sio_extend_buffer( __sio_id_t *idp, int fd, int b_left ){ int b_read ; /* * copy to auxiliary buffer */ if ( b_left ) sio_memcopy( idp->nextb, idp->buf - b_left, b_left ) ; b_read = __sio_readf( idp, fd ) ; idp->start = idp->buf - b_left ; return( b_read ) ;}/* * __sio_more tries to read more data from the given file descriptor iff * there is free space in the buffer. * __sio_more is used only by Srdline and only AFTER __sio_extend_buffer * has been called. This implies that * a) this is not a memory mapped file * b) __sio_readf has been called (so we don't need to check for tied fd's * * Fields modified (only if successful): * idp->end * * Return value: the number of bytes read. */int __sio_more( __sio_id_t *idp, int fd ){ int b_left = &idp->buf[ idp->buffer_size ] - idp->end ; int cc ; if ( b_left <= 0 ) return( 0 ) ; for ( ;; ) { cc = read( fd, idp->end, b_left ) ; if ( cc >= 0 ) { idp->end += cc ; return( cc ) ; } else if ( errno == EINTR ) continue ; else return( SIO_ERR ) ; }}/* * Finalize a buffer by unmapping the file or freeing the malloc'ed memory. * This function is only called by Sclose. We always free memory even if * SIO_ERR is returned as long as the descriptor was initialized. */int Sdone( int fd ){ __sio_descriptor_t *dp ; int ret_val = 0; if ( fd < 0 || fd >= __sio_n_descriptors ) { errno = EBADF ; return( SIO_ERR ) ; } dp = &__sio_descriptors[ fd ] ; if ( ! DESCRIPTOR_INITIALIZED( dp ) ) { errno = EBADF ; return( SIO_ERR ) ; } switch ( dp->stream_type ) { case __SIO_INPUT_STREAM: { __sio_id_t *idp = IDP( dp ) ;#ifdef HAVE_MMAP if ( idp->memory_mapped ) { mapd_s *mdp = MDP( fd ) ; if ( mdp->first_unit.addr != CHAR_NULL ) (void) SIO_MUNMAP( mdp->first_unit.addr, mdp->first_unit.mapped_bytes ) ; if ( mdp->second_unit.addr != CHAR_NULL ) (void) SIO_MUNMAP( mdp->second_unit.addr, mdp->second_unit.mapped_bytes ) ; idp->memory_mapped = FALSE ; } else#endif /* HAVE_MMAP */ free( idp->buf - idp->buffer_size ) ; idp->nextb = idp->end = NULL ; } break ; case __SIO_OUTPUT_STREAM: { __sio_od_t *odp = ODP( dp ) ; if ( Sflush( fd ) == SIO_ERR ) ret_val = SIO_ERR; free( odp->buf ) ; odp->nextb = odp->buf_end = NULL ; } break ; default: terminate( "SIO Sdone: bad stream type\n" ) ; } memset( dp, 0, sizeof(__sio_descriptor_t) ); dp->initialized = FALSE ; return ret_val;}static char *sioexpand( char *area, unsigned old_size, unsigned new_size, int is_static ){ char *new_area ; if ( is_static ) { if ( ( new_area = malloc( new_size ) ) == NULL ) return( NULL ) ; sio_memcopy( area, new_area, old_size ) ; } else if ( ( new_area = realloc( area, new_size ) ) == NULL ) return( NULL ) ; return( new_area ) ;}/* * Expand the descriptor array (and if we use memory mapping the * memory mapping descriptors). We first expand the memory mapping * descriptors. * There is no problem if the expansion of the SIO descriptors fails * (i.e. there is no need to undo anything). */int Smorefds(int fd){ char *p ; int is_static ; unsigned new_size, old_size ; int n_fds = 4; /* Let's bump 4 at a time for hysteresis */ /* If the fd is out of range of the proposed size, make n_fds big enough */ if (fd >= (__sio_n_descriptors+n_fds)) n_fds += fd - __sio_n_descriptors;#ifdef HAVE_MMAP old_size = __sio_n_descriptors * sizeof( mapd_s ) ; new_size = n_fds * sizeof( mapd_s ) ; new_size += old_size; is_static = ( mmap_descriptors == NULL ) ; p = sioexpand( (char *)mmap_descriptors, old_size, new_size, is_static ) ; if ( p == NULL ) return( SIO_ERR ) ; memset(p+old_size, 0, new_size-old_size); mmap_descriptors = (mapd_s *) p ;#endif /* HAVE_MMAP */ old_size = __sio_n_descriptors * sizeof( __sio_descriptor_t ) ; new_size = n_fds * sizeof( __sio_descriptor_t ) ; new_size += old_size; is_static = ( __sio_descriptors == NULL ) ; p = sioexpand( (char *)__sio_descriptors, old_size, new_size, is_static ) ; if ( p == NULL ) return( SIO_ERR ) ; memset(p+old_size, 0, new_size-old_size); __sio_descriptors = (__sio_descriptor_t *) p ; __sio_n_descriptors += n_fds ; return( 0 ) ;}void terminate(const char *msg){ syslog(LOG_CRIT, "%s", msg); (void) abort() ; _exit( 1 ) ; /* NOT REACHED */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -