Пример #1
0
/* Used for virtual directories like settings and statistics
 * If local, applies to all local (this program) and not a
 * specific local bus.
 * If remote, pass it on for the remote to handle
 * */
static enum parse_enum set_type( enum ePN_type epntype, struct parsedname * pn )
{
	if (SpecifiedLocalBus(pn)) {
		return parse_error;
	} else if ( ! SpecifiedRemoteBus(pn) ) {
		pn->type |= ePS_busanylocal;
	}
	pn->type = epntype;
	return parse_nonreal;
}
Пример #2
0
/* We've reached a /bus.n entry */
static enum parse_enum Parse_Bus( INDEX_OR_ERROR bus_number, struct parsedname *pn)
{
	static regex_t rx_p_bus ;
	struct ow_regmatch orm ;
	
	ow_regcomp( &rx_p_bus, "^/bus\\.[[:digit:]]+/?", REG_ICASE ) ;
	orm.number = 0 ;

	/* Processing for bus.X directories -- eventually will make this more generic */
	if ( INDEX_NOT_VALID(bus_number) ) {
		return parse_error;
	}

	/* Should make a presence check on remote buses here, but
	 * it's not a major problem if people use bad paths since
	 * they will just end up with empty directory listings. */
	if (SpecifiedLocalBus(pn)) {	/* already specified a "bus." */
		/* too many levels of bus for a non-remote adapter */
		return parse_error;
	} else if (SpecifiedRemoteBus(pn)) {	/* already specified a "bus." */
		/* Let the remote bus do the heavy lifting */
		pn->state |= ePS_busveryremote;
		return parse_first;
	}

	/* Since we are going to use a specific in-device now, set
	 * pn->selected_connection to point at that device at once. */
	if ( SetKnownBus(bus_number, pn) ) {
		return parse_error ; // bus doesn't exist
	}
	pn->state |= BusIsServer((pn)->selected_connection) ? ePS_busremote : ePS_buslocal ;

	if (SpecifiedLocalBus(pn)) {
		/* don't return bus-list for local paths. */
		pn->control_flags &= (~SHOULD_RETURN_BUS_LIST);
	}

