Subversion Repositories HelenOS

Rev

Rev 3520 | Rev 3524 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3520 Rev 3523
Line 46... Line 46...
46
 
46
 
47
def subtree_size(root, cluster_size, dirent_size):
47
def subtree_size(root, cluster_size, dirent_size):
48
    "Recursive directory walk and calculate size"
48
    "Recursive directory walk and calculate size"
49
   
49
   
50
    size = 0
50
    size = 0
51
    files = 0
51
    files = 2
52
   
52
   
53
    for name in os.listdir(root):
53
    for name in os.listdir(root):
54
        canon = os.path.join(root, name)
54
        canon = os.path.join(root, name)
55
       
55
       
56
        if (os.path.isfile(canon)):
56
        if (os.path.isfile(canon)):
Line 66... Line 66...
66
def root_entries(root):
66
def root_entries(root):
67
    "Return number of root directory entries"
67
    "Return number of root directory entries"
68
   
68
   
69
    return len(os.listdir(root))
69
    return len(os.listdir(root))
70
 
70
 
71
def write_file(path, outf, cluster_size, data_start, fat):
71
def write_file(path, outf, cluster_size, data_start, fat, reserved_clusters):
72
    "Store the contents of a file"
72
    "Store the contents of a file"
73
   
73
   
74
    size = os.path.getsize(path)
74
    size = os.path.getsize(path)
75
    prev = -1
75
    prev = -1
76
    first = -1
76
    first = 0
77
   
77
   
78
    inf = file(path, "r")
78
    inf = file(path, "r")
79
    rd = 0;
79
    rd = 0;
80
    while (rd < size):
80
    while (rd < size):
81
        data = inf.read(cluster_size);
-
 
82
       
-
 
83
        empty_cluster = fat.index(0)
81
        empty_cluster = fat.index(0)
84
       
-
 
85
        fat[empty_cluster] = 0xffff
82
        fat[empty_cluster] = 0xffff
-
 
83
       
86
        if (prev != -1):
84
        if (prev != -1):
87
            fat[prev] = empty_cluster
85
            fat[prev] = empty_cluster
88
        else:
86
        else:
89
            first = empty_cluster
87
            first = empty_cluster
90
       
88
       
91
        prev = empty_cluster
89
        prev = empty_cluster
92
       
90
       
-
 
91
        data = inf.read(cluster_size);
93
        outf.seek(data_start + empty_cluster * cluster_size)
92
        outf.seek(data_start + (empty_cluster - reserved_clusters) * cluster_size)
94
        outf.write(data)
93
        outf.write(data)
95
        rd += len(data)
94
        rd += len(data)
96
    inf.close()
95
    inf.close()
97
   
96
   
98
    return first, size
97
    return first, size
99
 
98
 
-
 
99
def write_directory(directory, outf, cluster_size, data_start, fat, reserved_clusters, dirent_size, empty_cluster):
-
 
100
    "Store the contents of a directory"
-
 
101
   
-
 
102
    length = len(directory)
-
 
103
    size = length * dirent_size
-
 
104
    prev = -1
-
 
105
    first = 0
-
 
106
   
-
 
107
    i = 0
-
 
108
    rd = 0;
-
 
109
    while (rd < size):
-
 
110
        if (prev != -1):
-
 
111
            empty_cluster = fat.index(0)
-
 
112
            fat[empty_cluster] = 0xffff
-
 
113
            fat[prev] = empty_cluster
-
 
114
        else:
-
 
115
            first = empty_cluster
-
 
116
       
-
 
117
        prev = empty_cluster
-
 
118
       
-
 
119
        data = ''
-
 
120
        data_len = 0
-
 
121
        while ((i < length) and (data_len < cluster_size)):
-
 
122
            if (i == 0):
-
 
123
                directory[i].cluster = empty_cluster
-
 
124
           
-
 
125
            data += directory[i].pack()
-
 
126
            data_len += dirent_size
-
 
127
            i += 1
-
 
128
       
-
 
129
        outf.seek(data_start + (empty_cluster - reserved_clusters) * cluster_size)
-
 
130
        outf.write(data)
-
 
131
        rd += len(data)
-
 
132
   
-
 
133
    return first, size
