Last active
February 15, 2023 11:52
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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