~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/Documentation/sphinx/kernel_include.py

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #!/usr/bin/env python3
  2 # -*- coding: utf-8; mode: python -*-
  3 # pylint: disable=R0903, C0330, R0914, R0912, E0401
  4 
  5 u"""
  6     kernel-include
  7     ~~~~~~~~~~~~~~
  8 
  9     Implementation of the ``kernel-include`` reST-directive.
 10 
 11     :copyright:  Copyright (C) 2016  Markus Heiser
 12     :license:    GPL Version 2, June 1991 see linux/COPYING for details.
 13 
 14     The ``kernel-include`` reST-directive is a replacement for the ``include``
 15     directive. The ``kernel-include`` directive expand environment variables in
 16     the path name and allows to include files from arbitrary locations.
 17 
 18     .. hint::
 19 
 20       Including files from arbitrary locations (e.g. from ``/etc``) is a
 21       security risk for builders. This is why the ``include`` directive from
 22       docutils *prohibit* pathnames pointing to locations *above* the filesystem
 23       tree where the reST document with the include directive is placed.
 24 
 25     Substrings of the form $name or ${name} are replaced by the value of
 26     environment variable name. Malformed variable names and references to
 27     non-existing variables are left unchanged.
 28 """
 29 
 30 # ==============================================================================
 31 # imports
 32 # ==============================================================================
 33 
 34 import os.path
 35 
 36 from docutils import io, nodes, statemachine
 37 from docutils.utils.error_reporting import SafeString, ErrorString
 38 from docutils.parsers.rst import directives
 39 from docutils.parsers.rst.directives.body import CodeBlock, NumberLines
 40 from docutils.parsers.rst.directives.misc import Include
 41 
 42 __version__  = '1.0'
 43 
 44 # ==============================================================================
 45 def setup(app):
 46 # ==============================================================================
 47 
 48     app.add_directive("kernel-include", KernelInclude)
 49     return dict(
 50         version = __version__,
 51         parallel_read_safe = True,
 52         parallel_write_safe = True
 53     )
 54 
 55 # ==============================================================================
 56 class KernelInclude(Include):
 57 # ==============================================================================
 58 
 59     u"""KernelInclude (``kernel-include``) directive"""
 60 
 61     def run(self):
 62         env = self.state.document.settings.env
 63         path = os.path.realpath(
 64             os.path.expandvars(self.arguments[0]))
 65 
 66         # to get a bit security back, prohibit /etc:
 67         if path.startswith(os.sep + "etc"):
 68             raise self.severe(
 69                 'Problems with "%s" directive, prohibited path: %s'
 70                 % (self.name, path))
 71 
 72         self.arguments[0] = path
 73 
 74         env.note_dependency(os.path.abspath(path))
 75 
 76         #return super(KernelInclude, self).run() # won't work, see HINTs in _run()
 77         return self._run()
 78 
 79     def _run(self):
 80         """Include a file as part of the content of this reST file."""
 81 
 82         # HINT: I had to copy&paste the whole Include.run method. I'am not happy
 83         # with this, but due to security reasons, the Include.run method does
 84         # not allow absolute or relative pathnames pointing to locations *above*
 85         # the filesystem tree where the reST document is placed.
 86 
 87         if not self.state.document.settings.file_insertion_enabled:
 88             raise self.warning('"%s" directive disabled.' % self.name)
 89         source = self.state_machine.input_lines.source(
 90             self.lineno - self.state_machine.input_offset - 1)
 91         source_dir = os.path.dirname(os.path.abspath(source))
 92         path = directives.path(self.arguments[0])
 93         if path.startswith('<') and path.endswith('>'):
 94             path = os.path.join(self.standard_include_path, path[1:-1])
 95         path = os.path.normpath(os.path.join(source_dir, path))
 96 
 97         # HINT: this is the only line I had to change / commented out:
 98         #path = utils.relative_path(None, path)
 99 
100         encoding = self.options.get(
101             'encoding', self.state.document.settings.input_encoding)
102         e_handler=self.state.document.settings.input_encoding_error_handler
103         tab_width = self.options.get(
104             'tab-width', self.state.document.settings.tab_width)
105         try:
106             self.state.document.settings.record_dependencies.add(path)
107             include_file = io.FileInput(source_path=path,
108                                         encoding=encoding,
109                                         error_handler=e_handler)
110         except UnicodeEncodeError as error:
111             raise self.severe('Problems with "%s" directive path:\n'
112                               'Cannot encode input file path "%s" '
113                               '(wrong locale?).' %
114                               (self.name, SafeString(path)))
115         except IOError as error:
116             raise self.severe('Problems with "%s" directive path:\n%s.' %
117                       (self.name, ErrorString(error)))
118         startline = self.options.get('start-line', None)
119         endline = self.options.get('end-line', None)
120         try:
121             if startline or (endline is not None):
122                 lines = include_file.readlines()
123                 rawtext = ''.join(lines[startline:endline])
124             else:
125                 rawtext = include_file.read()
126         except UnicodeError as error:
127             raise self.severe('Problem with "%s" directive:\n%s' %
128                               (self.name, ErrorString(error)))
129         # start-after/end-before: no restrictions on newlines in match-text,
130         # and no restrictions on matching inside lines vs. line boundaries
131         after_text = self.options.get('start-after', None)
132         if after_text:
133             # skip content in rawtext before *and incl.* a matching text
134             after_index = rawtext.find(after_text)
135             if after_index < 0:
136                 raise self.severe('Problem with "start-after" option of "%s" '
137                                   'directive:\nText not found.' % self.name)
138             rawtext = rawtext[after_index + len(after_text):]
139         before_text = self.options.get('end-before', None)
140         if before_text:
141             # skip content in rawtext after *and incl.* a matching text
142             before_index = rawtext.find(before_text)
143             if before_index < 0:
144                 raise self.severe('Problem with "end-before" option of "%s" '
145                                   'directive:\nText not found.' % self.name)
146             rawtext = rawtext[:before_index]
147 
148         include_lines = statemachine.string2lines(rawtext, tab_width,
149                                                   convert_whitespace=True)
150         if 'literal' in self.options:
151             # Convert tabs to spaces, if `tab_width` is positive.
152             if tab_width >= 0:
153                 text = rawtext.expandtabs(tab_width)
154             else:
155                 text = rawtext
156             literal_block = nodes.literal_block(rawtext, source=path,
157                                     classes=self.options.get('class', []))
158             literal_block.line = 1
159             self.add_name(literal_block)
160             if 'number-lines' in self.options:
161                 try:
162                     startline = int(self.options['number-lines'] or 1)
163                 except ValueError:
164                     raise self.error(':number-lines: with non-integer '
165                                      'start value')
166                 endline = startline + len(include_lines)
167                 if text.endswith('\n'):
168                     text = text[:-1]
169                 tokens = NumberLines([([], text)], startline, endline)
170                 for classes, value in tokens:
171                     if classes:
172                         literal_block += nodes.inline(value, value,
173                                                       classes=classes)
174                     else:
175                         literal_block += nodes.Text(value, value)
176             else:
177                 literal_block += nodes.Text(text, text)
178             return [literal_block]
179         if 'code' in self.options:
180             self.options['source'] = path
181             codeblock = CodeBlock(self.name,
182                                   [self.options.pop('code')], # arguments
183                                   self.options,
184                                   include_lines, # content
185                                   self.lineno,
186                                   self.content_offset,
187                                   self.block_text,
188                                   self.state,
189                                   self.state_machine)
190             return codeblock.run()
191         self.state_machine.insert_input(include_lines, path)
192         return []

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php