-
 
134
 
100
DIR_ENTRY = """little:
135
DIR_ENTRY = """little:
101
    char name[8]               /* file name */
136
    char name[8]               /* file name */
102
    char ext[3]                /* file extension */
137
    char ext[3]                /* file extension */
103
    uint8_t attr               /* file attributes */
138
    uint8_t attr               /* file attributes */
104
    padding[1]                 /* reserved for NT */
139
    padding[1]                 /* reserved for NT */
Line 111... Line 146...
111
    uint16_t mdate             /* modification date */
146
    uint16_t mdate             /* modification date */
112
    uint16_t cluster           /* first cluster */
147
    uint16_t cluster           /* first cluster */
113
    uint32_t size              /* file size */
148
    uint32_t size              /* file size */
114
"""
149
"""
115
 
150
 
-
 
151
DOT_DIR_ENTRY = """little:
-
 
152
    uint8_t signature          /* 0x2e signature */
-
 
153
    char name[7]               /* empty */
-
 
154
    char ext[3]                /* empty */
-
 
155
    uint8_t attr               /* file attributes */
-
 
156
    padding[1]                 /* reserved for NT */
-
 
157
    uint8_t ctime_fine         /* create time (fine resolution) */
-
 
158
    uint16_t ctime             /* create time */
-
 
159
    uint16_t cdate             /* create date */
-
 
160
    uint16_t adate             /* access date */
-
 
161
    padding[2]                 /* EA-index */
-
 
162
    uint16_t mtime             /* modification time */
-
 
163
    uint16_t mdate             /* modification date */
-
 
164
    uint16_t cluster           /* first cluster */
-
 
165
    uint32_t size              /* file size */
-
 
166
"""
-
 
167
 
-
 
168
DOTDOT_DIR_ENTRY = """little:
-
 
169
    uint8_t signature[2]       /* 0x2e signature */
-
 
170
    char name[6]               /* empty */
-
 
171
    char ext[3]                /* empty */
-
 
172
    uint8_t attr               /* file attributes */
-
 
173
    padding[1]                 /* reserved for NT */
-
 
174
    uint8_t ctime_fine         /* create time (fine resolution) */
-
 
175
    uint16_t ctime             /* create time */
-
 
176
    uint16_t cdate             /* create date */
-
 
177
    uint16_t adate             /* access date */
-
 
178
    padding[2]                 /* EA-index */
-
 
179
    uint16_t mtime             /* modification time */
-
 
180
    uint16_t mdate             /* modification date */
-
 
181
    uint16_t cluster           /* first cluster */
-
 
182
    uint32_t size              /* file size */
-
 
183
"""
-
 
184
 
116
def mangle_fname(name):
185
def mangle_fname(name):
117
    # FIXME: filter illegal characters
186
    # FIXME: filter illegal characters
118
    fname = (name.split('.')[0] + '          ').upper()[0:8]
187
    parts = name.split('.')
-
 
188
   
-
 
189
    if (len(parts) > 0):
-
 
190
        fname = parts[0]
-
 
191
    else:
119
    return fname
192
        fname = ''
-
 
193
       
-
 
194
    return (fname + '          ').upper()[0:8]
120
 
195
 
121
def mangle_ext(name):
196
def mangle_ext(name):
122
    # FIXME: filter illegal characters
197
    # FIXME: filter illegal characters
123
    ext = (name.split('.')[1] + '  ').upper()[0:3]
198
    parts = name.split('.')
-
 
199
   
-
 
200
    if (len(parts) > 1):
-
 
201
        ext = parts[1]
-
 
202
    else:
124
    return ext
203
        ext = ''
-
 
204
   
-
 
205
    return (ext + '   ').upper()[0:3]
125
 
206
 
126
def create_dirent(name, directory, cluster, size):
207
def create_dirent(name, directory, cluster, size):
127
    dir_entry = xstruct.create(DIR_ENTRY)
208
    dir_entry = xstruct.create(DIR_ENTRY)
128
   
209
   
129
    dir_entry.name = mangle_fname(name)
210
    dir_entry.name = mangle_fname(name)
Line 139... Line 220...
139
    dir_entry.cdate = 0 # FIXME
