| """Compare files.""" |
| |
| import os, stat, statcache |
| |
| _cache = {} |
| BUFSIZE=8*1024 |
| |
| def cmp(f1, f2, shallow=1,use_statcache=0): |
| """Compare two files. |
| |
| Arguments: |
| |
| f1 -- First file name |
| |
| f2 -- Second file name |
| |
| shallow -- Just check stat signature (do not read the files). |
| defaults to 1. |
| |
| use_statcache -- Do not stat() each file directly: go through |
| the statcache module for more efficiency. |
| |
| Return value: |
| |
| integer -- 1 if the files are the same, 0 otherwise. |
| |
| This function uses a cache for past comparisons and the results, |
| with a cache invalidation mechanism relying on stale signatures. |
| Of course, if 'use_statcache' is true, this mechanism is defeated, |
| and the cache will never grow stale. |
| |
| """ |
| if use_statcache: |
| stat_function = statcache.stat |
| else: |
| stat_function = os.stat |
| s1 = _sig(stat_function(f1)) |
| s2 = _sig(stat_function(f2)) |
| if s1[0] != stat.S_IFREG or s2[0] != stat.S_IFREG: |
| return 0 |
| if shallow and s1 == s2: |
| return 1 |
| if s1[1] != s2[1]: |
| return 0 |
| |
| result = _cache.get((f1, f2)) |
| if result and (s1, s2) == result[:2]: |
| return result[2] |
| outcome = _do_cmp(f1, f2) |
| _cache[f1, f2] = s1, s2, outcome |
| return outcome |
| |
| def _sig(st): |
| return (stat.S_IFMT(st[stat.ST_MODE]), |
| st[stat.ST_SIZE], |
| st[stat.ST_MTIME]) |
| |
| def _do_cmp(f1, f2): |
| bufsize = BUFSIZE |
| fp1 = open(f1, 'rb') |
| fp2 = open(f2, 'rb') |
| while 1: |
| b1 = fp1.read(bufsize) |
| b2 = fp2.read(bufsize) |
| if b1 != b2: |
| return 0 |
| if not b1: |
| return 1 |