📄 siosup.c
字号:
terminate( "SIO __sio_init: bad stream type (internal error).\n" ) ; /* NOTREACHED */ } dp->stream_type = stream_type ; dp->initialized = TRUE ;#ifdef HAS_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 /* HAS_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( odp, fd ) register __sio_od_t *odp ; int fd ;{ register int b_in_buffer ; register int cc_total = 0 ;#ifdef EVENTS EVENT( fd, EV_SIO_WRITEF ) ;#endif /* * 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 ( ;; ) { register 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 */int __sio_readf( idp, fd ) register __sio_id_t *idp ; int fd ;{ register int cc ;#ifdef EVENTS EVENT( fd, EV_SIO_READF ) ;#endif /* * 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 HAS_MMAP if ( idp->memory_mapped ) { register 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 { register 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 /* HAS_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( idp, fd, b_left ) register __sio_id_t *idp ; int fd ; register int b_left ;{ register int b_read ;#ifdef EVENTS EVENT( fd, EV_SIO_EXTEND_BUFFER ) ;#endif /* * 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( idp, fd ) register __sio_id_t *idp ; int fd ;{ register int b_left = &idp->buf[ idp->buffer_size ] - idp->end ; register int cc ;#ifdef EVENTS EVENT( fd, EV_SIO_MORE ) ;#endif 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 */int Sdone( fd ) int fd ;{ register __sio_descriptor_t *dp = &__sio_descriptors[ fd ] ;#ifdef EVENTS EVENT( fd, EV_SDONE ) ;#endif if ( ! DESCRIPTOR_INITIALIZED( dp ) ) { errno = EBADF ; return( SIO_ERR ) ; } switch ( dp->stream_type ) { case __SIO_INPUT_STREAM: { register __sio_id_t *idp = IDP( dp ) ;#ifdef HAS_MMAP if ( idp->memory_mapped ) { register 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 /* HAS_MMAP */ free( idp->buf - idp->buffer_size ) ; idp->nextb = idp->end = NULL ; } break ; case __SIO_OUTPUT_STREAM: { register __sio_od_t *odp = ODP( dp ) ; if ( Sflush( fd ) == SIO_ERR ) return( SIO_ERR ) ; free( odp->buf ) ; odp->nextb = odp->buf_end = NULL ; } break ; default: terminate( "SIO Sdone: bad stream type\n" ) ; } dp->initialized = FALSE ; return( 0 ) ;}PRIVATE char *expand( area, old_size, new_size, is_static ) char *area ; unsigned old_size, 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 ) ;}#include <sys/time.h>#include <sys/resource.h>PRIVATE int get_fd_limit(){#ifdef RLIMIT_NOFILE struct rlimit rl ; (void) getrlimit( RLIMIT_NOFILE, &rl ) ; return( rl.rlim_cur ) ;#else return( N_SIO_DESCRIPTORS ) ;#endif}/* * 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(){ char *p ; int is_static ; unsigned new_size, old_size ; int n_fds = get_fd_limit() ; if ( n_fds <= n_descriptors ) return( 0 ) ;#ifdef EVENTS old_size = n_descriptors * sizeof( events_s ) ; new_size = n_fds * sizeof( events_s ) ; is_static = ( __sio_events == static___sio_events ) ; p = expand( (char *)__sio_events, old_size, new_size, is_static ) ; if ( p == NULL ) return( SIO_ERR ) ; __sio_events = (events_s *) p ; /* * Clear the codes field of the extra events structs. * We have to do this because a non-null codes field implies that * events recording is on for that fd */ { int i ; for ( i = n_descriptors ; i < n_fds ; i++ ) __sio_events[i].codes = NULL ; }#endif /* EVENTS */#ifdef HAS_MMAP old_size = n_descriptors * sizeof( mapd_s ) ; new_size = n_fds * sizeof( mapd_s ) ; is_static = ( mmap_descriptors == static_mapd_array ) ; p = expand( (char *)mmap_descriptors, old_size, new_size, is_static ) ; if ( p == NULL ) return( SIO_ERR ) ; mmap_descriptors = (mapd_s *) p ;#endif /* HAS_MMAP */ old_size = n_descriptors * sizeof( __sio_descriptor_t ) ; new_size = n_fds * sizeof( __sio_descriptor_t ) ; is_static = ( __sio_descriptors == static_descriptor_array ) ; p = expand( (char *)__sio_descriptors, old_size, new_size, is_static ) ; if ( p == NULL ) return( SIO_ERR ) ; __sio_descriptors = (__sio_descriptor_t *) p ; n_descriptors = n_fds ; return( 0 ) ;}#ifdef EVENTS/* * Enable recording of events for the specified file descriptor */int __sio_enable_events( fd ) int fd ;{ char *p = malloc( EVENT_ENTRIES * sizeof( short ) ) ; if ( p == NULL ) return( SIO_ERR ) ; __sio_events[ fd ].codes = (short *) p ; return( 0 ) ;}/* * Disable recording of events for the specified file descriptor */void __sio_disable_events( fd ) int fd ;{ if ( __sio_events[ fd ].codes != NULL ) { free( (char *) __sio_events[ fd ].codes ) ; __sio_events[ fd ].codes = NULL ; }}/* * Move stored events to buf */int __sio_get_events( fd, buf, size ) int fd ; char *buf ; int size ;{ events_s *evp = &__sio_events[ fd ] ; int bufentries ; int range1, range2 ; int diff ; char *p ; int cc ; int cc_total ; int move_entries ; if ( evp->codes == NULL ) return( 0 ) ; diff = evp->next - evp->start ; if ( diff == 0 ) return( 0 ) ; if ( diff > 0 ) { range1 = diff ; range2 = 0 ; } else { range1 = EVENT_ENTRIES - evp->start ; range2 = evp->next ; } bufentries = size / sizeof( short ) ; p = buf ; cc_total = 0 ; move_entries = MIN( range1, bufentries ) ; cc = move_entries * sizeof( short ) ; sio_memcopy( (char *) &evp->codes[ evp->start ], p, cc ) ; cc_total += cc ; p += cc ; bufentries -= range1 ; ADD( evp->start, move_entries ) ; if ( bufentries == 0 || range2 == 0 ) return( cc_total ) ; move_entries = MIN( range2, bufentries ) ; cc = move_entries * sizeof( short ) ; sio_memcopy( (char *) &evp->codes[ evp->start ], p, cc ) ; cc_total += cc ; ADD( evp->start, move_entries ) ; return( cc_total ) ;}#endif /* EVENTS *//* * Simple function that prints the string s at stderr and then calls * exit */PRIVATE void terminate( s ) char *s ;{ (void) write( 2, s, strlen( s ) ) ; (void) abort() ; exit( 1 ) ; /* in case abort fails */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -