/* Put a string ionto the OWQ structure and return the length check lengths and offsets as part of the process */ static SIZE_OR_ERROR OWQ_parse_output_offset_and_size(const char *string, size_t length, struct one_wire_query *owq) { size_t copy_length = length; off_t offset = OWQ_offset(owq); Debug_Bytes("OWQ_parse_output_offset_and_size", (const BYTE *) string, length); /* offset is after the length of the string -- return 0 since some conditions a read after the end is done automatically */ if (offset > (off_t) length) { return 0; } /* correct length for offset (cannot be negative because of previous check) */ copy_length -= offset; /* correct length for buffer space */ if (copy_length > OWQ_size(owq)) { copy_length = OWQ_size(owq); } /* and copy */ memcpy(OWQ_buffer(owq), &string[offset], copy_length); // Warning, this will overwrite the I U or DATA value, // but that shouldn't matter since it's only called on ascii values // and all structure values OWQ_length(owq) = copy_length; return copy_length; }
GOOD_OR_BAD OWQ_allocate_write_buffer( const char * write_buffer, size_t buffer_length, off_t offset, struct one_wire_query * owq ) { char * buffer_copy ; if ( buffer_length == 0 ) { // Buffer size is zero. Allowed, but make it NULL and no cleanup needed. OWQ_size(owq) = 0 ; OWQ_offset(owq) = 0 ; return gbGOOD ; } buffer_copy = owmalloc( buffer_length+1) ; if ( buffer_copy == NULL) { // cannot allocate space for buffer LEVEL_DEBUG("Cannot allocate %ld bytes for buffer", buffer_length) ; OWQ_size(owq) = 0 ; OWQ_offset(owq) = 0 ; return gbBAD ; } memcpy( buffer_copy, write_buffer, buffer_length) ; buffer_copy[buffer_length] = '\0' ; // make sure it's zero-ended OWQ_buffer(owq) = buffer_copy ; OWQ_size(owq) = buffer_length ; OWQ_length(owq) = buffer_length ; OWQ_offset(owq) = offset ; OWQ_cleanup(owq) |= owq_cleanup_buffer ; // buffer needs cleanup return gbGOOD ; }
/* 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; }
static ZERO_OR_ERROR OW_read_external_script( struct sensor_node * sensor_n, struct property_node * property_n, struct one_wire_query * owq ) { char cmd[PATH_MAX+1] ; struct parsedname * pn = PN(owq) ; FILE * script_f ; int snp_return ; ZERO_OR_ERROR zoe ; // load the command script and arguments if ( pn->sparse_name == NULL ) { // not a text sparse name snp_return = snprintf( cmd, PATH_MAX+1, "%s %s %s %d %s %d %d %s %s", property_n->read, // command sensor_n->name, // sensor name property_n->property, // property, pn->extension, // extension "read", // mode (int) OWQ_size(owq), // size (int) OWQ_offset(owq), // offset sensor_n->data, // sensor-specific data property_n->data // property-specific data ) ; } else { snp_return = snprintf( cmd, PATH_MAX+1, "%s %s %s %s %s %d %d %s %s", property_n->read, // command sensor_n->name, // sensor name property_n->property, // property, pn->sparse_name, // extension "read", // mode (int) OWQ_size(owq), // size (int) OWQ_offset(owq), // offset sensor_n->data, // sensor-specific data property_n->data // property-specific data ) ; } if ( snp_return < 0 ) { LEVEL_DEBUG("Problem creating script string for %s/%s",sensor_n->name,property_n->property) ; return -EINVAL ; } script_f = popen( cmd, "r" ) ; if ( script_f == NULL ) { ERROR_DEBUG("Cannot create external program link for reading %s/%s",sensor_n->name,property_n->property); return -EIO ; } zoe = OW_script_read( script_f, owq ) ; fclose( script_f ) ; return zoe ; }
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; }
void _print_owq(struct one_wire_query *owq) { char c[32]; fprintf(stderr,"OWQ OneWireQuery structure of %s\n", PN(owq)->path); fprintf(stderr," OneWireQuery size=%lu offset=%lu, extension=%d\n", (unsigned long) OWQ_size(owq), (unsigned long) OWQ_offset(owq), (int) OWQ_pn(owq).extension); if ( OWQ_buffer(owq) != NULL ) { Debug_Bytes("OneWireQuery buffer", (BYTE *) OWQ_buffer(owq), OWQ_size(owq)); } fprintf(stderr," Cleanup = %.4X",OWQ_cleanup(owq)); fprintf(stderr," OneWireQuery I=%d U=%u F=%G Y=%d D=%s\n", OWQ_I(owq), OWQ_U(owq), OWQ_F(owq), OWQ_Y(owq), SAFESTRING(ctime_r(&OWQ_D(owq), c))); fprintf(stderr,"--- OneWireQuery done\n"); }
static ZERO_OR_ERROR OW_script_read( FILE * script_f, struct one_wire_query * owq ) { size_t fr_return ; memset( OWQ_buffer(owq), 0, OWQ_size(owq) ) ; fr_return = fread( OWQ_buffer(owq), OWQ_size(owq), 1, script_f ) ; if ( fr_return == 0 && ferror(script_f) != 0 ) { LEVEL_DEBUG( "Could not read script data back for %s",PN(owq)->path ) ; return -EIO ; } return OWQ_parse_input( owq ) ; }
/* 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 ; }
/* 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 ; }
void OWQ_create_temporary(struct one_wire_query *owq_temporary, char *buffer, size_t size, off_t offset, struct parsedname *pn) { OWQ_buffer(owq_temporary) = buffer; OWQ_size(owq_temporary) = size; OWQ_offset(owq_temporary) = offset; memcpy(PN(owq_temporary), pn, sizeof(struct parsedname)); }
static ZERO_OR_ERROR FS_w_TS(struct one_wire_query *owq) { ZERO_OR_ERROR ret = 0; if (OWQ_size(owq) == 0 || OWQ_offset(owq) > 0) { return 0; /* do nothing */ } switch (OWQ_buffer(owq)[0]) { case 'C': case 'c': Globals.temp_scale = temp_celsius ; break; case 'F': case 'f': Globals.temp_scale = temp_fahrenheit ; break; case 'R': case 'r': Globals.temp_scale = temp_rankine ; break; case 'K': case 'k': Globals.temp_scale = temp_kelvin ; break; default: ret = -EINVAL; } SetLocalControlFlags() ; return ret; }
static SIZE_OR_ERROR OWQ_parse_output_yesno(struct one_wire_query *owq) { if (OWQ_size(owq) < PROPERTY_LENGTH_YESNO) { return -EMSGSIZE; } OWQ_buffer(owq)[0] = ((OWQ_Y(owq) & 0x1) == 0) ? '0' : '1'; return ShouldTrim(PN(owq))? 1 : PROPERTY_LENGTH_YESNO; }
// print from current position static ZERO_OR_ERROR FS_Hscreen(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); // y=0 is flag to do no position setting struct yx YX = { LCD_SAME_LOCATION_VALUE, LCD_SAME_LOCATION_VALUE, OWQ_buffer(owq), OWQ_size(owq), 0 } ; RETURN_ERROR_IF_BAD( OW_Hinit(pn) ) ; return GB_to_Z_OR_E( OW_Hprintyx(&YX, pn) ); }
// Standard Data via GET void ChangeData(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); ASCII *value_string = OWQ_buffer(owq); /* Do command processing and make changes to 1-wire devices */ LEVEL_DETAIL("New data path=%s value=%s", pn->path, value_string); switch (pn->selected_filetype->format) { case ft_binary: hex_only(value_string); OWQ_size(owq) = hex_convert(value_string); break; default: OWQ_size(owq) = strlen(value_string); break; } FS_write_postparse(owq); }
// print from specified positionh -- // either in ascii format "y.x:text" or "x:text" // or binary (first 2 bytes are y and x) static ZERO_OR_ERROR FS_Hscreenyx(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); struct yx YX = { 0, 0, OWQ_buffer(owq), OWQ_size(owq), 0 } ; RETURN_ERROR_IF_BAD( Parseyx( &YX ) ) ; RETURN_ERROR_IF_BAD( OW_Hinit(pn) ) ; return GB_to_Z_OR_E( OW_Hprintyx(&YX, pn) ); }
static ZERO_OR_ERROR FS_r_name(struct one_wire_query *owq) { BYTE buf[256]; size_t len = OWQ_size(owq); RETURN_ERROR_IF_BAD( OW_r_std(buf,&len, M_CONFIG, CFG_NAME, PN(owq))); return OWQ_format_output_offset_and_size((const char *)buf, len, owq); }
static SIZE_OR_ERROR OWQ_parse_output_date(struct one_wire_query *owq) { char c[PROPERTY_LENGTH_DATE + 2]; if (OWQ_size(owq) < PROPERTY_LENGTH_DATE) { return -EMSGSIZE; } ctime_r(&OWQ_D(owq), c); return OWQ_parse_output_offset_and_size(c, PROPERTY_LENGTH_DATE, owq); }
static ZERO_OR_ERROR FS_r_ports_raw(struct one_wire_query *owq) { BYTE buf[10]; size_t len = OWQ_size(owq); if(len>sizeof(buf)) len=sizeof(buf); RETURN_ERROR_IF_BAD( OW_r_std(buf,&len, M_PORT, 0, PN(owq))); return OWQ_format_output_offset_and_size((const char *)buf, len, owq); }
static ZERO_OR_ERROR FS_r_info_raw(struct one_wire_query *owq) { BYTE buf[256]; size_t len = OWQ_size(owq); if(len>sizeof(buf)) len=sizeof(buf); RETURN_ERROR_IF_BAD( OW_r_std(buf,&len, M_CONFIG, OWQ_pn(owq).extension, PN(owq))); return OWQ_format_output_offset_and_size((const char *)buf, len, owq); }
/* If offset is too large, size is set to 0 */ static void adjust_file_size(struct one_wire_query *owq) { size_t file_length = 0; /* Adjust file length -- especially important for fuse which uses 4k buffers */ /* First file filelength */ file_length = FullFileLength(PN(owq)); /* next adjust for offset */ if ((unsigned long) OWQ_offset(owq) >= (unsigned long) file_length) { // This check is done in OWQ_parse_output() too, since it's always called when this function OWQ_size(owq) = 0 ; // this is status ok... but 0 bytes were read... } else if ( OWQ_size(owq) + OWQ_offset(owq) > file_length ) { // Finally adjust buffer length OWQ_size(owq) = file_length - OWQ_offset(owq) ; } LEVEL_DEBUG("file_length=%lu offset=%lu size=%lu", (unsigned long) file_length, (unsigned long) OWQ_offset(owq), (unsigned long) OWQ_size(owq)); }
// Print from home position static ZERO_OR_ERROR FS_Hmessage(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); struct yx YX = { 1, 1, OWQ_buffer(owq), OWQ_size(owq), 0 } ; RETURN_ERROR_IF_BAD( OW_Hinit(pn) ) ; if (FS_Hclear(owq) != 0) { return -EINVAL; } return GB_to_Z_OR_E( OW_Hprintyx(&YX, pn) ); }
/* return size if ok, else negative */ SIZE_OR_ERROR FS_write_postparse(struct one_wire_query *owq) { ZERO_OR_ERROR write_or_error; struct parsedname *pn = PN(owq); if (Globals.readonly) { LEVEL_DEBUG("Attempt to write but readonly set on command line."); return -EROFS; // read-only invokation } if (IsDir(pn)) { LEVEL_DEBUG("Attempt to write to a directory."); return -EISDIR; // not a file } STATLOCK; AVERAGE_IN(&write_avg); AVERAGE_IN(&all_avg); ++write_calls; /* statistics */ STATUNLOCK; write_or_error = FS_write_post_stats( owq ) ; STATLOCK; // write_or_error is still ZERO_OR_ERROR mode if ( write_or_error == 0 ) { LEVEL_DEBUG("Successful write to %s",pn->path) ; } else { LEVEL_DEBUG("Error writing to %s",pn->path) ; } if (write_or_error == 0) { ++write_success; /* statistics */ write_bytes += OWQ_size(owq); /* statistics */ // write_or_error now SIZE_OR_ERROR mode write_or_error = OWQ_size(owq); /* here's where the size is used! */ } AVERAGE_OUT(&write_avg); AVERAGE_OUT(&all_avg); STATUNLOCK; return write_or_error; }
static ZERO_OR_ERROR FS_redefchar(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); if ( OWQ_size(owq) != LCD_REDEFCHAR_LENGTH ) { return -ERANGE ; } if ( OWQ_offset(owq) != 0 ) { return -ERANGE ; } return GB_to_Z_OR_E( OW_redefchar( OWQ_buffer(owq), pn ) ) ; }
static void Set_OWQ_length(struct one_wire_query *owq) { switch (OWQ_pn(owq).selected_filetype->format) { case ft_binary: case ft_ascii: case ft_vascii: case ft_alias: OWQ_length(owq) = OWQ_size(owq); break; default: break; } }
static SIZE_OR_ERROR OWQ_parse_output_array_with_commas(struct one_wire_query *owq) { struct one_wire_query owq_single; size_t extension; int len; size_t used_size = 0; size_t remaining_size = OWQ_size(owq); size_t elements = OWQ_pn(owq).selected_filetype->ag->elements; // loop though all array elements for (extension = 0; extension < elements; ++extension) { //printf("OWQ_parse_output_array_with_commas element=%d, size_used=%d, remaining=%d\n",(int)extension,(int)used_size,(int)remaining_size) ; // Prepare a copy of owq that only points to a single element memcpy(&owq_single, owq, sizeof(owq_single)); OWQ_pn(&owq_single).extension = extension; memcpy(&OWQ_val(&owq_single), &OWQ_array(owq)[extension], sizeof(union value_object)); // add the comma first (if not the first element and enough room) if (used_size > 0) { if (remaining_size == 0) { return -EFAULT; } OWQ_buffer(owq)[used_size] = ','; ++used_size; --remaining_size; } // Now process the single element OWQ_buffer(&owq_single) = &OWQ_buffer(owq)[used_size]; OWQ_size(&owq_single) = remaining_size; len = OWQ_parse_output(&owq_single); // any error aborts if (len < 0) { return len; } remaining_size -= len; used_size += len; } return used_size; }
static ZERO_OR_ERROR FS_w_port_raw(struct one_wire_query *owq) { BYTE *buf = (BYTE *) OWQ_buffer(owq); size_t len = OWQ_size(owq); if (OWQ_offset(owq) != 0) return -EINVAL; /* ignore? */ // Hack for testing, otherwise we'll not be able to clear a port using owwrite. if(len == 1 && (*buf == '0' || *buf == '1')) { *buf -= '0'; } return GB_to_Z_OR_E( OW_w_std( buf,len, M_PORT,OWQ_pn(owq).extension, PN(owq)) ) ; }
/* No CRC -- 0xF0 code */ GOOD_OR_BAD COMMON_read_memory_F0(struct one_wire_query *owq, size_t page, size_t pagesize) { off_t offset = OWQ_offset(owq) + page * pagesize; BYTE p[3] = { _1W_READ_F0, LOW_HIGH_ADDRESS(offset), }; struct transaction_log t[] = { TRXN_START, TRXN_WRITE3(p), TRXN_READ((BYTE *) OWQ_buffer(owq), OWQ_size(owq)), TRXN_END, }; Set_OWQ_length(owq); return BUS_transaction(t, PN(owq)); }
void OWQ_assign_write_buffer(const char *buffer, size_t size, off_t offset, struct one_wire_query *owq) { // OWQ_buffer used for both read (non-const) and write (const) #if ( __GNUC__ > 4 ) || (__GNUC__ == 4 && __GNUC_MINOR__ > 4 ) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" OWQ_buffer(owq) = (char *) buffer; #pragma GCC diagnostic pop #else OWQ_buffer(owq) = (char *) buffer; #endif OWQ_size(owq) = size; OWQ_offset(owq) = offset; }
static ZERO_OR_ERROR FS_Mscreen(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); size_t size = OWQ_size(owq); BYTE data[size]; size_t i; for (i = 0; i < size; ++i) { // no upper ascii chars if (OWQ_buffer(owq)[i] & 0x80) { return -EINVAL; } data[i] = OWQ_buffer(owq)[i] | 0x80; } return GB_to_Z_OR_E( OW_w_pios(data, size, pn) ) ; }
static ZERO_OR_ERROR FS_redefchar_hex(struct one_wire_query *owq) { struct parsedname *pn = PN(owq); BYTE data[LCD_REDEFCHAR_LENGTH] ; if ( OWQ_size(owq) != LCD_REDEFCHAR_LENGTH * 2 ) { return -ERANGE ; } if ( OWQ_offset(owq) != 0 ) { return -ERANGE ; } string2bytes( OWQ_buffer(owq), data, LCD_REDEFCHAR_LENGTH ) ; return GB_to_Z_OR_E( OW_redefchar( OWQ_buffer(owq), pn ) ) ; }