예제 #1
0
파일: filter.cpp 프로젝트: Erethon/sysdig
void sinsp_filter::parse_check(sinsp_filter_expression* parent_expr, boolop op)
{
    uint32_t startpos = m_scanpos;
    vector<char> operand1 = next_operand(true);
    string str_operand1 = string((char *)&operand1[0]);
    sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(str_operand1, m_inspector, true);

    if(chk == NULL)
    {
        throw sinsp_exception("filter error: unrecognized field " +
                              str_operand1 + " at pos " + to_string((long long) startpos));
    }

    if(m_ttable_only)
    {
        if(!(chk->get_fields()->m_flags & filter_check_info::FL_WORKS_ON_THREAD_TABLE))
        {
            throw sinsp_exception("the given filter is not supported for thread table filtering");
        }
    }

    ppm_cmp_operator co = next_comparison_operator();
    vector<char> operand2 = next_operand(false);

    chk->m_boolop = op;
    chk->m_cmpop = co;
    chk->parse_field_name((char *)&operand1[0]);
    chk->parse_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1);

    parent_expr->add_check(chk);
}
예제 #2
0
파일: chisel.cpp 프로젝트: SpiderX/sysdig
	static int request_field(lua_State *ls) 
	{
		lua_getglobal(ls, "sichisel");

		sinsp_chisel* ch = (sinsp_chisel*)lua_touserdata(ls, -1);
		lua_pop(ls, 1);

		sinsp* inspector = ch->m_inspector;

		const char* fld = lua_tostring(ls, 1); 

		if(fld == NULL)
		{
			throw sinsp_exception("chisel requesting nil field");
		}

		sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(fld,
			inspector, 
			false);

		if(chk == NULL)
		{
			throw sinsp_exception("chisel requesting nonexistent field " + string(fld));
		}

		chk->parse_field_name(fld);

		lua_pushlightuserdata(ls, chk);

		ch->m_allocated_fltchecks.push_back(chk);

		return 1;
	}
