File: gendir

package info (click to toggle)
composefs 1.0.8-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 11,040 kB
  • sloc: ansic: 9,004; sh: 416; python: 225; makefile: 5
file content (201 lines) | stat: -rwxr-xr-x 11,836 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
#!/usr/bin/python3

import argparse
import hashlib
import os
import random
import shlex
import shutil
import stat
import string
import sys
import errno

adjectives = ["adorable", "adventurous", "aggressive", "agreeable", "alert", "alive", "amused", "angry", "annoyed", "annoying", "anxious", "arrogant", "ashamed", "attractive", "average", "awful", "bad", "beautiful", "better", "bewildered", "black", "bloody", "blue", "blue-eyed", "blushing", "bored", "brainy", "brave", "breakable", "bright", "busy", "calm", "careful", "cautious", "charming", "cheerful", "clean", "clear", "clever", "cloudy", "clumsy", "colorful", "combative", "comfortable", "concerned", "condemned", "confused", "cooperative", "courageous", "crazy", "creepy", "crowded", "cruel", "curious", "cute", "dangerous", "dark", "dead", "defeated", "defiant", "delightful", "depressed", "determined", "different", "difficult", "disgusted", "distinct", "disturbed", "dizzy", "doubtful", "drab", "dull", "eager", "easy", "elated", "elegant", "embarrassed", "enchanting", "encouraging", "energetic", "enthusiastic", "envious", "evil", "excited", "expensive", "exuberant", "fair", "faithful", "famous", "fancy", "fantastic", "fierce", "filthy", "fine", "foolish", "fragile", "frail", "frantic", "friendly", "frightened", "funny", "gentle", "gifted", "glamorous", "gleaming", "glorious", "good", "gorgeous", "graceful", "grieving", "grotesque", "grumpy", "handsome", "happy", "healthy", "helpful", "helpless", "hilarious", "homeless", "homely", "horrible", "hungry", "hurt", "ill", "important", "impossible", "inexpensive", "innocent", "inquisitive", "itchy", "jealous", "jittery", "jolly", "joyous", "kind", "lazy", "light", "lively", "lonely", "long", "lovely", "lucky", "magnificent", "misty", "modern", "motionless", "muddy", "mushy", "mysterious", "nasty", "naughty", "nervous", "nice", "nutty", "obedient", "obnoxious", "odd", "old-fashioned", "open", "outrageous", "outstanding", "panicky", "perfect", "plain", "pleasant", "poised", "poor", "powerful", "precious", "prickly", "proud", "putrid", "puzzled", "quaint", "real", "relieved", "repulsive", "rich", "scary", "selfish", "shiny", "shy", "silly", "sleepy", "smiling", "smoggy", "sore", "sparkling", "splendid", "spotless", "stormy", "strange", "stupid", "successful", "super", "talented", "tame", "tasty", "tender", "tense", "terrible", "thankful", "thoughtful", "thoughtless", "tired", "tough", "troubled", "ugliest", "ugly", "uninterested", "unsightly", "unusual", "upset", "uptight", "vast", "victorious", "vivacious", "wandering", "weary", "wicked", "wide-eyed", "wild", "witty", "worried", "worrisome", "wrong", "zany", "zealous"]

