Hello community,

here is the log from the commit of package iotop for openSUSE:Factory checked 
in at 2013-03-25 20:30:57
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/iotop (Old)
 and      /work/SRC/openSUSE:Factory/.iotop.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "iotop", Maintainer is "[email protected]"

Changes:
--------
--- /work/SRC/openSUSE:Factory/iotop/iotop.changes      2011-11-02 
11:54:05.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.iotop.new/iotop.changes 2013-03-25 
20:31:31.000000000 +0100
@@ -1,0 +2,9 @@
+Sun Mar  3 07:44:09 UTC 2013 - [email protected]
+
+- Update to version 0.5:
+  + Adapt the display to the maximum pid width.
+  + Include both total and actual disk bandwidth in the summary.
+  + Conversion to Python 3.
+  + Installation to sbin instead of bin.
+
+-------------------------------------------------------------------

Old:
----
  iotop-0.4.4.tar.bz2

New:
----
  iotop-0.5.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ iotop.spec ++++++
--- /var/tmp/diff_new_pack.FSeEBM/_old  2013-03-25 20:31:32.000000000 +0100
+++ /var/tmp/diff_new_pack.FSeEBM/_new  2013-03-25 20:31:32.000000000 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package iotop
 #
-# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,16 +19,16 @@
 %{!?python_sitelib: %global python_sitelib %(%{__python} -c "from 
distutils.sysconfig import get_python_lib; print(get_python_lib())")}
 
 Name:           iotop
-Version:        0.4.4
-Release:        1
+Version:        0.5
+Release:        0
 Summary:        Top Like UI to Show Per-Process I/O Going on
+License:        GPL-2.0
+Group:          System/Monitoring
 Source:         http://guichaz.free.fr/iotop/files/iotop-%{version}.tar.bz2
 Source1:        %{name}-rpmlintrc
 Url:            http://guichaz.free.fr/iotop/
-Group:          System/Monitoring
-License:        GPL-2.0
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
-BuildRequires:  python-devel >= 2.5
+BuildRequires:  python-devel >= 2.7
 Requires:       python-curses
 %if 0%{?suse_version} >= 1120
 BuildArch:      noarch

++++++ iotop-0.4.4.tar.bz2 -> iotop-0.5.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/.gitignore new/iotop-0.5/.gitignore
--- old/iotop-0.4.4/.gitignore  2011-10-30 21:36:22.000000000 +0100
+++ new/iotop-0.5/.gitignore    2013-02-03 19:50:02.000000000 +0100
@@ -1 +1,2 @@
 *.pyc
+/build/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/ChangeLog new/iotop-0.5/ChangeLog
--- old/iotop-0.4.4/ChangeLog   2011-10-30 21:56:10.000000000 +0100
+++ new/iotop-0.5/ChangeLog     2013-02-03 20:12:50.000000000 +0100
@@ -1,3 +1,120 @@
+2013-02-03  Guillaume Chazarain <[email protected]>
+
+       * README, iotop/data.py: Update python requirements
+
+2013-02-03  Guillaume Chazarain <[email protected]>
+
+       * NEWS: Also advertise the move to sbin/ as it's significant
+
+2013-02-03  Guillaume Chazarain <[email protected]>
+
+       * .install-rpm.sh: The RPM should also install to sbin.
+
+2013-02-03  Guillaume Chazarain <[email protected]>
+
+       * bin/iotop, sbin/iotop: Moved to sbin.
+
+2013-02-03  Guillaume Chazarain <[email protected]>
+
+       * .install-rpm.sh, MANIFEST.in: Finish man page renaming
+
+2013-02-03  Guillaume Chazarain <[email protected]>
+
+       * NEWS, iotop/version.py: Version bump
+
+2013-02-03  Guillaume Chazarain <[email protected]>
+
+       * NEWS, THANKS: Advertise the newly introduced differentiation
+       between total and actual I/O.
+
+2013-02-03  Guillaume Chazarain <[email protected]>
+
+       * iotop/ui.py: 80 cols
+
+2012-10-10  Igor Bazhitov <[email protected]>
+
+       * iotop.8, iotop/data.py, iotop/ui.py: Add 'Actual' bandwidth stats
+       to summary header 'Total' values in the summary header may look 
confusing to users.
+       They represent actual kernel <-> disk I/O bandwidth, while
+       individual values for processes/threads show process <-> kernel I/O
+       bandwidth.  Rename 'Total' to 'Actual' and add old 'Total' status line 
that sums
+       up all individual process/thread bandwidths. Explain the difference
+       between 'Total' and 'Actual' in the manpage.
+
+2012-10-09  Igor Bazhitov <[email protected]>
+
+       * README: Update manpage name in README
+
+2012-12-05  Paul Wise <[email protected]>
+
+       * iotop/data.py: Fix crash when running under python3.  This reverts 
cd6ffb5913664844290f44a7ea48533caf8c459e Traceback (most recent call last):   
File "./iotop.py", line 12, in <module>     main()   File 
"./iotop/iotop/ui.py", line 597, in main     main_loop()   File 
"./iotop/iotop/ui.py", line 587, in <lambda>     main_loop = lambda: 
run_iotop(options)   File "./iotop/iotop/ui.py", line 485, in run_iotop     
return curses.wrapper(run_iotop_window, options)   File 
"/usr/lib/python3.2/curses/wrapper.py", line 43, in wrapper     return 
func(stdscr, *args, **kwds)   File "./iotop/iotop/ui.py", line 478, in 
run_iotop_window     ui.run()   File "./iotop/iotop/ui.py", line 153, in run    
 total = self.process_list.refresh_processes()   File "./iotop/iotop/data.py", 
line 459, in refresh_processes     self.processes.items() if   File 
"./iotop/iotop/data.py", line 460, in <listcomp>     process.update_stats()])   
File "./iotop/iotop/data.py", line 358, in update_stats     for tid, thread in 
self.threads.items(): RuntimeError:
+       dictionary changed size during iteration [This is valid since 
0fc4ab84c8cbba1fbe83dc71fb89100b87c54898  added the self.threads = dict(...)]
+
+2012-09-02  Paul Wise <[email protected]>
+
+       * iotop.1, iotop.8, setup.py: Move iotop out of the path for users
+
+2012-09-03  Guillaume Chazarain <[email protected]>
+
+       * iotop/ui.py: Fix the setting of the I/O priority and advertise it
+       a litle more.
+
+2012-09-03  Guillaume Chazarain <[email protected]>
+
+       * iotop/ui.py: Here we print a string, not bytes.
+
+2012-09-03  Guillaume Chazarain <[email protected]>
+
+       * iotop/netlink.py: Remove stray print added during the python3
+       conversion.
+
+2012-09-03  Guillaume Chazarain <[email protected]>
+
+       * iotop/data.py: Restore compatibility with python2
+
+2012-09-03  Guillaume Chazarain <[email protected]>
+
+       * iotop/data.py: Put back code deleted in the python3 conversion
+
+2012-09-03  Guillaume Chazarain <[email protected]>
+
+       * iotop/data.py: Some missed python3 conversions
+
+2012-09-03  Guillaume Chazarain <[email protected]>
+
+       * iotop/data.py, iotop/ui.py: Cosmetic fixes
+
+2012-09-02  Paul Wise <[email protected]>
+
+       * iotop/data.py, iotop/genetlink.py, iotop/ioprio.py,
+       iotop/netlink.py, iotop/ui.py: Port to Python 3 Not entirely sure about 
all parts of this but it works in Python 2/3
+
+2012-09-03  Guillaume Chazarain <[email protected]>
+
+       * THANKS, iotop/data.py: Show custom thread names.
+
+2012-05-13  Paul Wise <[email protected]>
+
+       * iotop/ui.py: Improve the message that is printed when Linux denies
+       access to taskstats.
+
+2012-03-08  Guillaume Chazarain <[email protected]>
+
+       * README: Consistent option names
+
+2012-01-22  Guillaume Chazarain <[email protected]>
+
+       * iotop/ui.py: Restore the default SIGPIPE handler so that sudo
+       ./iotop.py -b|head does what's expected.
+
+2012-01-22  Guillaume Chazarain <[email protected]>
+
+       * NEWS, iotop/ui.py: Adapt the display to the maximum pid width
+
+2012-01-18  Guillaume Chazarain <[email protected]>
+
+       * .gitignore: Ignore the build directory.
+
 2011-10-30  Guillaume Chazarain <[email protected]>
 
        * .install-rpm.sh, setup.cfg: Actually install-rpm.sh is still
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/NEWS new/iotop-0.5/NEWS
--- old/iotop-0.4.4/NEWS        2011-10-30 21:36:22.000000000 +0100
+++ new/iotop-0.5/NEWS  2013-02-03 19:50:02.000000000 +0100
@@ -1,3 +1,10 @@
+0.5
+~~~
+o Adapt the display to the maximum pid width
+o Include both total and actual disk bandwidth in the summary
+o Conversion to Python 3
+o Installation to sbin instead of bin
+
 0.4.4
 ~~~~~
 o Cosmetic fixes, including a better error message when missing root
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/PKG-INFO new/iotop-0.5/PKG-INFO
--- old/iotop-0.4.4/PKG-INFO    2011-10-30 21:56:10.000000000 +0100
+++ new/iotop-0.5/PKG-INFO      2013-02-03 20:12:50.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: iotop
-Version: 0.4.4
+Version: 0.5
 Summary: Per process I/O bandwidth monitor
 Home-page: http://guichaz.free.fr/iotop
 Author: Guillaume Chazarain
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/README new/iotop-0.5/README
--- old/iotop-0.4.4/README      2011-10-30 21:36:22.000000000 +0100
+++ new/iotop-0.5/README        2013-02-03 19:50:02.000000000 +0100
@@ -1,7 +1,7 @@
 Iotop is a Python program with a top like UI used to show of behalf of which
