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

Bastian Germann bage at linutronix.de
Tue Dec 20 11:31:28 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 af153de8fc..44df1b1674 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 86a913b309..8481abdd55 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
@@ -272,7 +273,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
@@ -289,7 +295,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
@@ -360,7 +366,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)
@@ -390,10 +396,11 @@ class PreprocessWrapper:
             self.options += f' --variants "{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} '
-               f'-o {self.outxml.name} {self.xmlfile}')
+               f'-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