nouns = ["apple", "air", "conditioner", "airport", "ambulance", "aircraft", "apartment", "arrow", "antlers", "apro", "alligator", "architect", "ankle", "armchair", "aunt", "ball", "bermudas", "beans", "balloon", "bear", "blouse", "bed", "bow", "bread", "black", "board", "bones", "bill", "bitterness", "boxers", "belt", "brain", "buffalo", "bird", "baby", "book", "back", "butter", "bulb", "buckles", "bat", "bank", "bag", "bra", "boots", "blazer", "bikini", "bookcase", "bookstore", "bus", "stop", "brass", "brother", "boy", "blender", "bucket", "bakery", "bow", "bridge", "boat", "car", "cow", "cap", "cooker", "cheeks", "cheese", "credenza", "carpet", "crow", "crest", "chest", "chair", "candy", "cabinet", "cat", "coffee", "children", "cookware", "chaise", "longue", "chicken", "casino", "cabin", "castle", "church", "cafe", "cinema", "choker", "cravat", "cane", "costume", "cardigan", "chocolate", "crib", "couch", "cello", "cashier", "composer", "cave", "country", "computer", "canoe", "clock", "charlie", "dog", "deer", "donkey", "desk", "desktop", "dress", "dolphin", "doctor", "dentist", "drum", "dresser", "designer", "detective", "daughter", "egg", "elephant", "earrings", "ears", "eyes", "estate", "finger", "fox", "frock", "frog", "fan", "freezer", "fish", "film", "foot", "flag", "factory", "father", "farm", "forest", "flower", "fruit", "fork", "grapes", "goat", "gown", "garlic", "ginger", "giraffe", "gauva", "grains", "gas", "station", "garage", "gloves", "glasses", "gift", "galaxy", "guitar", "grandmother", "grandfather", "governor", "girl", "guest", "hamburger", "hand", "head", "hair", "heart", "house", "horse", "hen", "horn", "hat", "hammer", "hostel", "hospital", "hotel", "heels", "herbs", "host", "jacket", "jersey", "jewelry", "jaw", "jumper", "judge", "juicer", "keyboard", "kid", "kangaroo", "koala", "knife", "lemon", "lion", "leggings", "leg", "laptop", "library", "lamb", "london", "lips", "lung", "lighter", "luggage", "lamp", "lawyer", "mouse", "monkey", "mouth", "mango", "mobile", "milk", "music", "mirror", "musician", "mother", "man", "model", "mall", "museum", "market", "moonlight", "medicine", "microscope", "newspaper", "nose", "notebook", "neck", "noodles", "nurse", "necklace", "noise", "ocean", "ostrich", "oil", "orange", "onion", "oven", "owl", "paper", "panda", "pants", "palm", "pasta", "pumpkin", "pharmacist", "potato", "parfume", "panther", "pad", "pencil", "pipe", "police", "pen", "pharmacy", "petrol", "station", "police", "station", "parrot", "plane", "pigeon", "phone", "peacock", "pencil", "pig", "pouch", "pagoda", "pyramid", "purse", "pancake", "popcorn", "piano", "physician", "photographer", "professor", "painter", "park", "plant", "parfume", "radio", "razor", "ribs", "rainbow", "ring", "rabbit", "rice", "refrigerator", "remote", "restaurant", "road", "surgeon", "scale", "shampoo", "sink", "salt", "shark", "sandals", "shoulder", "spoon", "soap", "sand", "sheep", "sari", "stomach", "stairs", "soup", "shoes", "scissors", "sparrow", "shirt", "suitcase", "stove", "stairs", "snowman", "shower", "swan", "suit", "sweater", "smoke", "skirt", "sofa", "socks", "stadium", "skyscraper", "school", "sunglasses", "sandals", "slippers", "shorts", "sandwich", "strawberry", "spaghetti", "shrimp", "saxophone", "sister", "son", "singer", "senator", "street", "supermarket", "swimming", "pool", "star", "sky", "sun", "spoon", "ship", "smile", "table", "turkey", "tie", "toes", "truck", "train", "taxi", "tiger", "trousers", "tongue", "television", "teacher", "turtle", "tablet", "train", "station", "toothpaste", "tail", "theater", "trench", "coat", "tea", "tomato", "teen", "tunnel", "temple", "town", "toothbrush", "tree", "toy", "tissue", "telephone", "underwear", "uncle", "umbrella", "vest", "voice", "veterinarian", "villa", "violin", "village", "vehicle", "vase", "wallet", "wolf", "waist", "wrist", "water", "melon", "whale", "water", "wings", "whisker", "watch", "woman", "washing", "machine", "wheelchair", "waiter", "wound", "xylophone", "zebra", "zoo"]

def with_chance(chance):
    return random.random() <= chance

class Chance():
    def __init__(self):
        self.value = random.random()
        self.start = 0

    def with_chance(self, chance):
        if self.start > 1:
            print("Too many choices")
        start = self.start
        end = self.start + chance
        self.start = end
        return self.value >= start and self.value < end

    # Choose one of weighted options
    def choice(self, options):
        for value, chance in options:
            if self.with_chance(chance):
                return value
        # Default to first
        value, chance = options[0]
        return value

def gen_dir_mode():
    # For creation to work we want all dirs u+rwx
    return random.choice([0o777, 0o755, 0o750, 0o700])

def gen_file_mode():
    return random.choice([0o644, 0o666, 0o755, 0o777])

