diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2020-10-24 23:00:48 +0300 |
---|---|---|
committer | Giampaolo Rodola <g.rodola@gmail.com> | 2020-10-24 23:00:48 +0300 |
commit | 0d5302ccb06767dfd31a28a78c891aa53f204d2a (patch) | |
tree | 96634f3ad79e8ab2cbfbf13e54d94961475f1a91 | |
parent | 06c265bafc204be4b8cbc8bbf10213397750e7a0 (diff) | |
parent | 40abe5c0aa3e258161284b58cedcee1e11a66e75 (diff) | |
download | psutil-0d5302ccb06767dfd31a28a78c891aa53f204d2a.tar.gz |
merge from master
-rw-r--r-- | HISTORY.rst | 5 | ||||
-rw-r--r-- | README.rst | 4 | ||||
-rw-r--r-- | docs/index.rst | 30 | ||||
-rw-r--r-- | psutil/__init__.py | 18 | ||||
-rw-r--r-- | psutil/_common.py | 3 | ||||
-rw-r--r-- | psutil/_psaix.py | 4 | ||||
-rw-r--r-- | psutil/_psbsd.py | 4 | ||||
-rw-r--r-- | psutil/_pslinux.py | 4 | ||||
-rw-r--r-- | psutil/_psosx.py | 4 | ||||
-rw-r--r-- | psutil/_pssunos.py | 4 | ||||
-rw-r--r-- | psutil/_psutil_bsd.c | 5 | ||||
-rw-r--r-- | psutil/arch/freebsd/specific.c | 24 | ||||
-rw-r--r-- | psutil/arch/windows/disk.c | 30 | ||||
-rwxr-xr-x | psutil/tests/test_contracts.py | 2 | ||||
-rwxr-xr-x | psutil/tests/test_system.py | 20 |
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 ===== @@ -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) |