	/* Create the path without the "bus.x" part in pn->path_to_server */
	if ( ow_regexec( &rx_p_bus, pn->path, &orm ) == 0 ) {
		strcpy( pn->path_to_server, orm.pre[0] ) ;
		strcat( pn->path_to_server, "/" ) ;
		strcat( pn->path_to_server, orm.post[0] ) ;
		ow_regexec_free( &orm ) ;
	}
	return parse_first;
}
Пример #3
0
// This function should return number of bytes read... not status.
// Works for all the virtual directories, like statistics, interface, ...
// Doesn't need three-peat and bus was already set or not needed.
static SIZE_OR_ERROR FS_r_virtual(struct one_wire_query *owq)
{
	struct parsedname *pn = PN(owq);
	SIZE_OR_ERROR read_status = 0;

	if (SpecifiedRemoteBus(pn)) {
		/* The bus is not local... use a network connection instead */
		// Read afar -- returns already formatted in buffer
		read_status = ServerRead(owq);
		LEVEL_DEBUG("back from server");
		Debug_OWQ(owq);
	} else {
		/* local bus -- any special locking needs? */
		STAT_ADD1(read_calls);	/* statistics */
		switch (pn->type) {
		case ePN_structure:
			read_status = FS_structure(owq);
			break;
		case ePN_interface:
			BUSLOCK(pn);
			read_status = FS_r_local(owq);	// this returns status
			BUSUNLOCK(pn);
			break;
		case ePN_statistics:
			// reading /statistics/read/tries.ALL
			// will cause a deadlock since it calls STAT_ADD1(read_array);
			// Should perhaps create a new mutex for this.
			// Comment out this STATLOCK until it's solved.
			// STATLOCK now done at time of actual read in ow_stats.c
			read_status = FS_r_local(owq);	// this returns status
			break;
		default:
			read_status = FS_r_local(owq);	// this returns status
		}
		if (read_status >= 0) {
			// local success -- now format in buffer
			read_status = OWQ_parse_output(owq);	// this returns nr. bytes
		}
	}
	LEVEL_DEBUG("return %d", read_status);
	return read_status;
}
Пример #4
0
/* Parse off starting "mode" directory (uncached, alarm...) */
static ZERO_OR_ERROR FS_ParsedName_anywhere(const char *path, enum parse_pass remote_status, struct parsedname *pn)
{
	struct parsedname_pointers s_pp;
	struct parsedname_pointers *pp = &s_pp;
	ZERO_OR_ERROR parse_error_status = 0;
	enum parse_enum pe = parse_first;

	// To make the debug output useful it's cleared here.
	// Even on normal glibc, errno isn't cleared on good system calls
	errno = 0;

	LEVEL_CALL("path=[%s]", SAFESTRING(path));

	RETURN_CODE_ERROR_RETURN( FS_ParsedName_setup(pp, path, pn) );

	if (path == NO_PATH) {
		RETURN_CODE_RETURN( 0 ) ; // success (by default)
	}

	while (1) {
		// Check for extreme conditions (done, error)
		switch (pe) {

		case parse_done:		// the only exit!
			//LEVEL_DEBUG("PARSENAME parse_done") ;
			//printf("PARSENAME end parse_error_status=%d\n",parse_error_status) ;
			if (parse_error_status) {
				FS_ParsedName_destroy(pn);
				return parse_error_status ;
			}

			if ( pp->pathnext != NULL ) {
				// extra text -- make this an error
				RETURN_CODE_SET_SCALAR( parse_error_status, 77 ) ; // extra text in path
				pe = parse_done;
				continue;				
			}
			
			//printf("%s: Parse %s before corrections: %.4X -- state = %d\n",(back_from_remote)?"BACK":"FORE",pn->path,pn->state,pn->type) ;
			// Play with remote levels
			switch ( pn->type ) {
				case ePN_interface:
					// /interface is interesting -- it's actually a property of the calling server
					if ( SpecifiedVeryRemoteBus(pn) ) {
						// veryremote -> remote
						pn->state &= ~ePS_busveryremote ;
					} else if ( SpecifiedRemoteBus(pn) ) {
						// remote -> local
						pn->state &= ~ePS_busremote ;
						pn->state |= ePS_buslocal ;
					}
					break ;
					
				case ePN_root:
					// root buses are considered "real"
					pn->type = ePN_real;	// default state
					break ;
				default:
					// everything else gets promoted so directories aren't added on
					if ( SpecifiedRemoteBus(pn) ) {
						// very remote
						pn->state |= ePS_busveryremote;
					}
					break ;
			}
			//printf("%s: Parse %s after  corrections: %.4X -- state = %d\n\n",(back_from_remote)?"BACK":"FORE",pn->path,pn->state,pn->type) ;
			// set up detail debugging
			Detail_Test( pn ) ; // turns on debug mode only during this device's query
			return 0;

		case parse_error:
			RETURN_CODE_SET_SCALAR( parse_error_status, 27 ) ; // bad path syntax
			pe = parse_done;
			continue;

		default:
			break;
		}

		// break out next name in path
		if ( pp->pathnext == NULL ) {
			// make sure pp->pathnext isn't NULL. (SIGSEGV in uClibc)
			pp->pathnow = NULL ;
		} else {
			pp->pathnow = strsep(&(pp->pathnext), "/") ;
		}
		//LEVEL_DEBUG("PARSENAME pathnow=[%s] rest=[%s]",pp->pathnow,pp->pathnext) ;

		// test next path segment for existence
		if (pp->pathnow == NULL || pp->pathnow[0] == '\0') {
			// done parsing
			pe = parse_done;
		}

		// rest of state machine on parsename
		switch (pe) {

		case parse_done:
			// nothing left to process -- will be handled in next loop pass
			break ;
		
		case parse_first:
			//LEVEL_DEBUG("PARSENAME parse_first") ;
			pe = Parse_Unspecified(pp->pathnow, remote_status, pn);
			break;

		case parse_real:
			//LEVEL_DEBUG("PARSENAME parse_real") ;
			pe = Parse_Real(pp->pathnow, remote_status, pn);
			break;

		case parse_branch:
			//LEVEL_DEBUG("PARSENAME parse_branch") ;
			pe = Parse_Branch(pp->pathnow, remote_status, pn);
			break;

		case parse_nonreal:
			//LEVEL_DEBUG("PARSENAME parse_nonreal\n") ;
			pe = Parse_NonReal(pp->pathnow, pn);
			break;

		case parse_prop:
			//LEVEL_DEBUG("PARSENAME parse_prop") ;
			pn->dirlength = pp->pathnow - pp->pathcpy + 1 ;
			//LEVEL_DEBUG("Dirlength=%d <%*s>",pn->dirlength,pn->dirlength,pn->path) ;
			//printf("dirlength = %d which makes the path <%s> <%.*s>\n",pn->dirlength,pn->path,pn->dirlength,pn->path);
			pp->pathlast = pp->pathnow;	/* Save for concatination if subdirectory later wanted */
			pe = Parse_Property(pp->pathnow, pn);
			break;

		case parse_subprop:
			//LEVEL_DEBUG("PARSENAME parse_subprop") ;
			pp->pathnow[-1] = '/';
			pe = Parse_Property(pp->pathlast, pn);
			break;

		default:
			pe = parse_error;	// unknown state
			break;

		}
		//printf("PARSENAME pe=%d\n",pe) ;
	}
}