]> granicus.if.org Git - python/commitdiff
Issue #19855: uuid.getnode() on Unix now looks on the PATH for the
authorGeorg Brandl <georg@python.org>
Tue, 30 Sep 2014 17:34:19 +0000 (19:34 +0200)
committerGeorg Brandl <georg@python.org>
Tue, 30 Sep 2014 17:34:19 +0000 (19:34 +0200)
executables used to find the mac address, with /sbin and /usr/sbin as
fallbacks.

Issue #11508: Fixed uuid.getnode() and uuid.uuid1() on environment with
virtual interface.  Original patch by Kent Frazier.

Issue #18784: The uuid module no more attempts to load libc via ctypes.CDLL,
if all necessary functions are already found in libuuid.
Patch by Evgeny Sologubov.

Issue #16102: Make uuid._netbios_getnode() work again on Python 3.

Lib/test/test_uuid.py
Lib/uuid.py
Misc/ACKS
Misc/NEWS

index 43fa6561023b55a9940cc4a97c5aa0fe40e3bd80..7ba09677a7013f7df3117778783e739be4d76887 100644 (file)
@@ -1,6 +1,8 @@
 from unittest import TestCase
 from test import support
 import builtins
+import io
+import os
 import uuid
 
 def importable(name):
@@ -360,6 +362,25 @@ class TestUUID(TestCase):
 
         self.assertEqual(node1, node2)
 
+    def test_find_mac(self):
+        data = '''\
+
+fake hwaddr
+cscotun0  Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
+eth0      Link encap:Ethernet  HWaddr 12:34:56:78:90:ab
+'''
+        def mock_popen(cmd):
+            return io.StringIO(data)
+
+        with support.swap_attr(os, 'popen', mock_popen):
+            mac = uuid._find_mac(
+                command='ifconfig',
+                args='',
+                hw_identifiers=['hwaddr'],
+                get_index=lambda x: x + 1,
+            )
+            self.assertEqual(mac, 0x1234567890ab)
+
     def test_uuid1(self):
         # uuid1 requires ctypes.
         try:
index 5684ad7aceece0a916103ad460478d9973d5167a..53d5da55e8f7e8ee16db4a9984b6cfe8e599c4bb 100644 (file)
@@ -313,25 +313,38 @@ class UUID(object):
 
 def _find_mac(command, args, hw_identifiers, get_index):
     import os
-    for dir in ['', '/sbin/', '/usr/sbin']:
+    path = os.environ.get("PATH", os.defpath).split(os.pathsep)
+    path.extend(('/sbin', '/usr/sbin'))
+    for dir in path:
         executable = os.path.join(dir, command)
-        if not os.path.exists(executable):
-            continue
+        if (os.path.exists(executable) and
+            os.access(executable, os.F_OK | os.X_OK) and
+            not os.path.isdir(executable)):
+            break
+    else:
+        return None
 
-        try:
-            # LC_ALL to get English output, 2>/dev/null to
-            # prevent output on stderr
-            cmd = 'LC_ALL=C %s %s 2>/dev/null' % (executable, args)
-            with os.popen(cmd) as pipe:
-                for line in pipe:
-                    words = line.lower().split()
-                    for i in range(len(words)):
-                        if words[i] in hw_identifiers:
+    try:
+        # LC_ALL to ensure English output, 2>/dev/null to
+        # prevent output on stderr
+        cmd = 'LC_ALL=C %s %s 2>/dev/null' % (executable, args)
+        with os.popen(cmd) as pipe:
+            for line in pipe:
+                words = line.lower().split()
+                for i in range(len(words)):
+                    if words[i] in hw_identifiers:
+                        try:
                             return int(
                                 words[get_index(i)].replace(':', ''), 16)
-        except IOError:
-            continue
-    return None
+                        except (ValueError, IndexError):
+                            # Virtual interfaces, such as those provided by
+                            # VPNs, do not have a colon-delimited MAC address
+                            # as expected, but a 16-byte HWAddr separated by
+                            # dashes. These should be ignored in favor of a
+                            # real MAC address
+                            pass
+    except IOError:
+        pass
 
 def _ifconfig_getnode():
     """Get the hardware address on Unix by running ifconfig."""
@@ -406,7 +419,7 @@ def _netbios_getnode():
         if win32wnet.Netbios(ncb) != 0:
             continue
         status._unpack()
-        bytes = map(ord, status.adapter_address)
+        bytes = status.adapter_address
         return ((bytes[0]<<40) + (bytes[1]<<32) + (bytes[2]<<24) +
                 (bytes[3]<<16) + (bytes[4]<<8) + bytes[5])
 
@@ -429,6 +442,8 @@ try:
             _uuid_generate_random = lib.uuid_generate_random
         if hasattr(lib, 'uuid_generate_time'):
             _uuid_generate_time = lib.uuid_generate_time
+            if _uuid_generate_random is not None:
+                break  # found everything we were looking for
 
     # The uuid_generate_* functions are broken on MacOS X 10.5, as noted
     # in issue #8621 the function generates the same sequence of values
index 428fd01e8a5c3fd56895336595d3170b8a603288..8887dd28becde10d9149c563b0a4777201b95665 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -353,6 +353,7 @@ Doug Fort
 John Fouhy
 Stefan Franke
 Martin Franklin
+Kent Frazier
 Robin Friedrich
 Bradley Froehle
 Ivan Frohne
@@ -1028,6 +1029,7 @@ Ryan Smith-Roberts
 Rafal Smotrzyk
 Dirk Soede
 Paul Sokolovsky
+Evgeny Sologubov
 Cody Somerville
 Clay Spence
 Stefan Sperling
index babfb14e245efaad5cec8ef3092ec7212e63ce63..5b84414a3f9f96cb7fff8b7de4dde57c4562c880 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -47,6 +47,19 @@ Library
   with non-standard cookie handling in some Web browsers.  Reported by
   Sergey Bobrov.
 
+- Issue #19855: uuid.getnode() on Unix now looks on the PATH for the
+  executables used to find the mac address, with /sbin and /usr/sbin as
+  fallbacks.
+
+- Issue #11508: Fixed uuid.getnode() and uuid.uuid1() on environment with
+  virtual interface.  Original patch by Kent Frazier.
+
+- Issue #18784: The uuid module no more attempts to load libc via ctypes.CDLL,
+  if all necessary functions are already found in libuuid.
+  Patch by Evgeny Sologubov.
+
+- Issue #16102: Make uuid._netbios_getnode() work again on Python 3.
+
 - Issue #21766: Prevent a security hole in CGIHTTPServer by URL unquoting paths
   before checking for a CGI script at that path.