[tor-commits] [stem/master] Function for querying a process' pwd

atagar at torproject.org atagar at torproject.org
Sun Nov 13 19:05:14 UTC 2011


commit fab872725d791e8a9ca20f28f6eb5c5358aff87b
Author: Damian Johnson <atagar at torproject.org>
Date:   Thu Nov 10 09:30:06 2011 -0800

    Function for querying a process' pwd
    
    Implementing and testing a stem.util.system.get_pwd(pid) function. This will be
    needed for correcting the relative cookie paths mentioned in...
    https://trac.torproject.org/projects/tor/ticket/1101
---
 stem/util/system.py  |   72 ++++++++++++++++++++++++++++++++++++++++++++++++++
 test/integ/system.py |   11 +++++++
 2 files changed, 83 insertions(+), 0 deletions(-)

diff --git a/stem/util/system.py b/stem/util/system.py
index b63974d..467787c 100644
--- a/stem/util/system.py
+++ b/stem/util/system.py
@@ -9,6 +9,8 @@ import time
 import logging
 import subprocess
 
+import stem.util.proc
+
 LOGGER = logging.getLogger("stem")
 
 # Mapping of commands to if they're available or not. This isn't always
@@ -241,6 +243,76 @@ def get_pid(process_name, process_port = None):
   
   return None
 
+def get_pwd(pid):
+  """
+  Provices the working directory of the given process.
+  
+  Arguments:
+    pid (int) - process id of the process to be queried
+  
+  Returns:
+    str with the absolute path for the process' present working directory
+  
+  Raises:
+    IOError if it can't be determined
+  """
+  
+  # try fetching via the proc contents if it's available
+  if stem.util.proc.is_available():
+    try: return stem.util.proc.get_pwd(pid)
+    except IOError: pass
+  
+  # Fall back to a pwdx query. This isn't available on BSD. If we attempt this
+  # lookup then it trumps lsof when reporting an exception at the end since
+  # it's the better lookup method for this information.
+  
+  exc_msg = None
+  
+  if is_available("pwdx"):
+    # pwdx results are of the form:
+    # 3799: /home/atagar
+    # 5839: No such process
+    
+    try:
+      results = call("pwdx %s" % pid)
+      
+      if not results:
+        exc_msg = "pwdx didn't return any results"
+      elif results[0].endswith("No such process"):
+        exc_msg = "pwdx reported no process for pid %s" % pid
+      elif len(results) != 1 or results[0].count(" ") != 1:
+        exc_msg = "we got unexpected output from pwdx: %s" % results
+      else:
+        return results[0].split(" ", 1)[1].strip()
+    except OSError, exc:
+      exc_msg = "pwdx query for %s failed: %s" % (pid, exc)
+  
+  # Use lsof as the final fallback. This is available on both Linux and is the
+  # only lookup method here that works for BSD...
+  # https://trac.torproject.org/projects/tor/ticket/4236
+  #
+  # ~$ lsof -a -p 75717 -d cwd -Fn
+  # p75717
+  # n/Users/atagar/tor/src/or
+  
+  try:
+    results = call("lsof -a -p %s -d cwd -Fn" % pid)
+    
+    if results and len(results) == 2 and results[1].startswith("n/"):
+      return results[1][1:].strip()
+    elif not exc_msg:
+      exc_msg = "we got unexpected output from lsof: %s" % results
+  except OSError, exc:
+    if not exc_msg:
+      exc_msg = "lsof query for the pwd of %s failed: %s" % (pid, exc)
+  
+  if not exc_msg:
+    # shouldn't happen, somehow we never registered a failure...
+    exc_msg = "unable to query pwdx or lsof"
+  
+  # we failed all lookups, raise
+  raise IOError(exc_msg)
+
 def get_bsd_jail_id(pid):
   """
   Get the FreeBSD jail id for a process.
diff --git a/test/integ/system.py b/test/integ/system.py
index dc5b24c..6e3370e 100644
--- a/test/integ/system.py
+++ b/test/integ/system.py
@@ -2,6 +2,7 @@
 Unit tests for the util.system functions in the context of a tor process.
 """
 
+import os
 import unittest
 
 import test.runner
@@ -40,6 +41,16 @@ class TestSystemFunctions(unittest.TestCase):
     self.assertEquals(runner.get_pid(), system.get_pid("tor", runner.get_control_port()))
     self.assertEquals(None, system.get_pid("blarg_and_stuff"))
   
+  def test_get_pwd(self):
+    """
+    Checks the util.system.get_pwd function.
+    """
+    
+    # tor's pwd will match our process since we started it
+    runner = test.runner.get_runner()
+    self.assertEquals(os.getcwd(), system.get_pwd(runner.get_pid()))
+    self.assertRaises(IOError, system.get_pwd, 99999)
+  
   def test_get_bsd_jail_id(self):
     """
     Exercises the util.system.get_bsd_jail_id function, running through the





More information about the tor-commits mailing list