def gen_filename():
    if not args.unreadable:
        name = bytes(random.choice(adjectives) + "_" + random.choice(nouns) + str(random.randint(1,999)), "utf-8")
        if len(name) > 255:
            return gen_filename()
        return name

    name_len = random.randrange(1, 255)
    name = [0] * name_len
    for i in range(name_len):
        c = random.randrange(1, 255)
        while c == ord('/'):
            c = random.randrange(1, 255)
        name[i] = c
    name=bytes(name)
    if name == b'.' or name == b'..':
        return gen_filename()
    return name

def gen_filenames():
    c = Chance()
    # 5% of dirs are huge
    if c.with_chance(0.05):
        num_files = random.randrange(0, 4096)
    else:
        num_files = random.randrange(0, 25)

    files = []
    for i in range(num_files):
        files.append(gen_filename())

    return list(sorted(set(files)))

def gen_xattrname():
    return random.choice(nouns) + str(random.randint(1,9))

def gen_xattrdata():
    return bytes(random.choice(adjectives) + str(random.randint(1,9)), "utf-8")


def gen_hierarchy(root):
    num_dirs = random.randrange(30, 50)
    dirs = []
    for i in range(num_dirs):
        parent = random.choice([root] * 3 + dirs);
        p = os.path.join(parent, gen_filename())
        dirs.append(p)
    # Sort and drop any (unlikely) duplicateds
    return list(sorted(set(dirs)))

def set_user_xattr(path):
    n_xattrs = random.randrange(0, 3)
    for i in range(n_xattrs):
        name = "user." + gen_xattrname()
        value = gen_xattrdata()
        try:
            os.setxattr(path, name, value, follow_symlinks=False)
        except OSError as e:
            # Not much we can do if the backing fs doesn't allow xattrs
            if e.errno not in (errno.EPERM, errno.ENOTSUP):
                raise

old_files = []
def make_regular_file(path):
    with os.fdopen(os.open(path, os.O_WRONLY|os.O_CREAT, gen_file_mode()), 'wb') as fd:
        c = Chance();
        # 5% of reuse old file data
        if len(old_files) > 0 and c.with_chance(0.05):
            reused = random.choice(old_files)
            with os.fdopen(os.open(reused, os.O_RDONLY), 'rb') as src:
                shutil.copyfileobj(src, fd)
            return

        # 5% of files are large
        if c.with_chance(0.05):
            size = random.randrange(0, 4*1024*1024)
        else: # Rest are small
            size = random.randrange(0, 256)

        data = random.randbytes(size)
        fd.write(data)
        # Save path for reuse
        old_files.append(path)

        set_user_xattr(path)

def make_symlink(path):
    target = gen_filename()
    os.symlink(target, path)

def make_node(path):
    if not args.privileged:
        return
    target = gen_filename()
    os.mknod(path, gen_file_mode() | random.choice([stat.S_IFCHR,stat.S_IFBLK]), os.makedev(random.randrange(1, 255),random.randrange(1, 255)))

def make_whiteout(path):
    if args.nowhiteout:
        return
    target = gen_filename()
    os.mknod(path, gen_file_mode() | stat.S_IFCHR, device=os.makedev(0,0))

def make_fifo(path):
    target = gen_filename()
    os.mknod(path, gen_file_mode() | stat.S_IFIFO)

def make_file(path):
    c = Chance();
    f = c.choice([
        (make_regular_file, 0.7),
        (make_symlink, 0.15),
        (make_fifo, 0.05),
        (make_node, 0.05),
        (make_whiteout, 0.05)
    ])
    f(path)

def make_dir(path, dirs):
    os.mkdir(path, mode=gen_dir_mode())
    set_user_xattr(path)
    files = gen_filenames()
    for f in files:
        child_path = os.path.join(path, f)
        if child_path in dirs:
            continue

        func = random.choice([make_file])
        func(child_path)

argParser = argparse.ArgumentParser()
argParser.add_argument("--seed")
argParser.add_argument("--unreadable", action='store_true')
argParser.add_argument("--privileged", action='store_true')
argParser.add_argument("--nowhiteout", action='store_true')
argParser.add_argument('path')

args = argParser.parse_args()

if args.seed:
    seed = args.seed
else:
    seed = os.urandom(16).hex()
random.seed(seed)
print(f"Using seed '{seed}'")

# Generate tree structure
root = bytes(args.path,"utf-8")
dirs = gen_hierarchy(root)

make_dir(root, dirs)
for d in dirs:
    make_dir(d, dirs)