220
    dir_entry.cdate = 0 # FIXME
140
    dir_entry.adate = 0 # FIXME
221
    dir_entry.adate = 0 # FIXME
141
    dir_entry.mtime = 0 # FIXME
222
    dir_entry.mtime = 0 # FIXME
142
    dir_entry.mdate = 0 # FIXME
223
    dir_entry.mdate = 0 # FIXME
143
    dir_entry.cluster = cluster
224
    dir_entry.cluster = cluster
-
 
225
   
-
 
226
    if (directory):
-
 
227
        dir_entry.size = 0
-
 
228
    else:
144
    dir_entry.size = size
229
        dir_entry.size = size
-
 
230
   
-
 
231
    return dir_entry
-
 
232
 
-
 
233
def create_dot_dirent(empty_cluster):
-
 
234
    dir_entry = xstruct.create(DOT_DIR_ENTRY)
-
 
235
   
-
 
236
    dir_entry.signature = 0x2e
-
 
237
    dir_entry.name = '       '
-
 
238
    dir_entry.ext = '   '
-
 
239
    dir_entry.attr = 0x10
-
 
240
   
-
 
241
    dir_entry.ctime_fine = 0 # FIXME
-
 
242
    dir_entry.ctime = 0 # FIXME
-
 
243
    dir_entry.cdate = 0 # FIXME
-
 
244
    dir_entry.adate = 0 # FIXME
-
 
245
    dir_entry.mtime = 0 # FIXME
-
 
246
    dir_entry.mdate = 0 # FIXME
-
 
247
    dir_entry.cluster = empty_cluster
-
 
248
    dir_entry.size = 0
-
 
249
   
-
 
250
    return dir_entry
-
 
251
 
-
 
252
def create_dotdot_dirent(parent_cluster):
-
 
253
    dir_entry = xstruct.create(DOTDOT_DIR_ENTRY)
-
 
254
   
-
 
255
    dir_entry.signature = [0x2e, 0x2e]
-
 
256
    dir_entry.name = '      '
-
 
257
    dir_entry.ext = '   '
-
 
258
    dir_entry.attr = 0x10
-
 
259
   
-
 
260
    dir_entry.ctime_fine = 0 # FIXME
-
 
261
    dir_entry.ctime = 0 # FIXME
-
 
262
    dir_entry.cdate = 0 # FIXME
-
 
263
    dir_entry.adate = 0 # FIXME
-
 
264
    dir_entry.mtime = 0 # FIXME
-
 
265
    dir_entry.mdate = 0 # FIXME
-
 
266
    dir_entry.cluster = parent_cluster
-
 
267
    dir_entry.size = 0
145
   
268
   
146
    return dir_entry
269
    return dir_entry
147
 
270
 
148
def recursion(head, root, outf, cluster_size, root_start, data_start, fat):
271
def recursion(head, root, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, parent_cluster):
149
    "Recursive directory walk"
272
    "Recursive directory walk"
150
   
273
   
151
    directory = []
274
    directory = []
-
 
275
   
-
 
276
    if (not head):
-
 
277
        # Directory cluster preallocation
-
 
278
        empty_cluster = fat.index(0)
-
 
279
        fat[empty_cluster] = 0xffff
-
 
280
       
-
 
281
        directory.append(create_dot_dirent(empty_cluster))
-
 
282
        directory.append(create_dotdot_dirent(parent_cluster))
-
 
283
    else:
-
 
284
        empty_cluster = 0
-
 
285
   
152
    for name in os.listdir(root):
286
    for name in os.listdir(root):
153
        canon = os.path.join(root, name)
287
        canon = os.path.join(root, name)
154
       
288
       
155
        if (os.path.isfile(canon)):
289
        if (os.path.isfile(canon)):
156
            rv = write_file(canon, outf, cluster_size, data_start, fat)
290
            rv = write_file(canon, outf, cluster_size, data_start, fat, reserved_clusters)
157
            directory.append(create_dirent(name, False, rv[0], rv[1]))
291
            directory.append(create_dirent(name, False, rv[0], rv[1]))
-
 
292
       
-
 
293
        if (os.path.isdir(canon)):
-
 
294
            rv = recursion(False, canon, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster)
-
 
