Skip to content

Instantly share code, notes, and snippets.

@Supermanuu
Last active February 15, 2023 11:52
Show Gist options
  • Save Supermanuu/ccdbe0c5d15d41dd1df75ad288e2a30a to your computer and use it in GitHub Desktop.
Save Supermanuu/ccdbe0c5d15d41dd1df75ad288e2a30a to your computer and use it in GitHub Desktop.
This python script can reset or change the timestamp of ar output files for versions without -D option
#!/usr/bin/env python
import os
import re
max_file_size = 100 * 1024 * 1024
timestamp_length = 59
timestamp_pattern = re.compile(r'/((?:\d*\s+)?)(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+`')
class Timestamp:
'''AR timestamp data'''
def write(self, source, index, destination):
'''Writes data from source into destination starting in index'''
editableString = list(destination)
i = 0
for c in source:
editableString[index + i] = c
i += 1
return ''.join(editableString)
def __init__(self, index, line, linel, magic, imagic, date, idate, uid, iuid, gid, igid, mode, imode, size, isize):
self._index = index
self._linel = linel
# Values
self._line = line
self._magic = magic
self._date = date
self._uid = uid
self._gid = gid
self._mode = mode
self._size = size
# Found indexes
self._imagic = imagic
self._idate = idate
self._iuid = iuid
self._igid = igid
self._imode = imode
self._isize = isize
def __str__(self):
return 'Timestamp: \'' + self._line + '\'\n' +\
' New line (' + str(self._linel) + '): \'' + self.get() + '\'\n' +\
' Index: ' + str(self._index) + '\'\n' +\
' Magic (' + str(self._imagic) + '): \'' + self._magic + '\'\n' +\
' Date (' + str(self._idate) + '): \'' + self._date + '\'\n' +\
' UID (' + str(self._iuid) + '): \'' + self._uid + '\'\n' +\
' GID (' + str(self._igid) + '): \'' + self._gid + '\'\n' +\
' Mode (' + str(self._imode) + '): \'' + self._mode + '\'\n' +\
' Size (' + str(self._isize) + '): \'' + self._size + '\'\n'
def clearMetadata(self):
'''Resets timestamp data'''
self._date = '0'
self._uid = '0'
self._gid = '0'
def get(self):
'''Gets timestamp line'''
newLine = '/' + (' ' * (self._linel - 2)) + '`'
newLine = self.write(self._magic, self._imagic, newLine)
newLine = self.write(self._date, self._idate, newLine)
newLine = self.write(self._uid, self._iuid, newLine)
newLine = self.write(self._gid, self._igid, newLine)
newLine = self.write(self._mode, self._imode, newLine)
newLine = self.write(self._size, self._isize, newLine)
return newLine
def getStaticLibTimestamp(libraryPath):
'''Get timestamps list from a library'''
if os.stat(libraryPath).st_size > max_file_size:
raise RuntimeError("Error: filesize is more than " + max_file_size)
with open(libraryPath, 'r+b') as input:
content = input.read(max_file_size)
foundIndex = True
startingIndex = 0
timestamps = list()
while foundIndex:
# Get starting index
startingIndex = content.find(b'\x2f', startingIndex) # Initial header
foundIndex = startingIndex != -1
if foundIndex:
# Read constant from file
input.seek(startingIndex)
try:
timestamp = input.read(timestamp_length).decode("utf-8")
found = timestamp_pattern.match(timestamp)
if found != None:
timestamps.append(Timestamp(\
startingIndex,
found.group(0), len(found.group(0)),
found.group(1).rstrip(), found.span(1)[0],
found.group(2), found.span(2)[0],
found.group(3), found.span(3)[0],
found.group(4), found.span(4)[0],
found.group(5), found.span(5)[0],
found.group(6), found.span(6)[0]))
except:
pass
# To avoid repeating matches
startingIndex += 1
return timestamps
def setStaticLibTimestamp(libraryPath, timestamps):
'''Sets a timestamp list into a library'''
with open(libraryPath, "r+b") as write:
for t in timestamps:
write.seek(t._index)
if sys.version_info[0] == 2:
write.write(t.get())
else:
write.write(bytes(t.get(), 'UTF-8'))
def manageStaticLibTimestamp(options, libraries):
'''Prints, clears and writes static lib timestamps'''
libraries = set(libraries)
for library in libraries:
print('Processing ' + library)
timestamps = getStaticLibTimestamp(library)
if 'c' in options:
for t in timestamps:
t.clearMetadata()
print(' Clear timestamps done')
if 'p' in options:
print('# Timestamps = ' + str(len(timestamps)))
for t in timestamps:
print(t)
print(' Print timestamps done')
if 'w' in options:
setStaticLibTimestamp(library, timestamps)
print(' Write timestamps done')
if __name__ == '__main__':
import sys
usage = 'Usage: ' + sys.argv[0] + ' [pcw] <static library paths ...>\n' + \
' p - print timestamps\n' + \
' c - clear timestamps\n' + \
' w - write timestamps'
if len(sys.argv) < 3:
print(usage)
exit(2)
if not re.match('[pwc]+', sys.argv[1]):
print(usage)
exit(2)
manageStaticLibTimestamp(sys.argv[1], sys.argv[2:])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment