[elbe-devel] [PATCH 5/7] Prevent double file access

Bastian Germann bage at linutronix.de
Wed Nov 2 19:28:17 CET 2022


Windows locks an open file. Prevent files that are open from being
opened again on the client side.

To that end, eliminate the use of NamedTemporaryFile with .name
access.

Signed-off-by: Bastian Germann <bage at linutronix.de>
---
 elbepack/initvmaction.py  | 13 ++++++-------
 elbepack/xmlpreprocess.py | 25 ++++++++++++++++---------
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/elbepack/initvmaction.py b/elbepack/initvmaction.py
index 66bd5343e4..95bc3fdda8 100644
--- a/elbepack/initvmaction.py
+++ b/elbepack/initvmaction.py
@@ -13,8 +13,6 @@ import time
 import os
 import datetime
 
-from tempfile import NamedTemporaryFile
-
 import elbepack
 from elbepack.treeutils import etree
 from elbepack.directories import elbe_exe
@@ -266,16 +264,17 @@ class AttachAction(InitVMAction):
 
 
 def submit_with_repodir_and_dl_result(xmlfile, cdrom, opt):
+    fname = f'elbe-repodir-{time.time_ns()}.xml'
+    preprocess_xmlfile = os.path.join(os.path.dirname(xmlfile), fname)
     try:
-        with NamedTemporaryFile(suffix=".xml", prefix="elbe-repodir",
-                dir=os.path.dirname(xmlfile)) as tmpfile:
-            preprocess_xmlfile = tmpfile.name
-            with Repodir(xmlfile, preprocess_xmlfile):
-                submit_and_dl_result(preprocess_xmlfile, cdrom, opt)
+        with Repodir(xmlfile, preprocess_xmlfile):
+            submit_and_dl_result(preprocess_xmlfile, cdrom, opt)
     except RepodirError as err:
         print("elbe repodir failed", file=sys.stderr)
         print(err, file=sys.stderr)
         sys.exit(20)
+    finally:
+        os.remove(preprocess_xmlfile)
 
 
 def submit_and_dl_result(xmlfile, cdrom, opt):
diff --git a/elbepack/xmlpreprocess.py b/elbepack/xmlpreprocess.py
index 843e56d3e3..9ae1a5b0dc 100644
--- a/elbepack/xmlpreprocess.py
+++ b/elbepack/xmlpreprocess.py
@@ -8,8 +8,9 @@
 import os
 import re
 import sys
+import tempfile
+import time
 
-from tempfile import NamedTemporaryFile
 from optparse import OptionGroup
 from itertools import islice
 from urllib.error import HTTPError,URLError
@@ -17,7 +18,7 @@ from urllib.request import urlopen
 from passlib.hash import sha512_crypt
 
 from lxml import etree
-from lxml.etree import XMLParser, parse, Element
+from lxml.etree import XMLParser, Element
 
 from elbepack.archivedir import ArchivedirError, combinearchivedir
 from elbepack.config import cfg
@@ -273,7 +274,12 @@ def preprocess_passwd(xml):
         adduser.attrib['passwd_hashed'] = sha512_crypt.hash(passwd)
         del adduser.attrib['passwd']
 
-def xmlpreprocess(fname, output, variants=None, proxy=None):
+def xmlpreprocess(xml_input_file, xml_output_file, variants=None, proxy=None):
+    """Preprocesses the input XML data to make sure the `output`
+       can be validated against the current schema.
+       `xml_input_file` is either a file-like object or a path (str) to the input file.
+       `xml_output_file` is either a file-like object or a path (str) to the output file.
+    """
 
     # pylint: disable=too-many-locals
     # pylint: disable=too-many-branches
@@ -290,7 +296,7 @@ def xmlpreprocess(fname, output, variants=None, proxy=None):
     schema = etree.XMLSchema(schema_tree)
 
     try:
-        xml = parse(fname, parser=parser)
+        xml = etree.parse(xml_input_file, parser=parser)
         xml.xinclude()
 
         # Variant management
@@ -361,7 +367,7 @@ def xmlpreprocess(fname, output, variants=None, proxy=None):
         if schema.validate(xml):
             # if validation succedes write xml file
             xml.write(
-                output,
+                xml_output_file,
                 encoding="UTF-8",
                 pretty_print=True,
                 compression=9)
@@ -391,9 +397,10 @@ class PreprocessWrapper:
             self.options += ' --variants "%s"' % opt.variant
 
     def __enter__(self):
-        self.outxml = NamedTemporaryFile(prefix='elbe', suffix='xml')
+        fname = f'elbe-{time.time_ns()}.xml'
+        self.outxml = os.path.join(tempfile.gettempdir(), fname)
 
-        cmd = f'{sys.executable} {elbe_exe} preprocess {self.options} -o {self.outxml.name} {self.xmlfile}'
+        cmd = f'{sys.executable} {elbe_exe} preprocess {self.options} -o {self.outxml} {self.xmlfile}'
         ret, _, err = command_out_stderr(cmd)
         if ret != 0:
             print("elbe preprocess failed.", file=sys.stderr)
@@ -403,7 +410,7 @@ class PreprocessWrapper:
         return self
 
     def __exit__(self, _typ, _value, _traceback):
-        self.outxml = None
+        os.remove(self.outxml)
 
     @staticmethod
     def add_options(oparser):
@@ -420,4 +427,4 @@ class PreprocessWrapper:
 
     @property
     def preproc(self):
-        return self.outxml.name
+        return self.outxml
-- 
2.30.2



More information about the elbe-devel mailing list