/* cm.ret is also set to an error <0 or the read length */ void *ReadHandler(struct handlerdata *hd, struct client_msg *cm, struct one_wire_query *owq) { BYTE * retbuffer = NULL ; SIZE_OR_ERROR read_or_error; LEVEL_DEBUG("ReadHandler start"); if (hd == NULL || owq == NULL || cm == NULL) { LEVEL_DEBUG("ReadHandler: illegal null inputs hd==%p owq==%p cm==%p", hd, owq, cm); return NULL; // only sane response for bad inputs } LEVEL_DEBUG("ReadHandler: From Client sm->payload=%d sm->size=%d sm->offset=%d", hd->sm.payload, hd->sm.size, hd->sm.offset); if (hd->sm.payload >= PATH_MAX) { cm->ret = -EMSGSIZE; } else if ((hd->sm.size <= 0) || (hd->sm.size > MAX_OWSERVER_PROTOCOL_PAYLOAD_SIZE)) { cm->ret = -EMSGSIZE; LEVEL_DEBUG("ReadHandler: error hd->sm.size == %d", hd->sm.size); } else if ( BAD( OWQ_allocate_read_buffer(owq)) ) { // allocate read buffer LEVEL_DEBUG("ReadHandler: can't allocate memory"); cm->ret = -ENOBUFS; } else { struct parsedname *pn = PN(owq); if ( OWQ_size(owq) > (size_t) hd->sm.size ) { OWQ_size(owq) = hd->sm.size ; } OWQ_offset(owq) = hd->sm.offset ; LEVEL_DEBUG("ReadHandler: call FS_read_postparse on %s", pn->path); read_or_error = FS_read_postparse(owq); LEVEL_DEBUG("ReadHandler: FS_read_postparse read on %s return = %d", pn->path, read_or_error); Debug_OWQ(owq); if (read_or_error <= 0) { LEVEL_DEBUG("ReadHandler: FS_read_postparse error %d", read_or_error); cm->ret = read_or_error; } else { LEVEL_DEBUG("ReadHandler: FS_read_postparse ok size=%d", read_or_error); // make return size smaller (just large enough) cm->payload = read_or_error; cm->offset = hd->sm.offset; cm->size = read_or_error; cm->ret = read_or_error; /* Move this pointer, and let owfree remove it instead of OWQ_destroy() */ retbuffer = (BYTE *)OWQ_buffer(owq); OWQ_buffer(owq) = NULL; } } LEVEL_DEBUG("ReadHandler: To Client cm->payload=%d cm->size=%d cm->offset=%d", cm->payload, cm->size, cm->offset); if ((cm->size > 0)) { Debug_Bytes("Data returned to client",(BYTE *) OWQ_buffer(owq),cm->size) ; } return retbuffer; }
SIZE_OR_ERROR FS_get(const char *path, char **return_buffer, size_t * buffer_length) { SIZE_OR_ERROR size = 0 ; /* current buffer string length */ OWQ_allocate_struct_and_pointer( owq ) ; /* Check the parameters */ if (return_buffer == NULL) { // No buffer for read result. return -EINVAL; } if (path == NULL) { path = "/"; } *return_buffer = NULL; // default return string on error if ( BAD( OWQ_create(path, owq) ) ) { /* Can we parse the input string */ return -ENOENT; } if ( IsDir( PN(owq) ) ) { /* A directory of some kind */ struct charblob cb ; CharblobInit(&cb) ; getdir( &cb, owq ) ; size = CharblobLength(&cb) ; *return_buffer = copy_buffer( CharblobData(&cb), size ) ; CharblobClear( &cb ) ; } else { /* A regular file -- so read */ if ( GOOD(OWQ_allocate_read_buffer(owq)) ) { // make the space in the buffer size = FS_read_postparse(owq) ; *return_buffer = copy_buffer( OWQ_buffer(owq), size ) ; } } // the buffer is allocated by getdir or getval OWQ_destroy(owq); /* Check the parameters */ if (*return_buffer == NULL) { // no data. return -EINVAL; } if ( buffer_length != NULL ) { *buffer_length = size ; } return size ; }
SIZE_OR_ERROR FS_get(const char *path, char **return_buffer, size_t * buffer_length) { SIZE_OR_ERROR size = 0 ; /* current buffer string length */ OWQ_allocate_struct_and_pointer( owq ) ; /* Check the parameters */ if (return_buffer == NULL) { // No buffer supplied for read result. return -EINVAL; } if (path == NULL) { path = "/"; } *return_buffer = NULL; // default return string on error if ( BAD( OWQ_create(path, owq) ) ) { /* Can we parse the input string */ return -ENOENT; } // Check for known type. if ( (PN(owq)->selected_filetype) != NO_FILETYPE ) { // local owlib knows the type. if ( IsDir( PN(owq) ) ) { /* A directory of some kind */ struct charblob cb ; CharblobInit(&cb) ; getdir( &cb, owq ) ; size = CharblobLength(&cb) ; *return_buffer = copy_buffer( CharblobData(&cb), size ) ; CharblobClear(&cb) ; } else { /* A regular file -- so read */ if ( GOOD(OWQ_allocate_read_buffer(owq)) ) { // make the space in the buffer size = FS_read_postparse(owq) ; *return_buffer = copy_buffer( OWQ_buffer(owq), size ) ; } } } else { // local owlib doesn't know the type. struct charblob cb ; CharblobInit(&cb) ; // Try directory first. if (getdir( &cb, owq ) != -ENOTDIR) { // Is a directory. size = CharblobLength(&cb) ; *return_buffer = copy_buffer( CharblobData(&cb), size ) ; } else { // Is not a directory. Try file. if ( GOOD(OWQ_allocate_read_buffer(owq)) ) { // make the space in the buffer size = FS_read_postparse(owq) ; *return_buffer = copy_buffer( OWQ_buffer(owq), size ) ; } } CharblobClear(&cb) ; } // the buffer is allocated by getdir or getval OWQ_destroy(owq); /* Check the parameters */ if (*return_buffer == NULL) { // error return -EINVAL; } if ( buffer_length != NULL ) { // return buffer length as well *buffer_length = size ; } return size ; }
// Handles: ALL static ZERO_OR_ERROR FS_read_in_parts( struct one_wire_query *owq_all ) { struct parsedname *pn = PN(owq_all); struct filetype * ft = pn->selected_filetype ; struct one_wire_query * owq_part ; size_t elements = pn->selected_filetype->ag->elements; size_t extension; char * buffer_pointer = OWQ_buffer(owq_all) ; size_t buffer_left = OWQ_size(owq_all) ; // single for BYTE or iteration owq_part = OWQ_create_separate( 0, owq_all ) ; if ( owq_part == NO_ONE_WIRE_QUERY ) { return -ENOENT ; } // bitfield if ( ft->format == ft_bitfield ) { OWQ_pn(owq_part).extension = EXTENSION_BYTE ; if ( FS_read_owq(owq_part) < 0 ) { OWQ_destroy( owq_part ) ; return -EINVAL ; } for (extension = 0; extension < elements; ++extension) { OWQ_array_Y(owq_all,extension) = UT_getbit_U( OWQ_U(owq_part), extension ) ; } OWQ_destroy( owq_part ) ; return 0 ; } if ( BAD( OWQ_allocate_read_buffer( owq_part )) ) { LEVEL_DEBUG("Can't allocate buffer space"); OWQ_destroy( owq_part ) ; return -EMSGSIZE ; } /* Loop through get data */ for (extension = 0; extension < elements; ++extension) { size_t part_length ; OWQ_pn(owq_part).extension = extension; if ( FS_read_owq(owq_part) < 0 ) { OWQ_destroy( owq_part ) ; return -EINVAL ; } // Check that there is enough space for the combined message switch ( ft->format ) { case ft_ascii: case ft_vascii: case ft_alias: case ft_binary: part_length = OWQ_length(owq_part) ; if ( buffer_left < part_length ) { OWQ_destroy( owq_part ) ; return -EMSGSIZE ; } memcpy( buffer_pointer, OWQ_buffer(owq_part), part_length ) ; OWQ_array_length(owq_all,extension) = part_length ; buffer_pointer += part_length ; buffer_left -= part_length ; break ; default: // copy object (single to mixed array) memcpy(&OWQ_array(owq_all)[extension], &OWQ_val(owq_part), sizeof(union value_object)); break; } } OWQ_destroy( owq_part ) ; return 0; }