summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2020-10-24 23:00:48 +0300
committerGiampaolo Rodola <g.rodola@gmail.com>2020-10-24 23:00:48 +0300
commit0d5302ccb06767dfd31a28a78c891aa53f204d2a (patch)
tree96634f3ad79e8ab2cbfbf13e54d94961475f1a91
parent06c265bafc204be4b8cbc8bbf10213397750e7a0 (diff)
parent40abe5c0aa3e258161284b58cedcee1e11a66e75 (diff)
downloadpsutil-0d5302ccb06767dfd31a28a78c891aa53f204d2a.tar.gz
merge from master
-rw-r--r--HISTORY.rst5
-rw-r--r--README.rst4
-rw-r--r--docs/index.rst30
-rw-r--r--psutil/__init__.py18
-rw-r--r--psutil/_common.py3
-rw-r--r--psutil/_psaix.py4
-rw-r--r--psutil/_psbsd.py4
-rw-r--r--psutil/_pslinux.py4
-rw-r--r--psutil/_psosx.py4
-rw-r--r--psutil/_pssunos.py4
-rw-r--r--psutil/_psutil_bsd.c5
-rw-r--r--psutil/arch/freebsd/specific.c24
-rw-r--r--psutil/arch/windows/disk.c30
-rwxr-xr-xpsutil/tests/test_contracts.py2
-rwxr-xr-xpsutil/tests/test_system.py20
15 files changed, 110 insertions, 51 deletions
diff --git a/HISTORY.rst b/HISTORY.rst
index 0c24144a..54f2d79f 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -5,6 +5,11 @@
XXXX-XX-XX
+**Enhancements**
+
+- 1875_: `disk_partitions()` exposes 2 extra fields: `maxfile` and `maxpath`,
+ which are the maximum file name and path name length.
+
5.7.3
=====
diff --git a/README.rst b/README.rst
index 70fe8323..3b28ee5c 100644
--- a/README.rst
+++ b/README.rst
@@ -206,8 +206,8 @@ Disks
.. code-block:: python
>>> psutil.disk_partitions()
- [sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'),
- sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')]
+ [sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid', maxfile=255, maxpath=4096),
+ sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw', maxfile=255, maxpath=4096)]
>>>
>>> psutil.disk_usage('/')
sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)
diff --git a/docs/index.rst b/docs/index.rst
index bcf8d9b8..86b7ad1d 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -410,19 +410,27 @@ Disks
(e.g. pseudo, memory, duplicate, inaccessible filesystems).
Note that this may not be fully reliable on all systems (e.g. on BSD this
parameter is ignored).
- Named tuple's **fstype** field is a string which varies depending on the
- platform.
- On Linux it can be one of the values found in /proc/filesystems (e.g.
- ``'ext3'`` for an ext3 hard drive o ``'iso9660'`` for the CD-ROM drive).
- On Windows it is determined via `GetDriveType`_ and can be either
- ``"removable"``, ``"fixed"``, ``"remote"``, ``"cdrom"``, ``"unmounted"`` or
- ``"ramdisk"``. On macOS and BSD it is retrieved via `getfsstat`_ syscall.
See `disk_usage.py`_ script providing an example usage.
+ Returns a list of namedtuples with the following fields:
+
+ * **device**: the device path (e.g. ``"/dev/hda1"``). On Windows this is the
+ drive letter (e.g. ``"C:\\"``).
+ * **mountpoint**: the mount point path (e.g. ``"/"``). On Windows this is the
+ drive letter (e.g. ``"C:\\"``).
+ * **fstype**: the partition filesystem (e.g. ``"ext3"`` on UNIX or ``"NTFS"``
+ on Windows).
+ * **opts**: a comma-separated string indicating different mount options for
+ the drive/partition. Platform-dependent.
+ * **maxfile**: the maximum length a file name can have.
+ * **maxpath**: the maximum length a path name (directory name + base file
+ name) can have.
- >>> import psutil
- >>> psutil.disk_partitions()
- [sdiskpart(device='/dev/sda3', mountpoint='/', fstype='ext4', opts='rw,errors=remount-ro'),
- sdiskpart(device='/dev/sda7', mountpoint='/home', fstype='ext4', opts='rw')]
+ >>> import psutil
+ >>> psutil.disk_partitions()
+ [sdiskpart(device='/dev/sda3', mountpoint='/', fstype='ext4', opts='rw,errors=remount-ro', maxfile=255, maxpath=4096),
+ sdiskpart(device='/dev/sda7', mountpoint='/home', fstype='ext4', opts='rw', maxfile=255, maxpath=4096)]
+
+ .. versionchanged:: 5.7.4 added *maxfile* and *maxpath* fields
.. function:: disk_usage(path)
diff --git a/psutil/__init__.py b/psutil/__init__.py
index b2a6efd5..829bb33e 100644
--- a/psutil/__init__.py
+++ b/psutil/__init__.py
@@ -2002,7 +2002,23 @@ def disk_partitions(all=False):
If *all* parameter is False return physical devices only and ignore
all others.
"""
- return _psplatform.disk_partitions(all)
+ def pathconf(path, name):
+ try:
+ return os.pathconf(path, name)
+ except (OSError, AttributeError):
+ pass
+
+ ret = _psplatform.disk_partitions(all)
+ if POSIX:
+ new = []
+ for item in ret:
+ nt = item._replace(
+ maxfile=pathconf(item.mountpoint, 'PC_NAME_MAX'),
+ maxpath=pathconf(item.mountpoint, 'PC_PATH_MAX'))
+ new.append(nt)
+ return new
+ else:
+ return ret
def disk_io_counters(perdisk=False, nowrap=True):
diff --git a/psutil/_common.py b/psutil/_common.py
index b7a54786..771461d6 100644
--- a/psutil/_common.py
+++ b/psutil/_common.py
@@ -178,7 +178,8 @@ sdiskio = namedtuple('sdiskio', ['read_count', 'write_count',
'read_bytes', 'write_bytes',
'read_time', 'write_time'])
# psutil.disk_partitions()
-sdiskpart = namedtuple('sdiskpart', ['device', 'mountpoint', 'fstype', 'opts'])
+sdiskpart = namedtuple('sdiskpart', ['device', 'mountpoint', 'fstype', 'opts',
+ 'maxfile', 'maxpath'])
# psutil.net_io_counters()
snetio = namedtuple('snetio', ['bytes_sent', 'bytes_recv',
'packets_sent', 'packets_recv',
diff --git a/psutil/_psaix.py b/psutil/_psaix.py
index 994366aa..57d5378a 100644
--- a/psutil/_psaix.py
+++ b/psutil/_psaix.py
@@ -189,7 +189,9 @@ def disk_partitions(all=False):
# filter by filesystem having a total size > 0.
if not disk_usage(mountpoint).total:
continue
- ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
+ maxfile = maxpath = None # set later
+ ntuple = _common.sdiskpart(device, mountpoint, fstype, opts,
+ maxfile, maxpath)
retlist.append(ntuple)
return retlist
diff --git a/psutil/_psbsd.py b/psutil/_psbsd.py
index 428c8bde..f0a0c144 100644
--- a/psutil/_psbsd.py
+++ b/psutil/_psbsd.py
@@ -328,7 +328,9 @@ def disk_partitions(all=False):
partitions = cext.disk_partitions()
for partition in partitions:
device, mountpoint, fstype, opts = partition
- ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
+ maxfile = maxpath = None # set later
+ ntuple = _common.sdiskpart(device, mountpoint, fstype, opts,
+ maxfile, maxpath)
retlist.append(ntuple)
return retlist
diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py
index 683cef5d..b17b96a2 100644
--- a/psutil/_pslinux.py
+++ b/psutil/_pslinux.py
@@ -1171,7 +1171,9 @@ def disk_partitions(all=False):
if not all:
if device == '' or fstype not in fstypes:
continue
- ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
+ maxfile = maxpath = None # set later
+ ntuple = _common.sdiskpart(device, mountpoint, fstype, opts,
+ maxfile, maxpath)
retlist.append(ntuple)
return retlist
diff --git a/psutil/_psosx.py b/psutil/_psosx.py
index 6a189931..be22b48d 100644
--- a/psutil/_psosx.py
+++ b/psutil/_psosx.py
@@ -201,7 +201,9 @@ def disk_partitions(all=False):
if not all:
if not os.path.isabs(device) or not os.path.exists(device):
continue
- ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
+ maxfile = maxpath = None # set later
+ ntuple = _common.sdiskpart(device, mountpoint, fstype, opts,
+ maxfile, maxpath)
retlist.append(ntuple)
return retlist
diff --git a/psutil/_pssunos.py b/psutil/_pssunos.py
index 62362b89..c64ea9ca 100644
--- a/psutil/_pssunos.py
+++ b/psutil/_pssunos.py
@@ -233,7 +233,9 @@ def disk_partitions(all=False):
# https://github.com/giampaolo/psutil/issues/1674
debug("skipping %r: %r" % (mountpoint, err))
continue
- ntuple = _common.sdiskpart(device, mountpoint, fstype, opts)
+ maxfile = maxpath = None # set later
+ ntuple = _common.sdiskpart(device, mountpoint, fstype, opts,
+ maxfile, maxpath)
retlist.append(ntuple)
return retlist
diff --git a/psutil/_psutil_bsd.c b/psutil/_psutil_bsd.c
index 6933260a..c1b811c6 100644
--- a/psutil/_psutil_bsd.c
+++ b/psutil/_psutil_bsd.c
@@ -443,17 +443,12 @@ psutil_proc_environ(PyObject *self, PyObject *args) {
// On *BSD kernels there are a few kernel-only system processes without an
// environment (See e.g. "procstat -e 0 | 1 | 2 ..." on FreeBSD.)
- //
// Some system process have no stats attached at all
// (they are marked with P_SYSTEM.)
- //
// On FreeBSD, it's possible that the process is swapped or paged out,
// then there no access to the environ stored in the process' user area.
- //
// On NetBSD, we cannot call kvm_getenvv2() for a zombie process.
- //
// To make unittest suite happy, return an empty environment.
- //
#if defined(PSUTIL_FREEBSD)
#if (defined(__FreeBSD_version) && __FreeBSD_version >= 700000)
if (!((p)->ki_flag & P_INMEM) || ((p)->ki_flag & P_SYSTEM)) {
diff --git a/psutil/arch/freebsd/specific.c b/psutil/arch/freebsd/specific.c
index fcfce131..e7517a40 100644
--- a/psutil/arch/freebsd/specific.c
+++ b/psutil/arch/freebsd/specific.c
@@ -1142,19 +1142,19 @@ psutil_proc_setrlimit(PyObject *self, PyObject *args) {
name[4] = resource;
#if defined(HAVE_LONG_LONG)
- new.rlim_cur = PyLong_AsLongLong(py_soft);
- if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred())
- return NULL;
- new.rlim_max = PyLong_AsLongLong(py_hard);
- if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred())
- return NULL;
+ new.rlim_cur = PyLong_AsLongLong(py_soft);
+ if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred())
+ return NULL;
+ new.rlim_max = PyLong_AsLongLong(py_hard);
+ if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred())
+ return NULL;
#else
- new.rlim_cur = PyLong_AsLong(py_soft);
- if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred())
- return NULL;
- new.rlim_max = PyLong_AsLong(py_hard);
- if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred())
- return NULL;
+ new.rlim_cur = PyLong_AsLong(py_soft);
+ if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred())
+ return NULL;
+ new.rlim_max = PyLong_AsLong(py_hard);
+ if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred())
+ return NULL;
#endif
newp = &new;
ret = sysctl(name, 5, NULL, 0, newp, sizeof(*newp));
diff --git a/psutil/arch/windows/disk.c b/psutil/arch/windows/disk.c
index 45e0ee1e..92171fe5 100644
--- a/psutil/arch/windows/disk.c
+++ b/psutil/arch/windows/disk.c
@@ -206,6 +206,7 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
BOOL mp_flag= TRUE;
LPTSTR fs_type[MAX_PATH + 1] = { 0 };
DWORD pflags = 0;
+ DWORD lpMaximumComponentLength = 0; // max file name
PyObject *py_all;
PyObject *py_retlist = PyList_New(0);
PyObject *py_tuple = NULL;
@@ -257,8 +258,14 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
}
ret = GetVolumeInformation(
- (LPCTSTR)drive_letter, NULL, _ARRAYSIZE(drive_letter),
- NULL, NULL, &pflags, (LPTSTR)fs_type, _ARRAYSIZE(fs_type));
+ (LPCTSTR)drive_letter,
+ NULL,
+ _ARRAYSIZE(drive_letter),
+ NULL,
+ &lpMaximumComponentLength,
+ &pflags,
+ (LPTSTR)fs_type,
+ _ARRAYSIZE(fs_type));
if (ret == 0) {
// We might get here in case of a floppy hard drive, in
// which case the error is (21, "device not ready").
@@ -274,6 +281,8 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
strcat_s(opts, _countof(opts), "rw");
if (pflags & FILE_VOLUME_IS_COMPRESSED)
strcat_s(opts, _countof(opts), ",compressed");
+ if (pflags & FILE_READ_ONLY_VOLUME)
+ strcat_s(opts, _countof(opts), ",readonly");
// Check for mount points on this volume and add/get info
// (checks first to know if we can even have mount points)
@@ -282,17 +291,19 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
drive_letter, mp_buf, MAX_PATH);
if (mp_h != INVALID_HANDLE_VALUE) {
while (mp_flag) {
-
// Append full mount path with drive letter
strcpy_s(mp_path, _countof(mp_path), drive_letter);
strcat_s(mp_path, _countof(mp_path), mp_buf);
py_tuple = Py_BuildValue(
- "(ssss)",
+ "(ssssIi)",
drive_letter,
mp_path,
- fs_type, // Typically NTFS
- opts);
+ fs_type, // typically "NTFS"
+ opts,
+ lpMaximumComponentLength, // max file length
+ MAX_PATH // max path length
+ );
if (!py_tuple ||
PyList_Append(py_retlist, py_tuple) == -1) {
@@ -317,11 +328,14 @@ psutil_disk_partitions(PyObject *self, PyObject *args) {
strcat_s(opts, _countof(opts), psutil_get_drive_type(type));
py_tuple = Py_BuildValue(
- "(ssss)",
+ "(ssssIi)",
drive_letter,
drive_letter,
fs_type, // either FAT, FAT32, NTFS, HPFS, CDFS, UDF or NWFS
- opts);
+ opts,
+ lpMaximumComponentLength, // max file length
+ MAX_PATH // max path length
+ );
if (!py_tuple)
goto error;
if (PyList_Append(py_retlist, py_tuple))
diff --git a/psutil/tests/test_contracts.py b/psutil/tests/test_contracts.py
index 39a52569..72fe8c0c 100755
--- a/psutil/tests/test_contracts.py
+++ b/psutil/tests/test_contracts.py
@@ -242,6 +242,8 @@ class TestSystemAPITypes(PsutilTestCase):
self.assertIsInstance(disk.mountpoint, str)
self.assertIsInstance(disk.fstype, str)
self.assertIsInstance(disk.opts, str)
+ self.assertIsInstance(disk.maxfile, int)
+ self.assertIsInstance(disk.maxpath, int)
@unittest.skipIf(SKIP_SYSCONS, "requires root")
def test_net_connections(self):
diff --git a/psutil/tests/test_system.py b/psutil/tests/test_system.py
index 787397ad..bb6d2b89 100755
--- a/psutil/tests/test_system.py
+++ b/psutil/tests/test_system.py
@@ -592,6 +592,16 @@ class TestDiskAPIs(PsutilTestCase):
psutil.disk_usage(b'.')
def test_disk_partitions(self):
+ def check_ntuple(nt):
+ self.assertIsInstance(nt.device, str)
+ self.assertIsInstance(nt.mountpoint, str)
+ self.assertIsInstance(nt.fstype, str)
+ self.assertIsInstance(nt.opts, str)
+ self.assertIsInstance(nt.maxfile, int)
+ self.assertIsInstance(nt.maxpath, int)
+ self.assertGreater(nt.maxfile, 0)
+ self.assertGreater(nt.maxpath, 0)
+
# all = False
ls = psutil.disk_partitions(all=False)
# on travis we get:
@@ -599,10 +609,7 @@ class TestDiskAPIs(PsutilTestCase):
# AssertionError: Lists differ: [0, 1, 2, 3, 4, 5, 6, 7,... != [0]
self.assertTrue(ls, msg=ls)
for disk in ls:
- self.assertIsInstance(disk.device, str)
- self.assertIsInstance(disk.mountpoint, str)
- self.assertIsInstance(disk.fstype, str)
- self.assertIsInstance(disk.opts, str)
+ check_ntuple(disk)
if WINDOWS and 'cdrom' in disk.opts:
continue
if not POSIX:
@@ -619,6 +626,7 @@ class TestDiskAPIs(PsutilTestCase):
ls = psutil.disk_partitions(all=True)
self.assertTrue(ls, msg=ls)
for disk in psutil.disk_partitions(all=True):
+ check_ntuple(disk)
if not WINDOWS and disk.mountpoint:
try:
os.stat(disk.mountpoint)
@@ -632,8 +640,8 @@ class TestDiskAPIs(PsutilTestCase):
raise
else:
assert os.path.exists(disk.mountpoint), disk
- self.assertIsInstance(disk.fstype, str)
- self.assertIsInstance(disk.opts, str)
+
+ # ---
def find_mount_point(path):
path = os.path.abspath(path)