about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authortoonn <toonn@toonn.io>2020-07-07 22:53:57 +0200
committertoonn <toonn@toonn.io>2020-07-07 23:02:25 +0200
commitf321ce4c2072d1e76bbef7f85764c25ef7102f67 (patch)
tree9e054c0e7bd31a107a65cadfa5634073eac98a40
parent10894de1ff5baf71151859f1a3d864997202b1a7 (diff)
downloadranger-f321ce4c2072d1e76bbef7f85764c25ef7102f67.tar.gz
Switch to packing fields for sha512_encode
The easy solution was to render the `st_dev, st_ino, st_mtime` to a
string and encode that before hashing.

This solution is more efficient because it packs the numbers as bytes
rather than the digits. Technically POSIX.1 does not specify an upper
limit on the sizes for these fields. I think it's safe to say none of
the major operating systems will use more than 8 bytes/64 bits any time
soon.
-rw-r--r--ranger/core/actions.py12
1 files changed, 7 insertions, 5 deletions
diff --git a/ranger/core/actions.py b/ranger/core/actions.py
index 91f94f77..e76adc87 100644
--- a/ranger/core/actions.py
+++ b/ranger/core/actions.py
@@ -17,6 +17,7 @@ import tempfile
 from inspect import cleandoc
 from stat import S_IEXEC
 from hashlib import sha512
+from struct import pack
 from logging import getLogger
 
 import ranger
@@ -1049,11 +1050,12 @@ class Actions(  # pylint: disable=too-many-instance-attributes,too-many-public-m
     @staticmethod
     def sha512_encode(path):
         stat_ = stat(path)
-        sha = sha512(
-            '{dev},{inode},{mtime}'.format(
-                dev=stat_.st_dev, inode=stat_.st_ino, mtime=stat_.st_mtime
-            ).encode('utf-8', 'backslashreplace')
-        )
+        # How I arrived at the pack format string:
+        #   < -> little-endian
+        #   l -> st_dev: signed int (32/64 bits depending on platform)
+        #   L -> st_ino: unsigned int (ditto)
+        #   d -> st_mtime: double in python
+        sha = sha512(pack('<lLd', stat_.st_dev, stat_.st_ino, stat_.st_mtime))
         return '{0}.jpg'.format(sha.hexdigest())
 
     def get_preview(self, fobj, width, height):  # pylint: disable=too-many-return-statements