예제 #1
0
파일: ow_read.c 프로젝트: stromnet/owfs
// Handles .n
static ZERO_OR_ERROR FS_read_a_part( struct one_wire_query *owq_part )
{
	struct parsedname *pn = PN(owq_part);
	size_t extension = pn->extension;
	struct filetype * ft = pn->selected_filetype ;
	struct one_wire_query * owq_all ;
	
	// bitfield
	if ( ft->format == ft_bitfield ) {
		return FS_read_a_bit( owq_part ) ;
	}

	// non-bitfield 
	owq_all = OWQ_create_aggregate( owq_part ) ;
	if ( owq_all == NO_ONE_WIRE_QUERY ) {
		return -ENOENT ;
	}
	
	// First fill the whole array with current values
	if ( FS_read_owq( owq_all ) < 0 ) {
		OWQ_destroy( owq_all ) ;
		return -EINVAL ;
	}

	// Copy ascii/binary field
	switch (ft->format) {
	case ft_binary:
	case ft_ascii:
	case ft_vascii:
	case ft_alias:
		{
			size_t extension_index;
			char *buffer_pointer = OWQ_buffer(owq_all);

			// All prior elements
			for (extension_index = 0; extension_index < extension; ++extension_index) {
				// move past their buffer position
				buffer_pointer += OWQ_array_length(owq_all, extension_index);
			}

			// now move current element's buffer to location
			OWQ_length(owq_part) = OWQ_array_length(owq_all, extension) ;
			memmove( OWQ_buffer(owq_part), buffer_pointer, OWQ_length(owq_part));
			break;
		}
	default:
		// Copy value field
		memcpy( &OWQ_val(owq_part), &OWQ_array(owq_all)[pn->extension], sizeof(union value_object) );
		break;
	}

	OWQ_destroy(owq_all);
	return 0 ;
}
예제 #2
0
파일: ow_lcd.c 프로젝트: M-o-a-T/owfs
static ZERO_OR_ERROR FS_w_screenX(struct one_wire_query *owq)
{
	struct one_wire_query * owq_line ;
	int extension;

	struct parsedname *pn = PN(owq);

	int width = pn->selected_filetype->data.i;
	int rows = (width == 40) ? 2 : 4;	/* max number of rows */
	char *start_of_remaining_text = OWQ_buffer(owq);
	char *pointer_after_all_text = OWQ_buffer(owq) + OWQ_size(owq);

	if (OWQ_offset(owq)) {
		return -ERANGE;
	}

	if (BAD( OW_clear(pn) ) ) {
		return -EFAULT;
	}

	owq_line = OWQ_create_separate( 0, owq ) ;
	if ( owq_line == NO_ONE_WIRE_QUERY ) {
		return -ENOMEM ;
	}

	for (extension = 0; extension < rows; ++extension) {
		char *newline_location = memchr(start_of_remaining_text, '\n',
										pointer_after_all_text - start_of_remaining_text);
		OWQ_pn(owq_line).extension = extension;
		OWQ_buffer(owq_line) = start_of_remaining_text;
		if ((newline_location != NULL)
			&& (newline_location < start_of_remaining_text + width)) {
			OWQ_size(owq_line) = newline_location - start_of_remaining_text;
			start_of_remaining_text = newline_location + 1;	/* skip over newline */
		} else {
			char *lineend_location = start_of_remaining_text + width;
			if (lineend_location > pointer_after_all_text) {
				lineend_location = pointer_after_all_text;
			}
			OWQ_size(owq_line) = lineend_location - start_of_remaining_text;
			start_of_remaining_text = lineend_location;
		}
		if (FS_w_lineX(owq_line)) {
			OWQ_destroy( owq_line ) ;
			return -EINVAL;
		}
		if (start_of_remaining_text >= pointer_after_all_text)
			break;
	}
	OWQ_destroy( owq_line ) ;
	return 0;
}
예제 #3
0
/* Use an single OWQ as a template for the aggregate one */
struct one_wire_query * OWQ_create_aggregate( struct one_wire_query * owq_single )
{
    int sz = sizeof( struct one_wire_query ) + OWQ_DEFAULT_READ_BUFFER_SIZE;
	struct one_wire_query * owq_all = owmalloc( sz );
	
