alloc: upgrade to fallocate
[xfstests-dev.git] / src / btrfs_crc32c_forged_name.py
1 # SPDX-License-Identifier: GPL-2.0
2
3 import struct
4 import sys
5 import os
6 import argparse
7
8 class CRC32(object):
9   """A class to calculate and manipulate CRC32."""
10   def __init__(self):
11     self.polynom = 0x82F63B78
12     self.table, self.reverse = [0]*256, [0]*256
13     self._build_tables()
14
15   def _build_tables(self):
16     for i in range(256):
17       fwd = i
18       rev = i << 24
19       for j in range(8, 0, -1):
20         # build normal table
21         if (fwd & 1) == 1:
22           fwd = (fwd >> 1) ^ self.polynom
23         else:
24           fwd >>= 1
25         self.table[i] = fwd & 0xffffffff
26         # build reverse table =)
27         if rev & 0x80000000 == 0x80000000:
28           rev = ((rev ^ self.polynom) << 1) | 1
29         else:
30           rev <<= 1
31         rev &= 0xffffffff
32         self.reverse[i] = rev
33
34   def calc(self, s):
35     """Calculate crc32 of a string.
36        Same crc32 as in (binascii.crc32)&0xffffffff.
37     """
38     crc = 0xffffffff
39     for c in s:
40       crc = (crc >> 8) ^ self.table[(crc ^ ord(c)) & 0xff]
41     return crc^0xffffffff
42
43   def forge(self, wanted_crc, s, pos=None):
44     """Forge crc32 of a string by adding 4 bytes at position pos."""
45     if pos is None:
46       pos = len(s)
47
48     # forward calculation of CRC up to pos, sets current forward CRC state
49     fwd_crc = 0xffffffff
50     for c in s[:pos]:
51       fwd_crc = (fwd_crc >> 8) ^ self.table[(fwd_crc ^ ord(c)) & 0xff]
52
53     # backward calculation of CRC up to pos, sets wanted backward CRC state
54     bkd_crc = wanted_crc^0xffffffff
55     for c in s[pos:][::-1]:
56       bkd_crc = ((bkd_crc << 8) & 0xffffffff) ^ self.reverse[bkd_crc >> 24]
57       bkd_crc ^= ord(c)
58
59     # deduce the 4 bytes we need to insert
60     for c in struct.pack('<L',fwd_crc)[::-1]:
61       bkd_crc = ((bkd_crc << 8) & 0xffffffff) ^ self.reverse[bkd_crc >> 24]
62       bkd_crc ^= ord(c)
63
64     res = s[:pos] + struct.pack('<L', bkd_crc) + s[pos:]
65     return res
66
67   def parse_args(self):
68     parser = argparse.ArgumentParser()
69     parser.add_argument("-d", default=os.getcwd(), dest='dir',
70                         help="directory to generate forged names")
71     parser.add_argument("-c", default=1, type=int, dest='count',
72                         help="number of forged names to create")
73     return parser.parse_args()
74
75 if __name__=='__main__':
76
77   crc = CRC32()
78   wanted_crc = 0x00000000
79   count = 0
80   args = crc.parse_args()
81   dirpath=args.dir
82   while count < args.count :
83     origname = os.urandom (89).encode ("hex")[:-1].strip ("\x00")
84     forgename = crc.forge(wanted_crc, origname, 4)
85     if ("/" not in forgename) and ("\x00" not in forgename):
86       srcpath=dirpath + '/' + str(count)
87       dstpath=dirpath + '/' + forgename
88       file (srcpath, 'a').close()
89       os.rename(srcpath, dstpath)
90       os.system('btrfs fi sync %s' % (dirpath))
91       count+=1;