295
            directory.append(create_dirent(name, True, rv[0], rv[1]))
158
   
296
   
159
    if (head):
297
    if (head):
160
        outf.seek(root_start)
298
        outf.seek(root_start)
161
        for dir_entry in directory:
299
        for dir_entry in directory:
162
            outf.write(dir_entry.pack())
300
            outf.write(dir_entry.pack())
-
 
301
    else:
-
 
302
        return write_directory(directory, outf, cluster_size, data_start, fat, reserved_clusters, dirent_size, empty_cluster)
163
 
303
 
164
BOOT_SECTOR = """little:
304
BOOT_SECTOR = """little:
165
    uint8_t jmp[3]             /* jump instruction */
305
    uint8_t jmp[3]             /* jump instruction */
166
    char oem[8]                /* OEM string */
306
    char oem[8]                /* OEM string */
167
    uint16_t sector            /* bytes per sector */
307
    uint16_t sector            /* bytes per sector */
Line 209... Line 349...
209
    if (not os.path.isdir(path)):
349
    if (not os.path.isdir(path)):
210
        print "<PATH> must be a directory"
350
        print "<PATH> must be a directory"
211
        return
351
        return
212
   
352
   
213
    fat16_clusters = 4096
353
    fat16_clusters = 4096
-
 
354
    min_cluster_size = 1024
214
   
355
   
215
    sector_size = 512
356
    sector_size = 512
216
    cluster_size = 4096
357
    cluster_size = 4096
217
    dirent_size = 32
358
    dirent_size = 32
218
    fatent_size = 2
359
    fatent_size = 2
Line 220... Line 361...
220
    reserved_clusters = 2
361
    reserved_clusters = 2
221
   
362
   
222
    # Make sure the filesystem is large enought for FAT16
363
    # Make sure the filesystem is large enought for FAT16
223
    size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size
364
    size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size
224
    while (size / cluster_size < fat16_clusters):
365
    while (size / cluster_size < fat16_clusters):
225
        if (cluster_size > sector_size):
366
        if (cluster_size > min_cluster_size):
226
            cluster_size /= 2
367
            cluster_size /= 2
227
            size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size
368
            size = subtree_size(path, cluster_size, dirent_size) + reserved_clusters * cluster_size
228
        else:
369
        else:
229
            size = fat16_clusters * cluster_size + reserved_clusters * cluster_size
370
            size = fat16_clusters * cluster_size + reserved_clusters * cluster_size
230
   
371
   
Line 269... Line 410...
269
    for i in range(1, cluster_size / sector_size):
410
    for i in range(1, cluster_size / sector_size):
270
        outf.write(empty_sector.pack())
411
        outf.write(empty_sector.pack())
271
   
412
   
272
    # FAT tables
413
    # FAT tables
273
    for i in range(0, fat_count):
414
    for i in range(0, fat_count):
274
        for j in range(0, boot_sector.fat_sectors):
415
        for j in range(0, fat_size / sector_size):
275
            outf.write(empty_sector.pack())
416
            outf.write(empty_sector.pack())
276
   
417
   
277
    # Root directory
418
    # Root directory
278
    for i in range(0, root_size / sector_size):
419
    for i in range(0, root_size / sector_size):
279
        outf.write(empty_sector.pack())
420
        outf.write(empty_sector.pack())
Line 284... Line 425...
284
   
425
   
285
    fat = array.array('L', [0] * (fat_size / fatent_size))
426
    fat = array.array('L', [0] * (fat_size / fatent_size))
286
    fat[0] = 0xfff8
427
    fat[0] = 0xfff8
287
    fat[1] = 0xffff
428
    fat[1] = 0xffff
288
   
429
   
289
    recursion(True, path, outf, cluster_size, root_start, data_start, fat)
430
    recursion(True, path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, 0)
290
   
431
   
291
    # Store FAT
432
    # Store FAT
292
    fat_entry = xstruct.create(FAT_ENTRY)
433
    fat_entry = xstruct.create(FAT_ENTRY)
293
    for i in range(0, fat_count):
434
    for i in range(0, fat_count):
294
        outf.seek(cluster_size + i * fat_size)
435
        outf.seek(cluster_size + i * fat_size)