	LEVEL_DEBUG("%s with extension ALL", PN(owq_single)->path);

	if ( owq_all == NO_ONE_WIRE_QUERY) {
		LEVEL_DEBUG("No memory to create object for extension ALL") ;
		return NO_ONE_WIRE_QUERY ;
	}
	
	memset(owq_all, 0, sz);
	OWQ_cleanup(owq_all) = owq_cleanup_owq ;
	
	memcpy( PN(owq_all), PN(owq_single), sizeof(struct parsedname) ) ;
	PN(owq_all)->extension = EXTENSION_ALL ;
	OWQ_buffer(owq_all) = (char *) (& owq_all[1]) ; // point just beyond the one_wire_query struct
	OWQ_size(owq_all) = OWQ_DEFAULT_READ_BUFFER_SIZE ;
	OWQ_offset(owq_all) = 0 ;
	if ( BAD( OWQ_allocate_array(owq_all)) ) {
		OWQ_destroy(owq_all);
		return NO_ONE_WIRE_QUERY ;
	}
	return owq_all ;
}
예제 #4
0
/* Create the Parsename structure and create the buffer */
struct one_wire_query * OWQ_create_from_path(const char *path)
{
	int sz = sizeof( struct one_wire_query ) + OWQ_DEFAULT_READ_BUFFER_SIZE;
	struct one_wire_query * owq = owmalloc( sz );
	
	LEVEL_DEBUG("%s", path);

	if ( owq== NO_ONE_WIRE_QUERY) {
		LEVEL_DEBUG("No memory to create object for path %s",path) ;
		return NO_ONE_WIRE_QUERY ;
	}
	
	memset(owq, 0, sz);
	OWQ_cleanup(owq) = owq_cleanup_owq ;
	