예제 #3
0
파일: filter.cpp 프로젝트: Blevene/sysdig
void sinsp_filter::parse_check(sinsp_filter_expression* parent_expr, boolop op)
{
	uint32_t startpos = m_scanpos;
	string operand1 = next_operand(true);
	sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(operand1, m_inspector, true);

	if(chk == NULL)
	{
		throw sinsp_exception("filter error: unrecognized field " + 
			operand1 + " at pos " + to_string((long long) startpos));
	}

	ppm_cmp_operator co = next_comparison_operator();
	string operand2 = next_operand(false);

	chk->m_boolop = op;
	chk->m_cmpop = co;
	chk->parse_field_name(operand1.c_str());
	chk->parse_filter_value(operand2.c_str());

	parent_expr->add_check(chk);
}
예제 #4
0
파일: table.cpp 프로젝트: James-Dao/sysdig
void sinsp_table::configure(vector<sinsp_view_column_info>* entries, const string& filter, 
	bool use_defaults, uint32_t view_depth)
{
	m_use_defaults = use_defaults;
	m_view_depth = view_depth;

	//
	// If this is a list table, increase the refresh time to improve realtimyiness
	//
	if(m_type == sinsp_table::TT_LIST)
	{
		set_refresh_interval(200000000);
	}

	//////////////////////////////////////////////////////////////////////////////////////
	// If a filter has been spefied, compile it
	//////////////////////////////////////////////////////////////////////////////////////
	if(filter != "")
	{
		sinsp_filter_compiler compiler(m_inspector, filter);
		m_filter = compiler.compile();
	}

	//////////////////////////////////////////////////////////////////////////////////////
	// Extract the tokens
	//////////////////////////////////////////////////////////////////////////////////////
	m_premerge_extractors.clear();

	for(auto vit : *entries)
	{
		sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(vit.get_field(m_view_depth), 
			m_inspector,
			false);

		if(chk == NULL)
		{
			throw sinsp_exception("invalid field name " + vit.get_field(m_view_depth));
		}

		chk->m_aggregation = (sinsp_field_aggregation)vit.m_aggregation;
		m_chks_to_free.push_back(chk);

		chk->parse_field_name(vit.get_field(m_view_depth).c_str(), true);

		if((vit.m_flags & TEF_IS_KEY) != 0)
		{
			if(m_is_key_present)
			{
				throw sinsp_exception("invalid table configuration: multiple keys specified");
			}

			m_premerge_extractors.insert(m_premerge_extractors.begin(), chk);
			m_is_key_present = true;
		}
		else
		{
			m_premerge_extractors.push_back(chk);
		}
	}

	if(m_type == sinsp_table::TT_TABLE)
	{
		//
		// Make sure this is a valid table
		//
		if(!m_is_key_present)
		{
			throw sinsp_exception("table is missing the key");
		}
	}
	else
	{
		sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname("util.cnt", 
			m_inspector,
			false);

		if(chk == NULL)
		{
			throw sinsp_exception("internal table error");
		}

		chk->m_aggregation = A_NONE;
		m_chks_to_free.push_back(chk);

		chk->parse_field_name("util.cnt", true);

		if(m_is_key_present)
		{
			throw sinsp_exception("list table can't have a key");
		}

		m_premerge_extractors.insert(m_premerge_extractors.begin(), chk);
		m_is_key_present = true;
	}

	m_premerge_fld_pointers = new sinsp_table_field[m_premerge_extractors.size()];
	m_fld_pointers = m_premerge_fld_pointers;
	m_n_premerge_fields = (uint32_t)m_premerge_extractors.size();
	m_n_fields = m_n_premerge_fields;

	if(m_n_fields < 2)
	{
		throw sinsp_exception("table has no values");
	}

	for(auto it = m_premerge_extractors.begin(); it != m_premerge_extractors.end(); ++it)
	{
		m_premerge_types.push_back((*it)->get_field_info()->m_type);
		m_premerge_legend.push_back(*(*it)->get_field_info());
	}

	m_premerge_vals_array_sz = (m_n_fields - 1) * sizeof(sinsp_table_field);
	m_vals_array_sz = m_premerge_vals_array_sz;

	//////////////////////////////////////////////////////////////////////////////////////
	// If a merge has been specified, configure it 
	//////////////////////////////////////////////////////////////////////////////////////
	uint32_t n_gby_keys = 0;

	for(auto vit : *entries)
	{
		if((vit.m_flags & TEF_IS_GROUPBY_KEY) != 0)
		{
			n_gby_keys++;
		}
	}

	if(n_gby_keys == 0)
	{
		//
		// No merge string. We can stop here
		//
		m_do_merging = false;
		return;
	}
	else if(n_gby_keys > 1)
	{
		throw sinsp_exception("invalid table definition: multiple groupby keys");
	}

	//
	// Merging not supported for lists
	//
	if(m_type != sinsp_table::TT_TABLE)
	{
		throw sinsp_exception("group by not supported for list tables");
	}

	m_do_merging = true;

	for(uint32_t j = 0; j < entries->size(); j++)
	{
		auto vit = entries->at(j);

		//
		// Skip original key when grouping
		//
		if((vit.m_flags & TEF_IS_KEY) != 0)
		{
			continue;
		}


		sinsp_filter_check* chk = m_premerge_extractors[j];

		chk->m_merge_aggregation = (sinsp_field_aggregation)vit.m_groupby_aggregation;

		if((vit.m_flags & TEF_IS_GROUPBY_KEY) != 0)
		{
			if(m_is_groupby_key_present)
			{
				throw sinsp_exception("invalid table configuration: more than one groupby key specified");
			}

			m_is_groupby_key_present = true;
			m_postmerge_extractors.insert(m_postmerge_extractors.begin(), chk);
			m_groupby_columns.insert(m_groupby_columns.begin(), j);
		}
		else
		{
			m_postmerge_extractors.push_back(chk);
			m_groupby_columns.push_back(j);
		}
	}

	m_postmerge_fld_pointers = new sinsp_table_field[m_postmerge_extractors.size()];
	m_n_postmerge_fields = (uint32_t)m_postmerge_extractors.size();

	if(!m_is_groupby_key_present)
	{
		throw sinsp_exception("table is missing the groupby key");
	}

	if(m_groupby_columns.size() < 2)
	{
		throw sinsp_exception("groupby table has no values");
	}

	for(auto it = m_postmerge_extractors.begin(); it != m_postmerge_extractors.end(); ++it)
	{
		m_postmerge_types.push_back((*it)->get_field_info()->m_type);
		m_postmerge_legend.push_back(*(*it)->get_field_info());
	}

	m_postmerge_vals_array_sz = (m_n_postmerge_fields - 1) * sizeof(sinsp_table_field);
}
예제 #5
0
파일: filter.cpp 프로젝트: djc2k/sysdig
void sinsp_filter_compiler::parse_check()
{
	uint32_t startpos = m_scanpos;
	vector<char> operand1 = next_operand(true, false);
	string str_operand1 = string((char *)&operand1[0]);
	sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(str_operand1, m_inspector, true);
	boolop op = m_last_boolop;

	if(chk == NULL)
	{
		throw sinsp_exception("filter error: unrecognized field " +
			str_operand1 + " at pos " + to_string((long long) startpos));
	}

	if(m_ttable_only)
	{
		if(!(chk->get_fields()->m_flags & filter_check_info::FL_WORKS_ON_THREAD_TABLE))
		{
			throw sinsp_exception("the given filter is not supported for thread table filtering");
		}
	}

	cmpop co = next_comparison_operator();

	chk->m_boolop = op;
	chk->m_cmpop = co;

	chk->parse_field_name((char *)&operand1[0], true);

	if(co == CO_IN || co == CO_PMATCH)
	{
		//
		// Skip spaces
		//
		if(isblank(m_fltstr[m_scanpos]))
		{
			next();
		}

		if(m_fltstr[m_scanpos] != '(')
		{
			throw sinsp_exception("expected '(' after 'in/pmatch' operand");
		}

		//
		// Skip '('
		//
		m_scanpos++;

		if(chk->get_field_info()->m_type == PT_CHARBUF)
		{
			//
			// For character buffers, we can check all
			// values at once by putting them in a set and
			// checking for set membership.
			//

			//
			// Create the 'or' sequence
			//
			uint64_t num_values = 0;
			while(true)
			{
				// 'in' clause aware
				vector<char> operand2 = next_operand(false, true);

				chk->add_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1, num_values);
				num_values++;
				next();

				if(m_fltstr[m_scanpos] == ')')
				{
					break;
				}
				else if(m_fltstr[m_scanpos] == ',')
				{
					m_scanpos++;
				}
				else
				{
					throw sinsp_exception("expected either ')' or ',' after a value inside the 'in/pmatch' clause");
				}
			}
			m_filter->add_check(chk);
		}
		else if (co == CO_PMATCH)
		{
			// the pmatch operator can only work on charbufs
			throw sinsp_exception("pmatch requires all charbuf arguments");
		}
		else
		{
			//
			// In this case we need to create '(field=value1 or field=value2 ...)'
			//

			//
			// Separate the 'or's from the
			// rest of the conditions
			//
			m_filter->push_expression(op);
			m_last_boolop = BO_NONE;
			m_nest_level++;

			//
			// The first boolean operand will be BO_NONE
			// Then we will start putting BO_ORs
			//
			op = BO_NONE;

			//
			// Create the 'or' sequence
			//
			uint64_t num_values = 0;
			while(true)
			{
				// 'in' clause aware
				vector<char> operand2 = next_operand(false, true);

				//
				// Append every sinsp_filter_check creating the 'or' sequence
				//
				sinsp_filter_check* newchk = g_filterlist.new_filter_check_from_another(chk);
				newchk->m_boolop = op;
				newchk->m_cmpop = CO_EQ;
				newchk->add_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1, num_values);
				num_values++;

				m_filter->add_check(newchk);

				next();

				if(m_fltstr[m_scanpos] == ')')
				{
					break;
				}
				else if(m_fltstr[m_scanpos] == ',')
				{
					m_scanpos++;
				}
				else
				{
					throw sinsp_exception("expected either ')' or ',' after a value inside the 'in' clause");
				}

				//
				// From now on we 'or' every newchk
				//
				op = BO_OR;
			}

			//
			// Come back to the rest of the filter
			//
			m_filter->pop_expression();
			m_nest_level--;
		}
	}
	else
	{
		//
		// In this case we want next() to return the very next character
		// At this moment m_scanpos is already at it
		// e.g. "(field exists) and ..."
		//
		if(co == CO_EXISTS)
		{
			m_scanpos--;
		}
		//
		// Otherwise we need a value for the operand
		//
		else
		{
			vector<char> operand2 = next_operand(false, false);
			chk->add_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1);
		}

		m_filter->add_check(chk);
	}
}
예제 #6
0
void sinsp_evt_formatter::set_format(const string& fmt)
{
	uint32_t j;
	uint32_t last_nontoken_str_start = 0;
	string lfmt(fmt);

	if(lfmt == "")
	{
		throw sinsp_exception("empty formatting token");
	}

	//
	// If the string starts with a *, it means that we are ok with printing
	// the string even when not all the values it specifies are set.
	//
	if(lfmt[0] == '*')
	{
		m_require_all_values = false;
		lfmt.erase(0, 1);
	}
	else
	{
		m_require_all_values = true;
	}

	//
	// Parse the string and extract the tokens
	//
	const char* cfmt = lfmt.c_str();

	m_tokens.clear();

	for(j = 0; j < lfmt.length(); j++)
	{
		if(cfmt[j] == '%')
		{
			if(last_nontoken_str_start != j)
			{
				rawstring_check* newtkn = new rawstring_check(lfmt.substr(last_nontoken_str_start, j - last_nontoken_str_start));
				m_tokens.push_back(newtkn);
				m_chks_to_free.push_back(newtkn);
			}

			sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(string(cfmt + j + 1), 
				m_inspector, 
				false);

			if(chk == NULL)
			{
				throw sinsp_exception("invalid formatting token " + string(cfmt + j + 1));
			}

			m_chks_to_free.push_back(chk);

			j += chk->parse_field_name(cfmt + j + 1);
			ASSERT(j <= lfmt.length());

			m_tokens.push_back(chk);

			last_nontoken_str_start = j + 1;
		}
	}

	if(last_nontoken_str_start != j)
	{
		m_tokens.push_back(new rawstring_check(lfmt.substr(last_nontoken_str_start, j - last_nontoken_str_start)));
	}
}
예제 #7
0
void sinsp_evt_formatter::set_format(const string& fmt)
{
	uint32_t j;
	uint32_t last_nontoken_str_start = 0;
	string lfmt(fmt);

	if(lfmt == "")
	{
		throw sinsp_exception("empty formatting token");
	}

	//
	// If the string starts with a *, it means that we are ok with printing
	// the string even when not all the values it specifies are set.
	//
	if(lfmt[0] == '*')
	{
		m_require_all_values = false;
		lfmt.erase(0, 1);
	}
	else
	{
		m_require_all_values = true;
	}

	//
	// Parse the string and extract the tokens
	//
	const char* cfmt = lfmt.c_str();

	m_tokens.clear();
	uint32_t lfmtlen = lfmt.length();

	for(j = 0; j < lfmtlen; j++)
	{
		if(cfmt[j] == '%')
		{
			int toklen = 0;

			if(last_nontoken_str_start != j)
			{
				rawstring_check* newtkn = new rawstring_check(lfmt.substr(last_nontoken_str_start, j - last_nontoken_str_start));
				m_tokens.push_back(newtkn);
				m_tokenlens.push_back(0);
				m_chks_to_free.push_back(newtkn);
			}

			if(j == lfmtlen - 1)
			{
				throw sinsp_exception("invalid formatting syntax: formatting cannot end with a %");
			}

			//
			// If the field specifier starts with a number, it means that we have a length modifier
			//
			if(isdigit(cfmt[j + 1]))
			{
				//
				// Parse the token length
				//
				sscanf(cfmt+ j + 1, "%d", &toklen);

				//
				// Advance until the beginning of the field name
				//
				while(true)
				{
					if(j == lfmtlen - 1)
					{
						throw sinsp_exception("invalid formatting syntax: formatting cannot end with a number");
					}
					else if(isdigit(cfmt[j + 1]))
					{
						j++;
						continue;
					}
					else
					{
						break;
					}
				}
			}

			sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(string(cfmt + j + 1), 
				m_inspector, 
				false);

			if(chk == NULL)
			{
				throw sinsp_exception("invalid formatting token " + string(cfmt + j + 1));
			}

			m_chks_to_free.push_back(chk);

			j += chk->parse_field_name(cfmt + j + 1);
			ASSERT(j <= lfmt.length());

			m_tokens.push_back(chk);
			m_tokenlens.push_back(toklen);

			last_nontoken_str_start = j + 1;
		}
	}

	if(last_nontoken_str_start != j)
	{
		m_tokens.push_back(new rawstring_check(lfmt.substr(last_nontoken_str_start, j - last_nontoken_str_start)));
		m_tokenlens.push_back(0);
	}
}
예제 #8
0
파일: filter.cpp 프로젝트: diagprov/sysdig
void sinsp_filter::parse_check(sinsp_filter_expression* parent_expr, boolop op)
{
	uint32_t startpos = m_scanpos;
	vector<char> operand1 = next_operand(true, false);
	string str_operand1 = string((char *)&operand1[0]);
	sinsp_filter_check* chk = g_filterlist.new_filter_check_from_fldname(str_operand1, m_inspector, true);

	if(chk == NULL)
	{
		throw sinsp_exception("filter error: unrecognized field " +
			str_operand1 + " at pos " + to_string((long long) startpos));
	}

	if(m_ttable_only)
	{
		if(!(chk->get_fields()->m_flags & filter_check_info::FL_WORKS_ON_THREAD_TABLE))
		{
			throw sinsp_exception("the given filter is not supported for thread table filtering");
		}
	}

	ppm_cmp_operator co = next_comparison_operator();

	chk->m_boolop = op;
	chk->m_cmpop = co;

	chk->parse_field_name((char *)&operand1[0], true);

	//
	// In this case we need to create '(field=value1 or field=value2 ...)'
	//
	if(co == CO_IN)
	{
		//
		// Separate the 'or's from the
		// rest of the conditions
		//
		push_expression(op);

		//
		// Skip spaces
		//
		if(isblank(m_fltstr[m_scanpos]))
		{
			next();
		}

		if(m_fltstr[m_scanpos] != '(')
		{
			throw sinsp_exception("expected '(' after 'in' operand");
		}

		//
		// Skip '('
		//
		m_scanpos++;

		//
		// The first boolean operand will be BO_NONE
		// Then we will start putting BO_ORs
		//
		op = BO_NONE;

		//
		// Create the 'or' sequence
		//
		while(true)
		{
			// 'in' clause aware
			vector<char> operand2 = next_operand(false, true);

			//
			// Append every sinsp_filter_check creating the 'or' sequence
			//
			sinsp_filter_check* newchk = g_filterlist.new_filter_check_from_another(chk);
			newchk->m_boolop = op;
			newchk->m_cmpop = CO_EQ;
			newchk->parse_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1);

			//
			// We pushed another expression before
			// so 'parent_expr' still referers to
			// the old one, this is the new nested
			// level for the 'or' sequence
			//
			m_curexpr->add_check(newchk);

			next();

			if(m_fltstr[m_scanpos] == ')')
			{
				break;
			}
			else if(m_fltstr[m_scanpos] == ',')
			{
				m_scanpos++;
			}
			else
			{
				throw sinsp_exception("expected either ')' or ',' after a value inside the 'in' clause");
			}

			//
			// From now on we 'or' every newchk
			//
			op = BO_OR;
		}

		//
		// Come back to the rest of the filter
		//
		pop_expression();
	}
	else
	{
		//
		// In this case we want next() to return the very next character
		// At this moment m_scanpos is already at it
		// e.g. "(field exists) and ..."
		//
		if(co == CO_EXISTS)
		{
			m_scanpos--;
		}
		//
		// Otherwise we need a value for the operand
		//
		else
		{
			vector<char> operand2 = next_operand(false, false);
			chk->parse_filter_value((char *)&operand2[0], (uint32_t)operand2.size() - 1);
		}

		parent_expr->add_check(chk);
	}
}