blob: 7d6c5ae9db8a748ca35b5b46af06e118c1572efd [file] [log] [blame]
Tim Edwards9d3debb2020-10-20 20:52:18 -04001#!/usr/bin/env python3
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002# Script to read a GDS file, modify the timestamp(s), and rewrite the GDS file.
3
4import os
5import sys
6import datetime
7
8def usage():
9 print('change_gds_date.py <create_stamp> <mod_stamp> <path_to_gds_in> [<path_to_gds_out>]')
10
11if __name__ == '__main__':
12 debug = False
13
14 if len(sys.argv) == 1:
15 print("No options given to change_gds_date.py.")
16 usage()
17 sys.exit(0)
18
19 optionlist = []
20 arguments = []
21
22 for option in sys.argv[1:]:
23 if option.find('-', 0) == 0:
24 optionlist.append(option)
25 else:
26 arguments.append(option)
27
28 if len(arguments) < 3 or len(arguments) > 4:
29 print("Wrong number of arguments given to change_gds_date.py.")
30 usage()
31 sys.exit(0)
32
33 if '-debug' in optionlist:
34 debug = True
35
36 createstamp = arguments[0]
37 modstamp = arguments[1]
38 source = arguments[2]
39
40 # If modstamp is zero or negative, then set the modification timestamp
41 # to be the same as the creation timestamp.
42 try:
43 if int(modstamp) <= 0:
44 modstamp = createstamp
45 except:
46 pass
47
48 # If only three arguments are provided, then overwrite the source file.
49 if len(arguments) == 4:
50 dest = arguments[3]
51 else:
52 dest = arguments[2]
53
54 sourcedir = os.path.split(source)[0]
55 gdsinfile = os.path.split(source)[1]
56
57 destdir = os.path.split(dest)[0]
58 gdsoutfile = os.path.split(dest)[1]
59
60 with open(source, 'rb') as ifile:
61 gdsdata = ifile.read()
62
63 # Generate 12-byte modification timestamp data from date.
64 try:
65 modtime = datetime.datetime.fromtimestamp(int(modstamp))
66 except:
67 modtime = datetime.datetime.strptime(modstamp, "%m/%d/%Y %H:%M:%S")
68
69 modyear = modtime.year - 1900
70
71 year = modyear.to_bytes(2, byteorder='big')
72 month = modtime.month.to_bytes(2, byteorder='big')
73 day = modtime.day.to_bytes(2, byteorder='big')
74 hour = modtime.hour.to_bytes(2, byteorder='big')
75 minute = modtime.minute.to_bytes(2, byteorder='big')
76 second = modtime.second.to_bytes(2, byteorder='big')
77
78 gdsmodstamp = year + month + day + hour + minute + second
79
80 # Generate 12-byte creation timestamp data from date.
81 try:
82 createtime = datetime.datetime.fromtimestamp(int(createstamp))
83 except:
84 createtime = datetime.datetime.strptime(createstamp, "%m/%d/%Y %H:%M:%S")
85
86 createyear = createtime.year - 1900
87
88 year = createyear.to_bytes(2, byteorder='big')
89 month = createtime.month.to_bytes(2, byteorder='big')
90 day = createtime.day.to_bytes(2, byteorder='big')
91 hour = createtime.hour.to_bytes(2, byteorder='big')
92 minute = createtime.minute.to_bytes(2, byteorder='big')
93 second = createtime.second.to_bytes(2, byteorder='big')
94
95 gdscreatestamp = year + month + day + hour + minute + second
96
97 # To be done: Allow the user to select which datestamps to change
98 # (library or structure). Otherwise, apply the same datestamps to both.
99
100 recordtypes = ['beginstr', 'beginlib']
101 recordfilter = [5, 1]
102
103 datalen = len(gdsdata)
104 dataptr = 0
105 while dataptr < datalen:
106 # Read stream records up to any string, then search for search text.
107 bheader = gdsdata[dataptr:dataptr + 2]
108 reclen = int.from_bytes(bheader, 'big')
109 if reclen == 0:
110 print('Error: found zero-length record at position ' + str(dataptr))
111 break
112
113 rectype = gdsdata[dataptr + 2]
114 datatype = gdsdata[dataptr + 3]
115
116 brectype = rectype.to_bytes(1, byteorder='big')
117 bdatatype = datatype.to_bytes(1, byteorder='big')
118
119 if rectype in recordfilter:
120 # Datatype should be 2
121 if datatype != 2:
122 print('Error: Header data type is not 2-byte integer!')
123 if reclen != 28:
124 print('Error: Header record length is not 28!')
125 if debug:
126 print('Record type = ' + str(rectype) + ' data type = ' + str(datatype) + ' length = ' + str(reclen))
127
128 before = gdsdata[0:dataptr]
129 after = gdsdata[dataptr + reclen:]
130
131 # Assemble the new record
132 newrecord = bheader + brectype + bdatatype + gdscreatestamp + gdsmodstamp
133 # Reassemble the GDS data around the new record
134 gdsdata = before + newrecord + after
135
136 # Advance the pointer past the data
137 dataptr += reclen
138
139 with open(dest, 'wb') as ofile:
140 ofile.write(gdsdata)
141
142 exit(0)