summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2016-02-28 00:20:30 +0100
committerGiampaolo Rodola <g.rodola@gmail.com>2016-02-28 00:20:30 +0100
commitdc46f4c516fe84ca4d37776e4d2634a188bcaf23 (patch)
tree485de933ddce17e7f919b5c5fb33025ec9ab4138
parent7966bf55740e12844112837b15c9635e0a3a5a30 (diff)
downloadpsutil-dc46f4c516fe84ca4d37776e4d2634a188bcaf23.tar.gz
#777 / linux / open_files(): return also file mode
-rw-r--r--psutil/_pslinux.py20
-rw-r--r--psutil/tests/test_linux.py41
-rw-r--r--psutil/tests/test_process.py1
3 files changed, 59 insertions, 3 deletions
diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py
index 39f5328d..979a7784 100644
--- a/psutil/_pslinux.py
+++ b/psutil/_pslinux.py
@@ -179,6 +179,16 @@ def readlink(path):
return path
+def file_flags_to_mode(flags):
+ md = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'}
+ m = md[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)]
+ if flags & os.O_APPEND:
+ m = m.replace('w', 'a', 1)
+ m = m.replace('w+', 'r+')
+ # possible values: r, w, a, r+, a+
+ return m
+
+
def get_sector_size():
try:
with open(b"/sys/block/sda/queue/hw_sector_size") as f:
@@ -237,7 +247,7 @@ sdiskio = namedtuple('sdiskio', ['read_count', 'write_count',
'read_merged_count', 'write_merged_count',
'busy_time'])
-popenfile = namedtuple('popenfile', ['path', 'fd', 'position'])
+popenfile = namedtuple('popenfile', ['path', 'fd', 'position', 'mode'])
pmem = namedtuple('pmem', 'rss vms shared text lib data dirty')
pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', 'pss', 'swap'))
@@ -1318,8 +1328,12 @@ class Process(object):
file = "%s/%s/fdinfo/%s" % (
self._procfs_path, self.pid, fd)
with open_binary(file) as f:
- pos = int(f.readline().split()[1])
- ntuple = popenfile(path, int(fd), pos)
+ pos = f.readline().split()[1]
+ flags = f.readline().split()[1]
+ # flags is an octal number
+ flags_oct = int(flags, 8)
+ mode = file_flags_to_mode(flags_oct)
+ ntuple = popenfile(path, int(fd), int(pos), mode)
retlist.append(ntuple)
if hit_enoent:
# raise NSP if the process disappeared on us
diff --git a/psutil/tests/test_linux.py b/psutil/tests/test_linux.py
index 7bf753b2..a9545991 100644
--- a/psutil/tests/test_linux.py
+++ b/psutil/tests/test_linux.py
@@ -37,6 +37,7 @@ from psutil.tests import pyrun
from psutil.tests import reap_children
from psutil.tests import retry_before_failing
from psutil.tests import run_test_module_by_name
+from psutil.tests import safe_remove
from psutil.tests import sh
from psutil.tests import skip_on_not_implemented
from psutil.tests import TESTFN
@@ -719,6 +720,11 @@ class TestMisc(unittest.TestCase):
@unittest.skipUnless(LINUX, "not a Linux system")
class TestProcess(unittest.TestCase):
+ def setUp(self):
+ safe_remove(TESTFN)
+
+ tearDown = setUp
+
def test_memory_maps(self):
src = textwrap.dedent("""
import time
@@ -765,6 +771,41 @@ class TestProcess(unittest.TestCase):
self.assertEqual(
mem.swap, sum([x.swap for x in maps]))
+ def test_open_files_mode(self):
+ def get_test_file():
+ p = psutil.Process()
+ giveup_at = time.time() + 2
+ while True:
+ for file in p.open_files():
+ if file.path == os.path.abspath(TESTFN):
+ return file
+ elif time.time() > giveup_at:
+ break
+ raise RuntimeError("timeout looking for test file")
+
+ #
+ with open(TESTFN, "w"):
+ self.assertEqual(get_test_file().mode, "w")
+ with open(TESTFN, "r"):
+ self.assertEqual(get_test_file().mode, "r")
+ with open(TESTFN, "a"):
+ self.assertEqual(get_test_file().mode, "a")
+ #
+ with open(TESTFN, "r+"):
+ self.assertEqual(get_test_file().mode, "r+")
+ with open(TESTFN, "w+"):
+ self.assertEqual(get_test_file().mode, "r+")
+ with open(TESTFN, "a+"):
+ self.assertEqual(get_test_file().mode, "a+")
+ # note: "x" bit is not supported
+ if PY3:
+ safe_remove(TESTFN)
+ with open(TESTFN, "x"):
+ self.assertEqual(get_test_file().mode, "w")
+ safe_remove(TESTFN)
+ with open(TESTFN, "x+"):
+ self.assertEqual(get_test_file().mode, "r+")
+
def test_open_files_file_gone(self):
# simulates a file which gets deleted during open_files()
# execution
diff --git a/psutil/tests/test_process.py b/psutil/tests/test_process.py
index 1c7993de..1af2f3d1 100644
--- a/psutil/tests/test_process.py
+++ b/psutil/tests/test_process.py
@@ -1704,6 +1704,7 @@ class TestFetchAllProcesses(unittest.TestCase):
if LINUX:
self.assertIsInstance(f.position, int)
self.assertGreaterEqual(f.position, 0)
+ self.assertIn(f.mode, ('r', 'w', 'a', 'r+', 'a+'))
if BSD and not f.path:
# XXX see: https://github.com/giampaolo/psutil/issues/595
continue