From nobody Sun May 5 00:29:19 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=none (zohomail.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail(p=none dis=none) header.from=citrix.com ARC-Seal: i=1; a=rsa-sha256; t=1576760733; cv=none; d=zohomail.com; s=zohoarc; b=hZv9SEcOQes03ivjZccblsOQ4L0uT+ADeQrqr6CkxfLQbp1GCrunaKU/mDHvSmwM/QEWdsQrSjyqaUX0wmZTdSLssmBxvwllwffYT9IkI3RE84zFo52CjcG1RmlR5rPXAzHSxhLx/kWv3RAdhQNrkuCx6mUavZTr64cawAW+fqA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1576760733; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:To; bh=SGq7j6scc8cSRpw9UCX+65v6GayUX9QHuuVQBjTU9so=; b=LxygSP3fga4wFjY8wwE4/g4h0M1gnCFc6d1OTpAOqtvDf9/j0d0KmDxdsOTKVK7cJEFJuTTpVxEwVYPhTDYlt3jA2esaE1mumUs9fcpg336ehVeMTP6wP/gEv6stiZELNmKJkxsqQCEgSGspTFnBnWPIK4JO2nZJPLJYg8We+os= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=none (zohomail.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1576760733487133.64887631186673; Thu, 19 Dec 2019 05:05:33 -0800 (PST) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1ihvTX-0007EH-Bx; Thu, 19 Dec 2019 13:04:19 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1ihvTV-0007EC-Le for xen-devel@lists.xenproject.org; Thu, 19 Dec 2019 13:04:17 +0000 Received: from esa2.hc3370-68.iphmx.com (unknown [216.71.145.153]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 0f44b56b-2260-11ea-919f-12813bfff9fa; Thu, 19 Dec 2019 13:04:16 +0000 (UTC) X-Inumbo-ID: 0f44b56b-2260-11ea-919f-12813bfff9fa DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1576760656; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=1OvQmPV+51JxwiP/yU65B89LC51kPYTPYg4E90lY/RQ=; b=KzqJnQfhdv8wB6whEagBpwAmRdyyJ7whbWGMTZJRfYp3Jcu69TA6gWLV UVsvLwF7ZvluvhifsBWMEto8E8TWp5hlCvhfCq63M1+kcRIjRABp3J2hO MMz3LwHj/WUU3nryd7Kf0LZunDehHRn8HHrNrfGR9eUr5LJj2ecK/ns9h U=; Authentication-Results: esa2.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none; spf=None smtp.pra=andrew.cooper3@citrix.com; spf=Pass smtp.mailfrom=Andrew.Cooper3@citrix.com; spf=None smtp.helo=postmaster@mail.citrix.com Received-SPF: none (zohomail.com: 192.237.175.120 is neither permitted nor denied by domain of lists.xenproject.org) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Received-SPF: None (esa2.hc3370-68.iphmx.com: no sender authenticity information available from domain of andrew.cooper3@citrix.com) identity=pra; client-ip=162.221.158.21; receiver=esa2.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="andrew.cooper3@citrix.com"; x-conformance=sidf_compatible Received-SPF: Pass (esa2.hc3370-68.iphmx.com: domain of Andrew.Cooper3@citrix.com designates 162.221.158.21 as permitted sender) identity=mailfrom; client-ip=162.221.158.21; receiver=esa2.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="Andrew.Cooper3@citrix.com"; x-conformance=sidf_compatible; x-record-type="v=spf1"; x-record-text="v=spf1 ip4:209.167.231.154 ip4:178.63.86.133 ip4:195.66.111.40/30 ip4:85.115.9.32/28 ip4:199.102.83.4 ip4:192.28.146.160 ip4:192.28.146.107 ip4:216.52.6.88 ip4:216.52.6.188 ip4:162.221.158.21 ip4:162.221.156.83 ip4:168.245.78.127 ~all" Received-SPF: None (esa2.hc3370-68.iphmx.com: no sender authenticity information available from domain of postmaster@mail.citrix.com) identity=helo; client-ip=162.221.158.21; receiver=esa2.hc3370-68.iphmx.com; envelope-from="Andrew.Cooper3@citrix.com"; x-sender="postmaster@mail.citrix.com"; x-conformance=sidf_compatible IronPort-SDR: Xf8VahkGZ3B6axPb9KLkuG6FBMXO8uwxBsDyxLbOqv+PaIt1fiDchRGxpf1I1M3EH7HWdv52CG x+mAZ0/RTYWzcjemrxSE5jslA5d4lkcC6nKaqWvT2Mp9zHQfVQbhX+bnrJwfQ8bklyiGtAy4zq /lL8Bwf0rIgvmA7COA+5UNJJLAt8HAWCP8SvOy/FNMMnBKiGEG5n2nQmSbva41EAPfCgXpjgXy cf7okal+q0SutwPwn4jEJnAyw729Qj2FZcLk0XaDVgtaPCVuMDuFc3KP4CGB5+bDqZvUnfWqw8 GA4= X-SBRS: 2.7 X-MesageID: 9940637 X-Ironport-Server: esa2.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.69,332,1571716800"; d="scan'208";a="9940637" From: Andrew Cooper To: Xen-devel Date: Thu, 19 Dec 2019 13:04:12 +0000 Message-ID: <20191219130412.8258-1-andrew.cooper3@citrix.com> X-Mailer: git-send-email 2.11.0 MIME-Version: 1.0 Subject: [Xen-devel] [PATCH v2] tools/python: Python 3 compatibility X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Andrew Cooper , =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= , Wei Liu , Ian Jackson Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) convert-legacy-stream is only used for incomming migration from pre Xen 4.7, and verify-stream-v2 appears to only be used by me during migration development - it is little surprise that they missed the main converstion effort in Xen 4.13. Fix it all up. Move open_file_or_fd() into a new util.py to avoid duplication, making it a more generic wrapper around open() or fdopen(). In libxc.py, drop all long() conversion. Python 2 will DTRT with int =3D> = long promotion, even on 32bit builds. In convert-legacy-stream, don't pass empty strings to write_record(). Join= on the empty argl will do the right thing. Signed-off-by: Andrew Cooper Acked-by: Marek Marczykowski-G=C3=B3recki --- CC: Ian Jackson CC: Wei Liu CC: Marek Marczykowski-G=C3=B3recki v2: * Drop int/long in libxc.py. Python 2 will DTRT with int turning into lon= g. * More b prefixes in convert-legacy-stream. Drop empty string passing This needs backporting to 4.13 ASAP --- tools/python/scripts/convert-legacy-stream | 67 +++++++++-----------------= ---- tools/python/scripts/verify-stream-v2 | 42 ++++--------------- tools/python/xen/__init__.py | 1 - tools/python/xen/lowlevel/__init__.py | 1 - tools/python/xen/migration/libxc.py | 34 +++++++-------- tools/python/xen/migration/libxl.py | 2 +- tools/python/xen/migration/verify.py | 4 +- tools/python/xen/util.py | 23 ++++++++++ 8 files changed, 69 insertions(+), 105 deletions(-) create mode 100644 tools/python/xen/util.py diff --git a/tools/python/scripts/convert-legacy-stream b/tools/python/scri= pts/convert-legacy-stream index 5f80f13654..d316ae16f0 100755 --- a/tools/python/scripts/convert-legacy-stream +++ b/tools/python/scripts/convert-legacy-stream @@ -5,6 +5,8 @@ Convert a legacy migration stream to a v2 stream. """ =20 +from __future__ import print_function + import sys import os, os.path import syslog @@ -12,6 +14,7 @@ import traceback =20 from struct import calcsize, unpack, pack =20 +from xen.util import open_file_or_fd as open_file_or_fd from xen.migration import legacy, public, libxc, libxl, xl =20 __version__ =3D 1 @@ -39,16 +42,16 @@ def info(msg): for line in msg.split("\n"): syslog.syslog(syslog.LOG_INFO, line) else: - print msg + print(msg) =20 def err(msg): """Error message, routed to appropriate destination""" if log_to_syslog: for line in msg.split("\n"): syslog.syslog(syslog.LOG_ERR, line) - print >> sys.stderr, msg + print(msg, file =3D sys.stderr) =20 -class StreamError(StandardError): +class StreamError(Exception): """Error with the incoming migration stream""" pass =20 @@ -70,7 +73,7 @@ class VM(object): =20 # libxl self.libxl =3D fmt =3D=3D "libxl" - self.emu_xenstore =3D "" # NUL terminated key&val pairs from "tool= stack" records + self.emu_xenstore =3D b"" # NUL terminated key&val pairs from "too= lstack" records =20 def write_libxc_ihdr(): stream_write(pack(libxc.IHDR_FORMAT, @@ -102,12 +105,12 @@ def write_libxl_hdr(): )) =20 def write_record(rt, *argl): - alldata =3D ''.join(argl) + alldata =3D b''.join(argl) length =3D len(alldata) =20 record =3D pack(libxc.RH_FORMAT, rt, length) + alldata plen =3D (8 - (length & 7)) & 7 - record +=3D '\x00' * plen + record +=3D b'\x00' * plen =20 stream_write(record) =20 @@ -164,10 +167,10 @@ def write_libxc_hvm_params(params): pack("Q" * len(params), *params)) =20 def write_libxl_end(): - write_record(libxl.REC_TYPE_end, "") + write_record(libxl.REC_TYPE_end) =20 def write_libxl_libxc_context(): - write_record(libxl.REC_TYPE_libxc_context, "") + write_record(libxl.REC_TYPE_libxc_context) =20 def write_libxl_emulator_xenstore_data(data): write_record(libxl.REC_TYPE_emulator_xenstore_data, @@ -225,7 +228,7 @@ def read_pv_extended_info(vm): so_far +=3D datasz =20 # Eww, but this is how it is done :( - if blkid =3D=3D "vcpu": + if blkid =3D=3D b"vcpu": =20 vm.basic_len =3D datasz =20 @@ -242,10 +245,10 @@ def read_pv_extended_info(vm): =20 write_libxc_pv_info(vm) =20 - elif blkid =3D=3D "extv": + elif blkid =3D=3D b"extv": vm.extd =3D True =20 - elif blkid =3D=3D "xcnt": + elif blkid =3D=3D b"xcnt": vm.xsave_len, =3D unpack("I", data[:4]) info("xcnt sz 0x%x" % (vm.xsave_len, )) =20 @@ -296,7 +299,7 @@ def read_pv_tail(vm): info("Got shinfo") =20 write_record(libxc.REC_TYPE_shared_info, shinfo) - write_record(libxc.REC_TYPE_end, "") + write_record(libxc.REC_TYPE_end) =20 =20 def read_libxl_toolstack(vm, data): @@ -336,7 +339,7 @@ def read_libxl_toolstack(vm, data): if twidth =3D=3D 64: name =3D name[:-4] =20 - if name[-1] !=3D '\x00': + if name[-1] !=3D b'\x00': raise StreamError("physmap name not NUL terminated") =20 root =3D "physmap/%x" % (phys,) @@ -347,7 +350,7 @@ def read_libxl_toolstack(vm, data): for key, val in zip(kv[0::2], kv[1::2]): info(" '%s' =3D '%s'" % (key, val)) =20 - vm.emu_xenstore +=3D '\x00'.join(kv) + '\x00' + vm.emu_xenstore +=3D b'\x00'.join(kv) + b'\x00' =20 =20 def read_chunks(vm): @@ -524,7 +527,7 @@ def read_hvm_tail(vm): blob =3D rdexact(blobsz) =20 write_record(libxc.REC_TYPE_hvm_context, blob) - write_record(libxc.REC_TYPE_end, "") + write_record(libxc.REC_TYPE_end) =20 =20 =20 @@ -534,7 +537,7 @@ def read_qemu(vm): sig, =3D unpack("21s", rawsig) info("Qemu signature: %s" % (sig, )) =20 - if sig =3D=3D "DeviceModelRecord0002": + if sig =3D=3D b"DeviceModelRecord0002": rawsz =3D rdexact(4) sz, =3D unpack("I", rawsz) qdata =3D rdexact(sz) @@ -617,36 +620,6 @@ def read_legacy_stream(vm): return 2 return 0 =20 -def open_file_or_fd(val, mode): - """ - If 'val' looks like a decimal integer, open it as an fd. If not, try = to - open it as a regular file. - """ - - fd =3D -1 - try: - # Does it look like an integer? - try: - fd =3D int(val, 10) - except ValueError: - pass - - # Try to open it... - if fd !=3D -1: - return os.fdopen(fd, mode, 0) - else: - return open(val, mode, 0) - - except StandardError, e: - if fd !=3D -1: - err("Unable to open fd %d: %s: %s" % - (fd, e.__class__.__name__, e)) - else: - err("Unable to open file '%s': %s: %s" % - (val, e.__class__.__name__, e)) - - raise SystemExit(1) - =20 def main(): from optparse import OptionParser @@ -723,7 +696,7 @@ def main(): if __name__ =3D=3D "__main__": try: sys.exit(main()) - except SystemExit, e: + except SystemExit as e: sys.exit(e.code) except KeyboardInterrupt: sys.exit(1) diff --git a/tools/python/scripts/verify-stream-v2 b/tools/python/scripts/v= erify-stream-v2 index 3daf25791e..8bac04d566 100755 --- a/tools/python/scripts/verify-stream-v2 +++ b/tools/python/scripts/verify-stream-v2 @@ -3,12 +3,15 @@ =20 """ Verify a v2 format migration stream """ =20 +from __future__ import print_function + import sys import struct import os, os.path import syslog import traceback =20 +from xen.util import open_file_or_fd as open_file_or_fd from xen.migration.verify import StreamError, RecordError from xen.migration.libxc import VerifyLibxc from xen.migration.libxl import VerifyLibxl @@ -25,7 +28,7 @@ def info(msg): for line in msg.split("\n"): syslog.syslog(syslog.LOG_INFO, line) else: - print msg + print(msg) =20 def err(msg): """Error message, routed to appropriate destination""" @@ -33,7 +36,7 @@ def err(msg): if log_to_syslog: for line in msg.split("\n"): syslog.syslog(syslog.LOG_ERR, line) - print >> sys.stderr, msg + print(msg, file =3D sys.stderr) =20 def stream_read(_ =3D None): """Read from input""" @@ -56,7 +59,7 @@ def skip_xl_header(): """Skip over an xl header in the stream""" =20 hdr =3D rdexact(32) - if hdr !=3D "Xen saved domain, xl format\n \0 \r": + if hdr !=3D b"Xen saved domain, xl format\n \0 \r": raise StreamError("No xl header") =20 _, mflags, _, optlen =3D unpack_exact("=3DIIII") @@ -86,7 +89,7 @@ def read_stream(fmt): err(traceback.format_exc()) return 1 =20 - except StandardError: + except Exception: err("Script Error:") err(traceback.format_exc()) err("Please fix me") @@ -94,35 +97,6 @@ def read_stream(fmt): =20 return 0 =20 -def open_file_or_fd(val, mode, buffering): - """ - If 'val' looks like a decimal integer, open it as an fd. If not, try = to - open it as a regular file. - """ - - fd =3D -1 - try: - # Does it look like an integer? - try: - fd =3D int(val, 10) - except ValueError: - pass - - # Try to open it... - if fd !=3D -1: - return os.fdopen(fd, mode, buffering) - else: - return open(val, mode, buffering) - - except StandardError, e: - if fd !=3D -1: - err("Unable to open fd %d: %s: %s" % - (fd, e.__class__.__name__, e)) - else: - err("Unable to open file '%s': %s: %s" % - (val, e.__class__.__name__, e)) - - raise SystemExit(2) =20 def main(): """ main """ @@ -168,7 +142,7 @@ def main(): if __name__ =3D=3D "__main__": try: sys.exit(main()) - except SystemExit, e: + except SystemExit as e: sys.exit(e.code) except KeyboardInterrupt: sys.exit(2) diff --git a/tools/python/xen/__init__.py b/tools/python/xen/__init__.py index 8d1c8b69c3..e69de29bb2 100644 --- a/tools/python/xen/__init__.py +++ b/tools/python/xen/__init__.py @@ -1 +0,0 @@ -=20 diff --git a/tools/python/xen/lowlevel/__init__.py b/tools/python/xen/lowle= vel/__init__.py index 8d1c8b69c3..e69de29bb2 100644 --- a/tools/python/xen/lowlevel/__init__.py +++ b/tools/python/xen/lowlevel/__init__.py @@ -1 +0,0 @@ -=20 diff --git a/tools/python/xen/migration/libxc.py b/tools/python/xen/migrati= on/libxc.py index f24448a9ef..0a329c2090 100644 --- a/tools/python/xen/migration/libxc.py +++ b/tools/python/xen/migration/libxc.py @@ -14,10 +14,6 @@ =20 from xen.migration.verify import StreamError, RecordError, VerifyBase =20 -# In Python3 long type have been merged into int, 1L syntax is no longer v= alid -if sys.version_info > (3,): - long =3D int - # Image Header IHDR_FORMAT =3D "!QIIHHI" =20 @@ -87,23 +83,23 @@ =20 # page_data PAGE_DATA_FORMAT =3D "II" -PAGE_DATA_PFN_MASK =3D (long(1) << 52) - 1 -PAGE_DATA_PFN_RESZ_MASK =3D ((long(1) << 60) - 1) & ~((long(1) << 52)= - 1) +PAGE_DATA_PFN_MASK =3D (1 << 52) - 1 +PAGE_DATA_PFN_RESZ_MASK =3D ((1 << 60) - 1) & ~((1 << 52) - 1) =20 # flags from xen/public/domctl.h: XEN_DOMCTL_PFINFO_* shifted by 32 bits PAGE_DATA_TYPE_SHIFT =3D 60 -PAGE_DATA_TYPE_LTABTYPE_MASK =3D (long(0x7) << PAGE_DATA_TYPE_SHIFT) -PAGE_DATA_TYPE_LTAB_MASK =3D (long(0xf) << PAGE_DATA_TYPE_SHIFT) -PAGE_DATA_TYPE_LPINTAB =3D (long(0x8) << PAGE_DATA_TYPE_SHIFT) # Pin= ned pagetable - -PAGE_DATA_TYPE_NOTAB =3D (long(0x0) << PAGE_DATA_TYPE_SHIFT) # Reg= ular page -PAGE_DATA_TYPE_L1TAB =3D (long(0x1) << PAGE_DATA_TYPE_SHIFT) # L1 = pagetable -PAGE_DATA_TYPE_L2TAB =3D (long(0x2) << PAGE_DATA_TYPE_SHIFT) # L2 = pagetable -PAGE_DATA_TYPE_L3TAB =3D (long(0x3) << PAGE_DATA_TYPE_SHIFT) # L3 = pagetable -PAGE_DATA_TYPE_L4TAB =3D (long(0x4) << PAGE_DATA_TYPE_SHIFT) # L4 = pagetable -PAGE_DATA_TYPE_BROKEN =3D (long(0xd) << PAGE_DATA_TYPE_SHIFT) # Bro= ken -PAGE_DATA_TYPE_XALLOC =3D (long(0xe) << PAGE_DATA_TYPE_SHIFT) # All= ocate-only -PAGE_DATA_TYPE_XTAB =3D (long(0xf) << PAGE_DATA_TYPE_SHIFT) # Inv= alid +PAGE_DATA_TYPE_LTABTYPE_MASK =3D (0x7 << PAGE_DATA_TYPE_SHIFT) +PAGE_DATA_TYPE_LTAB_MASK =3D (0xf << PAGE_DATA_TYPE_SHIFT) +PAGE_DATA_TYPE_LPINTAB =3D (0x8 << PAGE_DATA_TYPE_SHIFT) # Pinned pa= getable + +PAGE_DATA_TYPE_NOTAB =3D (0x0 << PAGE_DATA_TYPE_SHIFT) # Regular p= age +PAGE_DATA_TYPE_L1TAB =3D (0x1 << PAGE_DATA_TYPE_SHIFT) # L1 pageta= ble +PAGE_DATA_TYPE_L2TAB =3D (0x2 << PAGE_DATA_TYPE_SHIFT) # L2 pageta= ble +PAGE_DATA_TYPE_L3TAB =3D (0x3 << PAGE_DATA_TYPE_SHIFT) # L3 pageta= ble +PAGE_DATA_TYPE_L4TAB =3D (0x4 << PAGE_DATA_TYPE_SHIFT) # L4 pageta= ble +PAGE_DATA_TYPE_BROKEN =3D (0xd << PAGE_DATA_TYPE_SHIFT) # Broken +PAGE_DATA_TYPE_XALLOC =3D (0xe << PAGE_DATA_TYPE_SHIFT) # Allocate-= only +PAGE_DATA_TYPE_XTAB =3D (0xf << PAGE_DATA_TYPE_SHIFT) # Invalid =20 # x86_pv_info X86_PV_INFO_FORMAT =3D "BBHI" @@ -223,7 +219,7 @@ def verify_record(self): self.squashed_pagedata_records +=3D 1 =20 padding =3D content[length:] - if padding !=3D "\x00" * len(padding): + if padding !=3D b"\x00" * len(padding): raise StreamError("Padding containing non0 bytes found") =20 if rtype not in record_verifiers: diff --git a/tools/python/xen/migration/libxl.py b/tools/python/xen/migrati= on/libxl.py index d5f54dc489..79f4024e72 100644 --- a/tools/python/xen/migration/libxl.py +++ b/tools/python/xen/migration/libxl.py @@ -128,7 +128,7 @@ def verify_record(self): content =3D self.rdexact(contentsz) =20 padding =3D content[length:] - if padding !=3D "\x00" * len(padding): + if padding !=3D b"\x00" * len(padding): raise StreamError("Padding containing non0 bytes found") =20 if rtype not in record_verifiers: diff --git a/tools/python/xen/migration/verify.py b/tools/python/xen/migrat= ion/verify.py index 7a42dbfc58..1e38f4a3c0 100644 --- a/tools/python/xen/migration/verify.py +++ b/tools/python/xen/migration/verify.py @@ -7,11 +7,11 @@ =20 from struct import calcsize, unpack =20 -class StreamError(StandardError): +class StreamError(Exception): """Error with the stream""" pass =20 -class RecordError(StandardError): +class RecordError(Exception): """Error with a record in the stream""" pass =20 diff --git a/tools/python/xen/util.py b/tools/python/xen/util.py new file mode 100644 index 0000000000..a11358eefa --- /dev/null +++ b/tools/python/xen/util.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os + +def open_file_or_fd(val, *argl, **kwargs): + """ + If 'val' looks like a decimal integer, open it as an fd. If not, try = to + open it as a regular file. + """ + + fd =3D -1 + try: + # Does it look like an integer? + fd =3D int(val, 10) + except ValueError: + pass + + # Try to open it... + if fd !=3D -1: + return os.fdopen(fd, *argl, **kwargs) + else: + return open(val, *argl, **kwargs) --=20 2.11.0 _______________________________________________ Xen-devel mailing list Xen-devel@lists.xenproject.org https://lists.xenproject.org/mailman/listinfo/xen-devel