-process is the I/O going on. It requires Python >= 2.5 (or Python >= 2.4 with
-the ctypes module) and a Linux kernel >= 2.6.20 with the TASK_DELAY_ACCT
-CONFIG_TASKSTATS, TASK_IO_ACCOUNTING and CONFIG_VM_EVENT_COUNTERS options on.
+process is the I/O going on. It requires Python >= 2.7 and a Linux kernel >=
+2.6.20 with the CONFIG_TASK_DELAY_ACCT CONFIG_TASKSTATS,
+CONFIG_TASK_IO_ACCOUNTING and CONFIG_VM_EVENT_COUNTERS options on.
 
 
 To run a local version of iotop:
@@ -11,7 +11,7 @@
 
 The documentation is available in the man page:
 
-$ man ./iotop.1
+$ man ./iotop.8
 
 
 To install iotop, you should use a package provided by your distribution. If 
you
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/THANKS new/iotop-0.5/THANKS
--- old/iotop-0.4.4/THANKS      2011-10-30 21:36:22.000000000 +0100
+++ new/iotop-0.5/THANKS        2013-02-03 19:50:02.000000000 +0100
@@ -42,3 +42,9 @@
 
 Florian Mickler <[email protected]>
     Contributed a fixed implementation of the taskstats parsing code.
