This file is indexed.

/usr/lib/python2.7/dist-packages/shinken/graph.py is in shinken-common 2.0.3-4.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/usr/bin/env python

# -*- coding: utf-8 -*-

# Copyright (C) 2009-2012:
#     Gabes Jean, naparuba@gmail.com
#     Gerhard Lausser, Gerhard.Lausser@consol.de
#     Gregory Starck, g.starck@gmail.com
#     Hartmut Goebel, h.goebel@goebel-consult.de
#
# This file is part of Shinken.
#
# Shinken is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Shinken is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Shinken.  If not, see <http://www.gnu.org/licenses/>.


class Graph:
    """Graph is a class to make graph things like DFS checks or accessibility
    Why use an atomic bomb when a little hammer is enough?

    """

    def __init__(self):
        self.nodes = {}

    # Do not call twice...
    def add_node(self, node):
        self.nodes[node] = []

    # Just loop over nodes
    def add_nodes(self, nodes):
        for node in nodes:
            self.add_node(node)

    # Add an edge to the graph from->to
    def add_edge(self, from_node, to_node):
        # Maybe to_node is unknown
        if to_node not in self.nodes:
            self.add_node(to_node)

        try:
            self.nodes[from_node].append(to_node)
        # If from_node does not exist, add it with its son
        except KeyError, exp:
            self.nodes[from_node] = [to_node]

    # Return all nodes that are in a loop. So if return [], no loop
    def loop_check(self):
        in_loop = []
        # Add the tag for dfs check
        for node in self.nodes:
            node.dfs_loop_status = 'DFS_UNCHECKED'

        # Now do the job
        for node in self.nodes:
            # Run the dfs only if the node has not been already done */
            if node.dfs_loop_status == 'DFS_UNCHECKED':
                self.dfs_loop_search(node)
            # If LOOP_INSIDE, must be returned
            if node.dfs_loop_status == 'DFS_LOOP_INSIDE':
                in_loop.append(node)

        # Remove the tag
        for node in self.nodes:
            del node.dfs_loop_status

        return in_loop

    # DFS_UNCHECKED default value
    # DFS_TEMPORARY_CHECKED check just one time
    # DFS_OK no problem for node and its children
    # DFS_NEAR_LOOP has trouble sons
    # DFS_LOOP_INSIDE is a part of a loop!
    def dfs_loop_search(self, root):
        # Make the root temporary checked
        root.dfs_loop_status = 'DFS_TEMPORARY_CHECKED'

        # We are scanning the sons
        for child in self.nodes[root]:
            child_status = child.dfs_loop_status
            # If a child is not checked, check it
            if child_status == 'DFS_UNCHECKED':
                self.dfs_loop_search(child)
                child_status = child.dfs_loop_status

            # If a child has already been temporary checked, it's a problem,
            # loop inside, and its a acked status
            if child_status == 'DFS_TEMPORARY_CHECKED':
                child.dfs_loop_status = 'DFS_LOOP_INSIDE'
                root.dfs_loop_status = 'DFS_LOOP_INSIDE'

            # If a child has already been temporary checked, it's a problem, loop inside
            if child_status in ('DFS_NEAR_LOOP', 'DFS_LOOP_INSIDE'):
                # if a node is known to be part of a loop, do not let it be less
                if root.dfs_loop_status != 'DFS_LOOP_INSIDE':
                    root.dfs_loop_status = 'DFS_NEAR_LOOP'
                # We've already seen this child, it's a problem
                child.dfs_loop_status = 'DFS_LOOP_INSIDE'

        # If root have been modified, do not set it OK
        # A node is OK if and only if all of its children are OK
        # if it does not have a child, goes ok
        if root.dfs_loop_status == 'DFS_TEMPORARY_CHECKED':
            root.dfs_loop_status = 'DFS_OK'

    # Get accessibility packs of the graph: in one pack,
    # element are related in a way. Between packs, there is no relation
    # at all.
    # TODO: Make it work for directional graph too
    # Because for now, edge must be father->son AND son->father
    def get_accessibility_packs(self):
        packs = []
        # Add the tag for dfs check
        for node in self.nodes:
            node.dfs_loop_status = 'DFS_UNCHECKED'

        for node in self.nodes:
            # Run the dfs only if the node is not already done */
            if node.dfs_loop_status == 'DFS_UNCHECKED':
                packs.append(self.dfs_get_all_childs(node))

        # Remove the tag
        for node in self.nodes:
            del node.dfs_loop_status

        return packs

    # Return all my children, and all my grandchildren
    def dfs_get_all_childs(self, root):
        root.dfs_loop_status = 'DFS_CHECKED'

        ret = set()
        # Me
        ret.add(root)
        # And my sons
        ret.update(self.nodes[root])

        for child in self.nodes[root]:
            # I just don't care about already checked childs
            if child.dfs_loop_status == 'DFS_UNCHECKED':
                ret.update(self.dfs_get_all_childs(child))

        return list(ret)