	if ( GOOD( OWQ_parsename(path,owq) ) ) {
		if ( GOOD( OWQ_allocate_array(owq)) ) {
			/*   Add a 1 byte buffer by default. This distinguishes from filesystem calls at end of buffer */
			/*   Read bufer is provided by OWQ_assign_read_buffer or OWQ_allocate_read_buffer */
			OWQ_buffer(owq) = (char *) (& owq[1]) ; // point just beyond the one_wire_query struct
			OWQ_size(owq) = OWQ_DEFAULT_READ_BUFFER_SIZE ;
			return owq ;
		}
		OWQ_destroy(owq);
	}
	return NO_ONE_WIRE_QUERY ;
}
예제 #5
0
파일: ow_read.c 프로젝트: stromnet/owfs
// Handles: ALL
static ZERO_OR_ERROR FS_read_all( struct one_wire_query *owq_all)
{
	struct parsedname * pn = PN(owq_all) ;
	
	// bitfield, convert to .BYTE format and write ( and delete cache ) as BYTE.
	if ( pn->selected_filetype->format == ft_bitfield ) {
		struct one_wire_query * owq_byte = OWQ_create_separate( EXTENSION_BYTE, owq_all ) ;
		int ret = -EINVAL ;

		if ( owq_byte != NO_ONE_WIRE_QUERY ) {
			if ( FS_read_owq( owq_byte ) >= 0 ) {
				size_t elements = pn->selected_filetype->ag->elements;
				size_t extension;
			
				for ( extension=0 ; extension < elements ; ++extension ) {
					OWQ_array_Y(owq_all,extension) = UT_getbit_U( OWQ_U(owq_byte), extension ) ;
				}
				ret = 0 ;
			}
			OWQ_destroy( owq_byte ) ;
		}
		return ret ;
	}
	return FS_read_owq( owq_all ) ;
}
예제 #6
0
/* called when pn->extension==EXTENSION_ALL and pn->selected_filetype->ag->combined==ag_separate */
static ZERO_OR_ERROR FS_read_tester_array(struct one_wire_query *owq)
{
	size_t elements = OWQ_pn(owq).selected_filetype->ag->elements;
	size_t extension;
	size_t entry_length = FileLength(PN(owq));

	for (extension = 0; extension < elements; ++extension) {
		struct one_wire_query * owq_single = OWQ_create_separate( extension, owq ) ;
		if ( owq_single == NO_ONE_WIRE_QUERY ) {
			return -ENOMEM ;
		}
		switch (OWQ_pn(owq).selected_filetype->format) {
		case ft_integer:
		case ft_yesno:
		case ft_bitfield:
		case ft_unsigned:
		case ft_pressure:
		case ft_temperature:
		case ft_tempgap:
		case ft_float:
		case ft_date:
			break;
		case ft_vascii:
		case ft_alias:
		case ft_ascii:
		case ft_binary:
			OWQ_assign_read_buffer(&OWQ_buffer(owq)[extension * entry_length],entry_length,0,owq_single) ;
			break;
		case ft_directory:
		case ft_subdir:
		case ft_unknown:
			OWQ_destroy(owq_single) ;
			return -ENOENT;
		}
		if (FS_read_tester_single(owq_single)) {
			OWQ_destroy(owq_single) ;
			return -EINVAL;
		}
		memcpy(&OWQ_array(owq)[extension], &OWQ_val(owq_single), sizeof(union value_object));
		OWQ_destroy(owq_single) ;
	}
	return 0;
}
예제 #7
0
// Handles: ALL
static ZERO_OR_ERROR FS_write_all_bits( struct one_wire_query *owq_all )
{
	struct one_wire_query * owq_byte = ALLtoBYTE( owq_all ) ;
	ZERO_OR_ERROR z_or_e = -ENOENT ;
	
	if ( owq_byte != NO_ONE_WIRE_QUERY ) {
		z_or_e = FS_write_owq( owq_byte ) ;
		OWQ_destroy( owq_byte ) ;
	}
	return z_or_e ;
}
예제 #8
0
/* Create the Parsename structure and load the relevant fields */
GOOD_OR_BAD OWQ_create(const char *path, struct one_wire_query *owq)
{
	LEVEL_DEBUG("%s", path);

	if ( GOOD( OWQ_parsename(path,owq) ) ) {
		if ( GOOD( OWQ_allocate_array(owq)) ) {
			return gbGOOD ;
		}
		OWQ_destroy(owq);
	}
	return gbBAD ;
}
예제 #9
0
ZERO_OR_ERROR FS_r_sibling_Y(INT *Y, const char * sibling, struct one_wire_query *owq)
{
	struct one_wire_query * owq_sibling  = OWQ_create_sibling( sibling, owq ) ;
	SIZE_OR_ERROR sib_status ;

	if ( owq_sibling == NO_ONE_WIRE_QUERY ) {
		return -EINVAL ;
	}
	sib_status = FS_read_local(owq_sibling) ;
	Y[0] = OWQ_Y(owq_sibling) ;
	OWQ_destroy(owq_sibling) ;
	return sib_status >= 0 ? 0 : -EINVAL ;
}
예제 #10
0
/* Starts with a statically allocated owq space */
GOOD_OR_BAD OWQ_create_plus(const char *path, const char *file, struct one_wire_query *owq)
{
	LEVEL_DEBUG("%s + %s", path, file);

	OWQ_cleanup(owq) = owq_cleanup_none ;
	if ( GOOD( OWQ_parsename_plus(path,file,owq) ) ) {
		if ( GOOD( OWQ_allocate_array(owq)) ) {
			return gbGOOD ;
		}
		OWQ_destroy(owq);
	}
	return gbBAD ;
}
예제 #11
0
ZERO_OR_ERROR FS_w_sibling_Y(INT Y, const char * sibling, struct one_wire_query *owq)
{
	ZERO_OR_ERROR write_error;
	struct one_wire_query * owq_sibling  = OWQ_create_sibling( sibling, owq ) ;

	if ( owq_sibling == NO_ONE_WIRE_QUERY ) {
		return -EINVAL ;
	}
	OWQ_Y(owq_sibling) = Y ;
	write_error = FS_write_local(owq_sibling) ;
	OWQ_destroy(owq_sibling) ;
	return write_error ;
}
예제 #12
0
// Handles: .n
static ZERO_OR_ERROR FS_write_a_bit(struct one_wire_query *owq_bit)
{
	struct one_wire_query * owq_byte = OWQ_create_separate( EXTENSION_BYTE, owq_bit ) ;
	ZERO_OR_ERROR z_or_e = -ENOENT ;
	
	if ( owq_byte != NO_ONE_WIRE_QUERY ) {
		if ( FS_read_local( owq_byte ) >= 0 ) {
			UT_setbit( (BYTE *) &OWQ_U( owq_byte ), OWQ_pn(owq_bit).extension, OWQ_Y(owq_bit) ) ;
			z_or_e = FS_write_owq( owq_byte ) ;
		}
		OWQ_destroy( owq_byte ) ;
	}
	return z_or_e ;
}
예제 #13
0
파일: ow_read.c 프로젝트: stromnet/owfs
// Handles: BYTE
static ZERO_OR_ERROR FS_read_all_bits(struct one_wire_query *owq_byte)
{
	struct one_wire_query * owq_bit = OWQ_create_separate( 0, owq_byte ) ;
	struct parsedname *pn = PN(owq_byte);
	size_t elements = pn->selected_filetype->ag->elements;
	size_t extension;
	
	if ( owq_bit == NO_ONE_WIRE_QUERY ) {
		return -ENOENT ;
	}

	/* Loop through F_r_single, just to get data */
	for (extension = 0; extension < elements; ++extension) {
		OWQ_pn(owq_bit).extension = extension ;
		if ( FS_read_owq(owq_bit) < 0 ) {
			OWQ_destroy(owq_bit);
			return -EINVAL;
		}
		UT_setbit_U( &OWQ_U(owq_byte), extension, OWQ_Y(owq_bit) ) ;
	}

	OWQ_destroy(owq_bit);
	return 0;
}
예제 #14
0
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 ;
}
예제 #15
0
/* return size if ok, else negative */
SIZE_OR_ERROR FS_write(const char *path, const char *buf, const size_t size, const off_t offset)
{
	ZERO_OR_ERROR write_return;
	OWQ_allocate_struct_and_pointer(owq);

	LEVEL_CALL("path=%s size=%d offset=%d", SAFESTRING(path), (int) size, (int) offset);

	// parsable path?
	if ( OWQ_create(path, owq) != 0 ) { // for write
		return -ENOENT;
	}
	OWQ_assign_write_buffer(buf, size, offset, owq) ;
	write_return = FS_write_postparse(owq);
	OWQ_destroy(owq);
	return write_return;		/* here's where the size is used! */
}
예제 #16
0
파일: ow_read.c 프로젝트: stromnet/owfs
SIZE_OR_ERROR FS_read(const char *path, char *buf, const size_t size, const off_t offset)
{
	SIZE_OR_ERROR read_or_error;
	OWQ_allocate_struct_and_pointer(owq);

	LEVEL_CALL("path=%s size=%d offset=%d", SAFESTRING(path), (int) size, (int) offset);
	// Parseable path?
	if ( BAD( OWQ_create(path, owq) ) ) { // for read
		return -ENOENT;
	}
	OWQ_assign_read_buffer( buf, size, offset, owq) ;
	read_or_error = FS_read_postparse(owq);
	OWQ_destroy(owq);

	return read_or_error;
}
예제 #17
0
파일: ow_read.c 프로젝트: stromnet/owfs
/* read a bit from BYTE */
static ZERO_OR_ERROR FS_read_a_bit( struct one_wire_query *owq_bit )
{
	// Bus and device already locked
	struct one_wire_query * owq_byte = OWQ_create_separate( EXTENSION_BYTE, owq_bit ) ;
	struct parsedname *pn = PN(owq_bit);
	ZERO_OR_ERROR z_or_e = -ENOENT ;
	
	if ( owq_byte == NO_ONE_WIRE_QUERY ) {
		return -ENOENT ;
	}

	/* read the UINT */
	if ( FS_read_owq(owq_byte) >= 0) {
		OWQ_Y(owq_bit) = UT_getbit_U( OWQ_U(owq_byte), pn->extension) ;
		z_or_e = 0 ;
	}

	OWQ_destroy(owq_byte);
	return z_or_e;
}
예제 #18
0
// handles: BYTE
static ZERO_OR_ERROR FS_write_as_bits( struct one_wire_query *owq_byte )
{
	struct one_wire_query * owq_bit = OWQ_create_separate( 0, owq_byte ) ;
	size_t elements = OWQ_pn(owq_byte).selected_filetype->ag->elements;
	size_t extension ;
	ZERO_OR_ERROR z_or_e = 0 ;
	
	if ( owq_bit == NO_ONE_WIRE_QUERY ) {
		return -ENOENT ;
	}

	for ( extension = 0 ; extension < elements ; ++extension ) {
		ZERO_OR_ERROR z ;
		OWQ_pn(owq_bit).extension = extension ;
		OWQ_Y(owq_bit) = UT_getbit( (BYTE *) &OWQ_U(owq_byte), extension ) ;
		z = FS_write_owq( owq_bit ) ;
		if ( z != 0 ) {
			z_or_e = z ;
		}
	}
	OWQ_destroy( owq_bit ) ;

	return z_or_e ;
}
예제 #19
0
// Handles .n
static ZERO_OR_ERROR FS_write_a_part( struct one_wire_query *owq_part )
{
	struct parsedname *pn = PN(owq_part);
	size_t extension = pn->extension;
	struct filetype * ft = pn->selected_filetype ;
	ZERO_OR_ERROR z_or_e ;
	struct one_wire_query * owq_all ;
	
	// bitfield
	if ( ft->format == ft_bitfield ) {
		return FS_write_a_bit( owq_part ) ;
	}

	// non-bitfield 
	owq_all = OWQ_create_aggregate( owq_part ) ;
	if ( owq_all == NO_ONE_WIRE_QUERY ) {
		return -ENOENT ;
	}
	
	// First fill the whole array with current values
	if ( FS_read_local( owq_all ) < 0 ) {
		OWQ_destroy( owq_all ) ;
		return -ENOENT ;
	}

	// Copy ascii/binary field
	switch (ft->format) {
	case ft_binary:
	case ft_ascii:
	case ft_vascii:
	case ft_alias:
		{
			size_t extension_index;
			size_t elements = ft->ag->elements;
			char *buffer_pointer = OWQ_buffer(owq_all);
			char *entry_pointer;
			char *target_pointer;

			// All prior elements
			for (extension_index = 0; extension_index < extension; ++extension) {
				// move past their buffer position
				buffer_pointer += OWQ_array_length(owq_all, extension_index);
			}

			entry_pointer = buffer_pointer; // this element's buffer start

			target_pointer = buffer_pointer + OWQ_length(owq_part); // new start next element
			buffer_pointer = buffer_pointer + OWQ_array_length(owq_all, extension); // current start next element

			// move rest of elements to new locations
			for (extension_index = extension + 1; extension_index < elements; ++extension) {
				size_t this_length = OWQ_array_length(owq_all, extension_index);
				memmove(target_pointer, buffer_pointer, this_length);
				target_pointer += this_length;
				buffer_pointer += this_length;
			}

			// now move current element's buffer to location
			memmove(entry_pointer, OWQ_buffer(owq_part), OWQ_length(owq_part));
			OWQ_array_length(owq_all,extension) = OWQ_length(owq_part) ;
		}
		break;
	default:
		// Copy value field
		memcpy(&OWQ_array(owq_all)[pn->extension], &OWQ_val(owq_part), sizeof(union value_object));
		break;
	}

	// Write whole thing out
	z_or_e = FS_write_owq(owq_all);

	OWQ_destroy(owq_all);

	return z_or_e ;
}
예제 #20
0
파일: ow_read.c 프로젝트: stromnet/owfs
// 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;
}
예제 #21
0
파일: ow_get.c 프로젝트: M-o-a-T/owfs
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 ;
}
예제 #22
0
파일: data.c 프로젝트: M-o-a-T/owfs
/*
 * lower level routine for actually handling a request
 * deals with data (ping is handled higher)
 */