+
+Ka-Hing Cheung <[email protected]>
+    Contributed code to show custom thread names.
+
+Igor Bazhitov <[email protected]>
+    Contributed the differentiation between total and actual I/O.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/bin/iotop new/iotop-0.5/bin/iotop
--- old/iotop-0.4.4/bin/iotop   2011-10-30 21:36:22.000000000 +0100
+++ new/iotop-0.5/bin/iotop     1970-01-01 01:00:00.000000000 +0100
@@ -1,19 +0,0 @@
-#!/usr/bin/python
-# iotop: Display I/O usage of processes in a top like UI
-# Copyright (c) 2007, 2008 Guillaume Chazarain <[email protected]>, GPLv2
-# See iotop --help for some help
-
-import sys
-
-try:
-    from iotop.ui import main
-except ImportError, e:
-    print e
-    print 'To run an uninstalled copy of iotop,'
-    print 'launch iotop.py in the top directory'
-else:
-    try:
-        main()
-    except KeyboardInterrupt:
-        pass
-    sys.exit(0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/iotop/data.py new/iotop-0.5/iotop/data.py
--- old/iotop-0.4.4/iotop/data.py       2011-10-30 21:36:22.000000000 +0100
+++ new/iotop-0.5/iotop/data.py 2013-02-03 19:50:02.000000000 +0100
@@ -16,6 +16,9 @@
 #
 # Copyright (c) 2007 Guillaume Chazarain <[email protected]>
 
+# Allow printing with same syntax in Python 2/3
+from __future__ import print_function
+
 import errno
 import os
 import pprint
@@ -28,19 +31,11 @@
 #
 # Check for requirements:
 #   o Linux >= 2.6.20 with I/O accounting and VM event counters
-#   o Python >= 2.5 or Python 2.4 + ctypes
 #
 
 ioaccounting = os.path.exists('/proc/self/io')
 
 try:
-    import ctypes
-except ImportError:
-    has_ctypes = False
-else:
-    has_ctypes = True
-
-try:
     from iotop.vmstat import VmStat
     vmstat_f = VmStat()
 except:
@@ -48,24 +43,20 @@
 else:
     vm_event_counters = True
 
-if not ioaccounting or not has_ctypes or not vm_event_counters:
-    print 'Could not run iotop as some of the requirements are not met:'
-    if not ioaccounting or not vm_event_counters:
-        print '- Linux >= 2.6.20 with'
-        if not ioaccounting:
-            print '  - I/O accounting support ' \
-              '(CONFIG_TASKSTATS, CONFIG_TASK_DELAY_ACCT, ' \
-              'CONFIG_TASK_IO_ACCOUNTING)'
-        if not vm_event_counters:
-            print '  - VM event counters (CONFIG_VM_EVENT_COUNTERS)'
-    if not has_ctypes:
-        print '- Python >= 2.5 or Python 2.4 with the ctypes module'
-
+if not ioaccounting or not vm_event_counters:
+    print('Could not run iotop as some of the requirements are not met:')
+    print('- Linux >= 2.6.20 with')
+    if not ioaccounting:
+        print('  - I/O accounting support ' \
+          '(CONFIG_TASKSTATS, CONFIG_TASK_DELAY_ACCT, ' \
+          'CONFIG_TASK_IO_ACCOUNTING)')
+    if not vm_event_counters:
+        print('  - VM event counters (CONFIG_VM_EVENT_COUNTERS)')
     sys.exit(1)
 
 from iotop import ioprio, vmstat
-from netlink import Connection, NETLINK_GENERIC, U32Attr, NLM_F_REQUEST
-from genetlink import Controller, GeNlMessage
+from iotop.netlink import Connection, NETLINK_GENERIC, U32Attr, NLM_F_REQUEST
+from iotop.genetlink import Controller, GeNlMessage
 
 class DumpableObject(object):
     """Base class for all objects that allows easy introspection when 
printed"""
@@ -154,12 +145,12 @@
         thread.task_stats_request.send(self.connection)
         try:
             reply = GeNlMessage.recv(self.connection)
-        except OSError, e:
+        except OSError as e:
             if e.errno == errno.ESRCH:
                 # OSError: Netlink error: No such process (3)
                 return
             raise
-        for attr_type, attr_value in reply.attrs.iteritems():
+        for attr_type, attr_value in reply.attrs.items():
             if attr_type == TASKSTATS_TYPE_AGGR_PID:
                 reply = attr_value.nested()
                 break
@@ -188,7 +179,7 @@
             try:
                 passwd = pwd.getpwnam(u)
             except KeyError:
-                print >> sys.stderr, 'Unknown user:', u
+                print('Unknown user:', u, file=sys.stderr)
                 error = True
             else:
                 uid = passwd.pw_uid
@@ -197,11 +188,25 @@
     if error:
         sys.exit(1)
 
+
+def parse_proc_pid_status(pid):
+    result_dict = {}
+    try:
+        for line in open('/proc/%d/status' % pid):
+            key, value = line.split(':\t', 1)
+            result_dict[key] = value.strip()
+    except IOError:
+        pass  # No such process
+    return result_dict
+
+
 def safe_utf8_decode(s):
     try:
         return s.decode('utf-8')
     except UnicodeDecodeError:
         return s.encode('string_escape')
+    except AttributeError:
+        return s
 
 class ThreadInfo(DumpableObject):
     """Stats for a single thread"""
@@ -273,26 +278,10 @@
         if uid is not None and not self.user:
             try:
                 self.user = safe_utf8_decode(pwd.getpwuid(uid).pw_name)
-            except KeyError:
+            except (KeyError, AttributeError):
                 self.user = str(uid)
         return self.user or '{none}'
 
-    def get_proc_status_name(self):
-        try:
-            first_line = open('/proc/%d/status' % self.pid).readline()
-        except IOError:
-            return '{no such process}'
-        prefix = 'Name:\t'
-        if first_line.startswith(prefix):
-            name = first_line[6:].strip()
-        else:
-            name = ''
-        if name:
-            name = '[%s]' % name
-        else:
-            name = '{no name}'
-        return name
-
     def get_cmdline(self):
         # A process may exec, so we must always reread its cmdline
         try:
@@ -300,32 +289,46 @@
             cmdline = proc_cmdline.read(4096)
         except IOError:
             return '{no such process}'
+        proc_status = parse_proc_pid_status(self.pid)
         if not cmdline:
             # Probably a kernel thread, get its name from /proc/PID/status
-            return self.get_proc_status_name()
+            proc_status_name = proc_status.get('Name', '')
+            if proc_status_name:
+                proc_status_name = '[%s]' % proc_status_name
+            else:
+                proc_status_name = '{no name}'
+            return proc_status_name
+        suffix = ''
+        tgid = int(proc_status.get('Tgid', self.pid))
+        if tgid != self.pid:
+            # Not the main thread, maybe it has a custom name
+            tgid_name = parse_proc_pid_status(tgid).get('Name', '')
+            thread_name = proc_status.get('Name', '')
+            if thread_name != tgid_name:
+                suffix += ' [%s]' % thread_name
         parts = cmdline.split('\0')
         if parts[0].startswith('/'):
             first_command_char = parts[0].rfind('/') + 1
             parts[0] = parts[0][first_command_char:]
         cmdline = ' '.join(parts).strip()
-        return safe_utf8_decode(cmdline)
+        return safe_utf8_decode(cmdline + suffix)
 
     def did_some_io(self, accumulated):
         if accumulated:
             return not self.stats_accum.is_all_zero()
-        for t in self.threads.itervalues():
+        for t in self.threads.values():
             if not t.stats_delta.is_all_zero():
                 return True
         return False
 
     def get_ioprio(self):
-        priorities = set(t.get_ioprio() for t in self.threads.itervalues())
+        priorities = set(t.get_ioprio() for t in self.threads.values())
         if len(priorities) == 1:
             return priorities.pop()
         return '?dif'
 
     def set_ioprio(self, ioprio_class, ioprio_data):
-        for thread in self.threads.itervalues():
+        for thread in self.threads.values():
             thread.set_ioprio(ioprio_class, ioprio_data)
 
     def ioprio_sort_key(self):
@@ -341,10 +344,10 @@
     def update_stats(self):
         stats_delta = Stats.build_all_zero()
         for tid, thread in self.threads.items():
-            if thread.mark:
-                del self.threads[tid]
-            else:
+            if not thread.mark:
                 stats_delta.accumulate(thread.stats_delta, stats_delta)
+        self.threads = dict([(tid, thread) for tid, thread in
+                             self.threads.items() if not thread.mark])
 
         nr_threads = len(self.threads)
         if not nr_threads:
@@ -404,7 +407,7 @@
             return [tgid]
 
         try:
-            tids = map(int, os.listdir('/proc/%d/task' % tgid))
+            tids = list(map(int, os.listdir('/proc/%d/task' % tgid)))
         except OSError:
             return []
 
@@ -418,6 +421,8 @@
         self.duration = new_timestamp - self.timestamp
         self.timestamp = new_timestamp
 
+        total_read = total_write = 0
+
         for tgid in self.list_tgids():
             process = self.get_process(tgid)
             if not process:
@@ -427,20 +432,22 @@
                 stats = self.taskstats_connection.get_single_task_stats(thread)
                 if stats:
                     thread.update_stats(stats)
+                    delta = thread.stats_delta
+                    total_read += delta.read_bytes
+                    total_write += delta.write_bytes
                     thread.mark = False
-
-        return self.vmstat.delta()
+        return (total_read, total_write), self.vmstat.delta()
 
     def refresh_processes(self):
-        for process in self.processes.itervalues():
-            for thread in process.threads.itervalues():
+        for process in self.processes.values():
+            for thread in process.threads.values():
                 thread.mark = True
 
         total_read_and_write = self.update_process_counts()
 
-        for pid, process in self.processes.items():
-            if not process.update_stats():
-                del self.processes[pid]
+        self.processes = dict([(pid, process) for pid, process in
+                               self.processes.items() if
+                               process.update_stats()])
 
         return total_read_and_write
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/iotop/genetlink.py 
new/iotop-0.5/iotop/genetlink.py
--- old/iotop-0.4.4/iotop/genetlink.py  2011-10-30 21:36:22.000000000 +0100
+++ new/iotop-0.5/iotop/genetlink.py    2013-02-03 19:50:02.000000000 +0100
@@ -7,8 +7,8 @@
 '''
 
 import struct
-from netlink import NLM_F_REQUEST, NLMSG_MIN_TYPE, Message, parse_attributes
-from netlink import NulStrAttr, Connection, NETLINK_GENERIC
+from iotop.netlink import NLM_F_REQUEST, NLMSG_MIN_TYPE, Message, 
parse_attributes
+from iotop.netlink import NulStrAttr, Connection, NETLINK_GENERIC
 
 CTRL_CMD_UNSPEC       = 0
 CTRL_CMD_NEWFAMILY    = 1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/iotop/ioprio.py 
new/iotop-0.5/iotop/ioprio.py
--- old/iotop-0.4.4/iotop/ioprio.py     2011-10-30 21:36:22.000000000 +0100
+++ new/iotop-0.5/iotop/ioprio.py       2013-02-03 19:50:02.000000000 +0100
@@ -175,6 +175,6 @@
         pid = int(sys.argv[1])
     else:
         pid = os.getpid()
-    print 'pid:', pid
-    print 'ioprio:', get(pid)
+    print('pid:', pid)
+    print('ioprio:', get(pid))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/iotop/netlink.py 
new/iotop-0.5/iotop/netlink.py
--- old/iotop-0.4.4/iotop/netlink.py    2011-10-30 21:36:22.000000000 +0100
+++ new/iotop-0.5/iotop/netlink.py      2013-02-03 19:50:02.000000000 +0100
@@ -102,7 +102,7 @@
         hdr = struct.pack("HH", len(self.data)+4, self.type)
         length = len(self.data)
         pad = ((length + 4 - 1) & ~3 ) - length
-        return hdr + self.data + '\0' * pad
+        return hdr + self.data + b'\0' * pad
 
     def __repr__(self):
         return '<Attr type %d, data "%s">' % (self.type, repr(self.data))
@@ -124,11 +124,11 @@
 
 class StrAttr(Attr):
     def __init__(self, attr_type, data):
-        Attr.__init__(self, attr_type, "%ds" % len(data), data)
+        Attr.__init__(self, attr_type, "%ds" % len(data), data.encode('utf-8'))
 
 class NulStrAttr(Attr):
     def __init__(self, attr_type, data):
-        Attr.__init__(self, attr_type, "%dsB" % len(data), data, 0)
+        Attr.__init__(self, attr_type, "%dsB" % len(data), 
data.encode('utf-8'), 0)
 
 class U32Attr(Attr):
     def __init__(self, attr_type, val):
@@ -181,7 +181,7 @@
             contents = []
             for attr in payload:
                 contents.append(attr._dump())
-            self.payload = ''.join(contents)
+            self.payload = b''.join(contents)
         else:
             self.payload = payload
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/iotop/ui.py new/iotop-0.5/iotop/ui.py
--- old/iotop-0.4.4/iotop/ui.py 2011-10-30 21:36:22.000000000 +0100
+++ new/iotop-0.5/iotop/ui.py   2013-02-03 19:50:02.000000000 +0100
@@ -16,6 +16,9 @@
 #
 # Copyright (c) 2007 Guillaume Chazarain <[email protected]>
 
+# Allow printing with same syntax in Python 2/3
+from __future__ import print_function
+
 import curses
 import errno
 import locale
@@ -23,14 +26,15 @@
 import optparse
 import os
 import select
+import signal
 import sys
 import time
 
 from iotop.data import find_uids, TaskStatsNetlink, ProcessList, Stats
 from iotop.data import ThreadInfo
 from iotop.version import VERSION
-import ioprio
-from ioprio import IoprioSetError
+from iotop import ioprio
+from iotop.ioprio import IoprioSetError
 
 #
 # Utility functions for the UI
@@ -79,6 +83,16 @@
     write_bytes = display_format(written_bytes, duration)
     return io_delay, swapin_delay, read_bytes, write_bytes
 
+def get_max_pid_width():
+    try:
+        return len(open('/proc/sys/kernel/pid_max').read().strip())
+    except Exception as e:
+        print(e)
+        # Reasonable default in case something fails
+        return 5
+
+MAX_PID_WIDTH = get_max_pid_width()
+
 #
 # UI Exceptions
 #
@@ -136,9 +150,8 @@
             poll.register(sys.stdin.fileno(), select.POLLIN|select.POLLPRI)
         while self.options.iterations is None or \
               iterations < self.options.iterations:
-            total = self.process_list.refresh_processes()
-            total_read, total_write = total
-            self.refresh_display(iterations == 0, total_read, total_write,
+            total, actual = self.process_list.refresh_processes()
+            self.refresh_display(iterations == 0, total, actual,
                                  self.process_list.duration)
             if self.options.iterations is not None:
                 iterations += 1
@@ -149,7 +162,7 @@
 
             try:
                 events = poll.poll(self.options.delay_seconds * 1000.0)
-            except select.error, e:
+            except select.error as e:
                 if e.args and e.args[0] == errno.EINTR:
                     events = 0
                 else:
@@ -304,7 +317,7 @@
                 exec_unit.set_ioprio(ioprio_class, ioprio_data)
                 self.process_list.clear()
                 self.process_list.refresh_processes()
-            except IoprioSetError, e:
+            except IoprioSetError as e:
                 self.prompt_error('Error setting I/O priority: %s' % e.err)
             except InvalidPid:
                 self.prompt_error('Invalid process id!')
@@ -365,7 +378,8 @@
                 delay_stats = '%7s %7s ' % (swapin_delay, io_delay)
             else:
                 delay_stats = ' ?unavailable?  '
-            line = '%5d %4s %-8s %11s %11s %s' % (
+            pid_format = '%%%dd' % MAX_PID_WIDTH
+            line = (pid_format + ' %4s %-8s %11s %11s %s') % (
                 p.pid, p.get_ioprio(), p.get_user()[:8], read_bytes,
                 write_bytes, delay_stats)
             cmdline = p.get_cmdline()
@@ -384,7 +398,8 @@
             return not self.options.only or \
                    p.did_some_io(self.options.accumulated)
 
-        processes = filter(should_format, self.process_list.processes.values())
+        processes = list(filter(should_format,
+                                self.process_list.processes.values()))
         key = IOTopUI.sorting_keys[self.sorting_key][0]
         if self.options.accumulated:
             stats_lambda = lambda p: p.stats_accum
@@ -394,16 +409,23 @@
                        reverse=self.sorting_reverse)
         if not self.options.batch:
             del processes[self.height - 2:]
-        return map(format, processes)
+        return list(map(format, processes))
+
+    def refresh_display(self, first_time, total, actual, duration):
+        summary = [
+                'Total DISK READ : %s | Total DISK WRITE : %s' % (
+                format_bandwidth(self.options, total[0], duration).rjust(14),
+                format_bandwidth(self.options, total[1], duration).rjust(14)),
+                'Actual DISK READ: %s | Actual DISK WRITE: %s' % (
+                format_bandwidth(self.options, actual[0], duration).rjust(14),
+                format_bandwidth(self.options, actual[1], duration).rjust(14))
+        ]
 
-    def refresh_display(self, first_time, total_read, total_write, duration):
-        summary = 'Total DISK READ: %s | Total DISK WRITE: %s' % (
-                format_bandwidth(self.options, total_read, duration).rjust(14),
-                format_bandwidth(self.options, total_write, 
duration).rjust(14))
+        pid = max(0, (MAX_PID_WIDTH - 3)) * ' '
         if self.options.processes:
-            pid = '  PID'
+            pid += 'PID'
         else:
-            pid = '  TID'
+            pid += 'TID'
         titles = [pid, '  PRIO', '  USER', '     DISK READ', '  DISK WRITE',
                   '  SWAPIN', '      IO', '    COMMAND']
         lines = self.get_data()
@@ -411,21 +433,24 @@
             titles = ['    TIME'] + titles
             current_time = time.strftime('%H:%M:%S ')
             lines = [current_time + l for l in lines]
-            summary = current_time + summary
+            summary = [current_time + s for s in summary]
         if self.options.batch:
             if self.options.quiet <= 2:
-                print summary
+                for s in summary:
+                    print(s)
                 if self.options.quiet <= int(first_time):
-                    print ''.join(titles)
+                    print(''.join(titles))
             for l in lines:
-                print l.encode('utf-8')
+                print(l)
             sys.stdout.flush()
         else:
             self.win.erase()
-            self.win.addstr(summary[:self.width])
-            self.win.hline(1, 0, ord(' ') | curses.A_REVERSE, self.width)
+            for i, s in enumerate(summary):
+                self.win.addstr(i, 0, s[:self.width])
+            self.win.hline(len(summary), 0, ord(' ') | curses.A_REVERSE,
+                           self.width)
             remaining_cols = self.width
-            for i in xrange(len(titles)):
+            for i in range(len(titles)):
                 attr = curses.A_REVERSE
                 title = titles[i]
                 if i == self.sorting_key:
@@ -442,16 +467,19 @@
                 status_msg = ('CONFIG_TASK_DELAY_ACCT not enabled in kernel, '
                               'cannot determine SWAPIN and IO %')
             num_lines = min(len(lines), self.height - 2 - 
int(bool(status_msg)))
-            for i in xrange(num_lines):
+            for i in range(num_lines):
                 try:
-                    self.win.addstr(i + 2, 0, lines[i].encode('utf-8'))
+                    self.win.addstr(i + len(summary) + 1, 0, lines[i])
                 except curses.error:
                     pass
             if status_msg:
-                self.win.insstr(self.height - 1, 0, status_msg, curses.A_BOLD)
+                self.win.insstr(self.height - len(summary), 0, status_msg,
+                                curses.A_BOLD)
             self.win.refresh()
 
 def run_iotop_window(win, options):
+    if options.batch:
+        signal.signal(signal.SIGPIPE, signal.SIG_DFL)
     taskstats_connection = TaskStatsNetlink(options)
     process_list = ProcessList(taskstats_connection, options)
     ui = IOTopUI(win, process_list, options)
@@ -463,11 +491,17 @@
             return run_iotop_window(None, options)
         else:
             return curses.wrapper(run_iotop_window, options)
-    except OSError, e:
+    except OSError as e:
         if e.errno == errno.EPERM:
-            print >> sys.stderr, e
-            print >> sys.stderr, ('iotop requires root or the NET_ADMIN '
-                                  'capability.')
+            print(e, file=sys.stderr)
+            print('''
+The Linux kernel interfaces that iotop relies on now require root priviliges
+or the NET_ADMIN capability. This change occured because a security issue
+(CVE-2011-2494) was found that allows leakage of sensitive data across user
+boundaries. If you require the ability to run iotop as a non-root user, please
+configure sudo to allow you to run iotop as root.
+
+Please do not file bugs on iotop about this.''', file=sys.stderr)
             sys.exit(1)
         else:
             raise
@@ -481,14 +515,14 @@
     try:
         import cProfile
         import pstats
-        print 'Profiling using cProfile'
+        print('Profiling using cProfile')
         cProfile.runctx('continuation()', globals(), locals(), prof_file)
         stats = pstats.Stats(prof_file)
     except ImportError:
         import hotshot
         import hotshot.stats
         prof = hotshot.Profile(prof_file, lineevents=1)
-        print 'Profiling using hotshot'
+        print('Profiling using hotshot')
         prof.runcall(continuation)
         prof.close()
         stats = hotshot.stats.load(prof_file)
@@ -511,14 +545,14 @@
 
 Controls: left and right arrows to change the sorting column, r to invert the
 sorting order, o to toggle the --only option, p to toggle the --processes
-option, a to toggle the --accumulated option, q to quit, any other key to force
-a refresh.''' % sys.argv[0]
+option, a to toggle the --accumulated option, i to change I/O priority, q to
+quit, any other key to force a refresh.''' % sys.argv[0]
 
 def main():
     try:
         locale.setlocale(locale.LC_ALL, '')
     except locale.Error:
-        print 'unable to set locale, falling back to the default locale'
+        print('unable to set locale, falling back to the default locale')
     parser = optparse.OptionParser(usage=USAGE, version='iotop ' + VERSION)
     parser.add_option('-o', '--only', action='store_true',
                       dest='only', default=False,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/iotop/version.py 
new/iotop-0.5/iotop/version.py
--- old/iotop-0.4.4/iotop/version.py    2011-10-30 21:36:22.000000000 +0100
+++ new/iotop-0.5/iotop/version.py      2013-02-03 19:50:02.000000000 +0100
@@ -1 +1 @@
-VERSION = '0.4.4'
+VERSION = '0.5'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/iotop.1 new/iotop-0.5/iotop.1
--- old/iotop-0.4.4/iotop.1     2011-10-30 21:36:22.000000000 +0100
+++ new/iotop-0.5/iotop.1       1970-01-01 01:00:00.000000000 +0100
@@ -1,89 +0,0 @@
-.\" Debian manual page, has been forwarded upstream
-.TH IOTOP "1" "April 2009"
-.SH NAME
-iotop \- simple top\-like I/O monitor
-.SH SYNOPSIS
-.B iotop
-[\fIOPTIONS\fR]
-.SH DESCRIPTION
-iotop watches I/O usage information output by the Linux kernel (requires
-2.6.20 or later) and displays a table of current I/O usage by processes
-or threads on the system. At least the CONFIG_TASK_DELAY_ACCT,
-CONFIG_TASK_IO_ACCOUNTING, CONFIG_TASKSTATS and CONFIG_VM_EVENT_COUNTERS
-options need to be enabled in your Linux kernel build configuration.
-.PP
-iotop displays columns for the I/O bandwidth read and written by each
-process/thread during the sampling period. It also displays the percentage
-of time the thread/process spent while swapping in and while waiting on I/O. 
For each process, its I/O priority (class/level) is shown.
-In addition, the total I/O bandwidth read and written during the sampling
-period is displayed at the top of the interface.
-.PP
-Use the left and right arrows to change the sorting, r to reverse the
-sorting order, o to toggle the \-\-only option, p to toggle the \-\-processes 
option, a to toggle the \-\-accumulated option, q to quit or i to change the 
priority of a thread or a process' thread(s). Any other key will force a 
refresh.
-.SH OPTIONS
-.TP
-\fB\-\-version\fR
-Show the version number and exit
-.TP
-\fB\-h\fR, \fB\-\-help\fR
-Show usage information and exit
-.TP
-\fB\-o\fR, \fB\-\-only\fR
-Only show processes or threads actually doing I/O, instead of showing all 
processes or threads. This can be dynamically toggled by pressing o.
-.TP
-\fB\-b\fR, \fB\-\-batch\fR
-Turn on non\-interactive mode.
-Useful for logging I/O usage over time.
-.TP
-\fB\-n\fR NUM, \fB\-\-iter\fR=\fINUM\fR
-Set the number of iterations before quitting (never quit by default).
-This is most useful in non\-interactive mode.
-.TP
-\fB\-d\fR SEC, \fB\-\-delay\fR=\fISEC\fR
-Set the delay between iterations in seconds (1 second by default).
-Accepts non-integer values such as 1.1 seconds.
-.TP
-\fB\-p\fR PID, \fB\-\-pid\fR=\fIPID\fR
-A list of processes/threads to monitor (all by default).
-.TP
-\fB\-u\fR USER, \fB\-\-user\fR=\fIUSER\fR
-A list of users to monitor (all by default)
-.TP
-\fB\-P\fR, \fB\-\-processes\fR
-Only show processes. Normally iotop shows all threads.
-.TP
-\fB\-a\fR, \fB\-\-accumulated\fR
-Show accumulated I/O instead of bandwidth. In this mode, iotop shows the 
amount of I/O processes have done since iotop started.
-.TP
-\fB\-k\fR, \fB\-\-kilobytes\fR
-Use kilobytes instead of a human friendly unit. This mode is useful when 
scripting the batch mode of iotop. Instead of choosing the most appropriate 
unit iotop will display all sizes in kilobytes.
-.TP
-\fB\-t\fR, \fB\-\-time\fR
-Add a timestamp on each line (implies \-\-batch). Each line will be prefixed 
by the current time.
-.TP
-\fB\-q\fR, \fB\-\-quiet\fR
-suppress some lines of header (implies \-\-batch). This option can be 
specified up to three times to remove header lines.
-.RS
-.PD 0
-.TP
-.B \-q
-column names are only printed on the first iteration,
-.TP
-.B \-qq
-column names are never printed,
-.TP
-.B \-qqq
-the I/O summary is never printed.
-.PD 1
-.RE
-.SH SEE ALSO
-.BR ionice (1),
-.BR top (1),
-.BR vmstat (1),
-.BR atop (1),
-.BR htop (1)
-.SH AUTHOR
-iotop was written by Guillaume Chazarain.
-.PP
-This manual page was started by Paul Wise for the
-Debian project and is placed in the public domain.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/iotop.8 new/iotop-0.5/iotop.8
--- old/iotop-0.4.4/iotop.8     1970-01-01 01:00:00.000000000 +0100
+++ new/iotop-0.5/iotop.8       2013-02-03 19:50:02.000000000 +0100
@@ -0,0 +1,97 @@
+.\" Debian manual page, has been forwarded upstream
+.TH IOTOP "8" "April 2009"
+.SH NAME
+iotop \- simple top\-like I/O monitor
+.SH SYNOPSIS
+.B iotop
+[\fIOPTIONS\fR]
+.SH DESCRIPTION
+iotop watches I/O usage information output by the Linux kernel (requires
+2.6.20 or later) and displays a table of current I/O usage by processes
+or threads on the system. At least the CONFIG_TASK_DELAY_ACCT,
+CONFIG_TASK_IO_ACCOUNTING, CONFIG_TASKSTATS and CONFIG_VM_EVENT_COUNTERS
+options need to be enabled in your Linux kernel build configuration.
+.PP
+iotop displays columns for the I/O bandwidth read and written by each
+process/thread during the sampling period. It also displays the percentage
+of time the thread/process spent while swapping in and while waiting on I/O. 
For each process, its I/O priority (class/level) is shown.
+.PP
+In addition, the total I/O bandwidth read and written during the sampling
+period is displayed at the top of the interface.
+\fBTotal DISK READ\fR and \fBTotal DISK WRITE\fR values represent total read
+and write bandwidth between processes and kernel threads on the one side and
+kernel block device subsystem on the other. While \fBActual DISK READ\fR and
+\fBActual DISK WRITE\fR values represent corresponding bandwidths for actual
+disk I/O between kernel block device subsystem and underlying hardware (HDD, 
SSD, etc.).
+Thus \fBTotal\fR and \fBActual\fR values may not be equal at any given moment 
of time
+due to data caching and I/O operations reordering that take place inside Linux 
kernel.
+.PP
+Use the left and right arrows to change the sorting, r to reverse the
+sorting order, o to toggle the \-\-only option, p to toggle the \-\-processes 
option, a to toggle the \-\-accumulated option, q to quit or i to change the 
priority of a thread or a process' thread(s). Any other key will force a 
refresh.
+.SH OPTIONS
+.TP
+\fB\-\-version\fR
+Show the version number and exit
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show usage information and exit
+.TP
+\fB\-o\fR, \fB\-\-only\fR
+Only show processes or threads actually doing I/O, instead of showing all 
processes or threads. This can be dynamically toggled by pressing o.
+.TP
+\fB\-b\fR, \fB\-\-batch\fR
+Turn on non\-interactive mode.
+Useful for logging I/O usage over time.
+.TP
+\fB\-n\fR NUM, \fB\-\-iter\fR=\fINUM\fR
+Set the number of iterations before quitting (never quit by default).
+This is most useful in non\-interactive mode.
+.TP
+\fB\-d\fR SEC, \fB\-\-delay\fR=\fISEC\fR
+Set the delay between iterations in seconds (1 second by default).
+Accepts non-integer values such as 1.1 seconds.
+.TP
+\fB\-p\fR PID, \fB\-\-pid\fR=\fIPID\fR
+A list of processes/threads to monitor (all by default).
+.TP
+\fB\-u\fR USER, \fB\-\-user\fR=\fIUSER\fR
+A list of users to monitor (all by default)
+.TP
+\fB\-P\fR, \fB\-\-processes\fR
+Only show processes. Normally iotop shows all threads.
+.TP
+\fB\-a\fR, \fB\-\-accumulated\fR
+Show accumulated I/O instead of bandwidth. In this mode, iotop shows the 
amount of I/O processes have done since iotop started.
+.TP
+\fB\-k\fR, \fB\-\-kilobytes\fR
+Use kilobytes instead of a human friendly unit. This mode is useful when 
scripting the batch mode of iotop. Instead of choosing the most appropriate 
unit iotop will display all sizes in kilobytes.
+.TP
+\fB\-t\fR, \fB\-\-time\fR
+Add a timestamp on each line (implies \-\-batch). Each line will be prefixed 
by the current time.
+.TP
+\fB\-q\fR, \fB\-\-quiet\fR
+suppress some lines of header (implies \-\-batch). This option can be 
specified up to three times to remove header lines.
+.RS
+.PD 0
+.TP
+.B \-q
+column names are only printed on the first iteration,
+.TP
+.B \-qq
+column names are never printed,
+.TP
+.B \-qqq
+the I/O summary is never printed.
+.PD 1
+.RE
+.SH SEE ALSO
+.BR ionice (1),
+.BR top (1),
+.BR vmstat (1),
+.BR atop (1),
+.BR htop (1)
+.SH AUTHOR
+iotop was written by Guillaume Chazarain.
+.PP
+This manual page was started by Paul Wise for the
+Debian project and is placed in the public domain.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/sbin/iotop new/iotop-0.5/sbin/iotop
--- old/iotop-0.4.4/sbin/iotop  1970-01-01 01:00:00.000000000 +0100
+++ new/iotop-0.5/sbin/iotop    2013-02-03 19:50:02.000000000 +0100
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+# iotop: Display I/O usage of processes in a top like UI
+# Copyright (c) 2007, 2008 Guillaume Chazarain <[email protected]>, GPLv2
+# See iotop --help for some help
+
+import sys
+
+try:
+    from iotop.ui import main
+except ImportError, e:
+    print e
+    print 'To run an uninstalled copy of iotop,'
+    print 'launch iotop.py in the top directory'
+else:
+    try:
+        main()
+    except KeyboardInterrupt:
+        pass
+    sys.exit(0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/iotop-0.4.4/setup.py new/iotop-0.5/setup.py
--- old/iotop-0.4.4/setup.py    2011-10-30 21:36:22.000000000 +0100
+++ new/iotop-0.5/setup.py      2013-02-03 19:50:02.000000000 +0100
@@ -12,8 +12,8 @@
       author='Guillaume Chazarain',
       author_email='[email protected]',
       url='http://guichaz.free.fr/iotop',
-      scripts=['bin/iotop'],
-      data_files=[('share/man/man1', ['iotop.1'])],
+      scripts=['sbin/iotop'],
+      data_files=[('share/man/man8', ['iotop.8'])],
       packages=['iotop'],
       license='GPL'
 )

--
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to