void *DataHandler(void *v)
{
	struct handlerdata *hd = v;
	char *retbuffer = NULL;
	struct client_msg cm; // the return message

#if OW_CYGWIN
	/* Random generator seem to need initialization for each new thread
	 * If not, seed will be reset and rand() will return 0 the first call.
	 */
	{
		struct timeval tv;
		gettimeofday(&tv, NULL);
		srand((unsigned int) tv.tv_usec);
	}
#endif

	memset(&cm, 0, sizeof(struct client_msg));
	cm.version = MakeServerprotocol(OWSERVER_PROTOCOL_VERSION);
	cm.control_flags = hd->sm.control_flags;			// default flag return -- includes persistence state

	/* Pre-handling for special testing mode to exclude certain messages */
	switch ((enum msg_classification) hd->sm.type) {
	case msg_dirall:
	case msg_dirallslash:
		if (Globals.no_dirall) {
			LEVEL_DEBUG("DIRALL message rejected.") ;
			hd->sm.type = msg_error;
		}
		break;
	case msg_get:
	case msg_getslash:
		if (Globals.no_get) {
			LEVEL_DEBUG("GET message rejected.") ;
			hd->sm.type = msg_error;
		}
		break;
	default:
		break;
	}

	/* Now Check message types and only parse valid messages */
	switch ((enum msg_classification) hd->sm.type) {	// outer switch
	case msg_read:				// good message
	case msg_write:				// good message
	case msg_dir:				// good message
	case msg_presence:			// good message
	case msg_dirall:			// good message
	case msg_dirallslash:			// good message
	case msg_get:				// good message
	case msg_getslash:			// good message
		if (hd->sm.payload == 0) {	/* Bad query -- no data after header */
			LEVEL_DEBUG("No payload -- ignore.") ;
			cm.ret = -EBADMSG;
		} else {
			struct parsedname *pn;
			OWQ_allocate_struct_and_pointer(owq);
			pn = PN(owq);

			/* Parse the path string and crete  query object */
			LEVEL_CALL("DataHandler: parse path=%s", hd->sp.path);
			cm.ret = BAD( OWQ_create(hd->sp.path, owq) ) ? -1 : 0 ;
			if ( cm.ret != 0 ) {
				LEVEL_DEBUG("DataHandler: OWQ_create failed cm.ret=%d", cm.ret);
				break;
			}

			/* Use client persistent settings (temp scale, display mode ...) */
			pn->control_flags = hd->sm.control_flags;
			/* Override some settings from control flags */
			if ( (pn->control_flags & UNCACHED) != 0 ) {
				// client wants uncached
				pn->state |= ePS_uncached;
			}
			if ( (pn->control_flags & ALIAS_REQUEST) == 0 ) {
				// client wants unaliased
				pn->state |= ePS_unaliased;
			}
			

			/* Antilooping tags */
			pn->tokens = hd->sp.tokens;
			pn->tokenstring = hd->sp.tokenstring;
			//printf("Handler: sm.sg=%X pn.state=%X\n", sm.sg, pn.state);
			//printf("Scale=%s\n", TemperatureScaleName(SGTemperatureScale(sm.sg)));

			switch ((enum msg_classification) hd->sm.type) {
			case msg_presence:
				LEVEL_CALL("Presence message for %s", SAFESTRING(pn->path));
				// Basically, if we were able to ParsedName it's here!
				cm.size = 0;
				retbuffer = owmalloc( SERIAL_NUMBER_SIZE ) ;
				if ( retbuffer ) {
					memcpy( retbuffer, pn->sn, SERIAL_NUMBER_SIZE ) ;
					cm.payload = SERIAL_NUMBER_SIZE ;
				} else {
					cm.payload = 0 ;
				}
				cm.ret = 0;		// good answer
				break;
			case msg_read:
				LEVEL_CALL("Read message");
				retbuffer = ReadHandler(hd, &cm, owq);
				LEVEL_DEBUG("Read message done value=%p", retbuffer);
				break;
			case msg_write:
				LEVEL_CALL("Write message");
				if ( (int) hd->sp.datasize < hd->sm.size ) {
					cm.ret = -EMSGSIZE;
				} else {
					/* set buffer (size already set) */
					OWQ_assign_write_buffer( (ASCII *) hd->sp.data, hd->sm.size, hd->sm.offset, owq) ;
					WriteHandler(hd, &cm, owq);
				}
				break;
			case msg_dir:
				LEVEL_CALL("Directory message (one at a time)");
				DirHandler(hd, &cm, pn);
				break;
			case msg_dirall:
				LEVEL_CALL("Directory message (all at once)");
				retbuffer = DirallHandler(hd, &cm, pn);
				break;
			case msg_dirallslash:
				LEVEL_CALL("Directory message (all at once, with directory /)");
				retbuffer = DirallslashHandler(hd, &cm, pn);
				break;
			case msg_get:
				if (IsDir(pn)) {
					LEVEL_CALL("Get -> Directory message (all at once)");
					retbuffer = DirallHandler(hd, &cm, pn);
				} else {
					LEVEL_CALL("Get -> Read message");
					retbuffer = ReadHandler(hd, &cm, owq);
				}
				break;
			case msg_getslash:
				if (IsDir(pn)) {
					LEVEL_CALL("Get -> Directory message (all at once)");
					retbuffer = DirallslashHandler(hd, &cm, pn);
				} else {
					LEVEL_CALL("Get -> Read message");
					retbuffer = ReadHandler(hd, &cm, owq);
				}
				break;
			default:			// never reached
				LEVEL_CALL("Error: unknown message %d", (int) hd->sm.type);
				break;
			}
			OWQ_destroy(owq);
			LEVEL_DEBUG("DataHandler: FS_ParsedName_destroy done");
		}
		break;
	case msg_nop:				// "bad" message
		LEVEL_CALL("NOP message");
		cm.ret = 0;
		break;
	case msg_size:				// no longer used
	case msg_error:
	default:					// "bad" message
		cm.ret = -ENOMSG;
		LEVEL_CALL("No message");
		break;
	}
	LEVEL_DEBUG("DataHandler: cm.ret=%d", cm.ret);

	TOCLIENTLOCK(hd);
	if (cm.ret != -EIO) {
		ToClient(hd->file_descriptor, &cm, retbuffer);
	} else {
		ErrorToClient(hd, &cm) ;
	}

	// Signal to PingLoop that we're done.
	hd->toclient = toclient_complete ;
	if ( hd->ping_pipe[fd_pipe_write] != FILE_DESCRIPTOR_BAD ) {
		ignore_result = write( hd->ping_pipe[fd_pipe_write],"X",1) ; //dummy payload
	}
	TOCLIENTUNLOCK(hd);

	if (retbuffer) {
		owfree(retbuffer);
	}
	LEVEL_DEBUG("Finished with client request");
	return VOID_RETURN;
}