~martin-decky/helenos/rcu

« back to all changes in this revision

Viewing changes to tools/mkfat.py

  • Committer: Vojtech Horky
  • Author(s): Balaji Rao
  • Date: 2012-03-29 07:56:17 UTC
  • mto: (1460.2.42 mainline)
  • mto: This revision was merged to the branch mainline in revision 1447.
  • Revision ID: vojtechhorky@users.sourceforge.net-20120329075617-iuilcuha9x4h0vcq
Support for LFN in mkfat.py utility (#400)

mkfat.py is now able to handle long filenames. Support for filenames
with characters outside of base ASCII is still missing, though.

Show diffs side-by-side

added added

removed removed

Lines of Context:
167
167
        uint32_t size              /* file size */
168
168
"""
169
169
 
170
 
def mangle_fname(name):
 
170
LFN_ENTRY = """little:
 
171
        uint8_t pos
 
172
        uint16_t name1[5]
 
173
        uint8_t attr
 
174
        uint8_t type
 
175
        uint8_t csum
 
176
        uint16_t name2[6]
 
177
        uint16_t fc
 
178
        uint16_t name3[2]
 
179
"""
 
180
 
 
181
# Global variable to hold the file names in 8.3 format. Needed to 
 
182
# keep track of "number" when creating a short fname from a LFN.
 
183
name83_list = []
 
184
 
 
185
def name83(fname):
 
186
        "Create a 8.3 name for the given fname"
 
187
 
171
188
        # FIXME: filter illegal characters
172
 
        parts = name.split('.')
 
189
        parts = fname.split('.')
173
190
        
 
191
        name = ''
 
192
        ext = ''
 
193
        lfn = False
 
194
 
 
195
        if len(fname) > 11 :
 
196
                lfn = True
 
197
 
174
198
        if len(parts) > 0:
175
 
                fname = parts[0]
176
 
        else:
177
 
                fname = ''
178
 
        
179
 
        if len(fname) > 8:
180
 
                sys.stdout.write("mkfat.py: error: Directory entry " + name +
181
 
                    " base name is longer than 8 characters\n")
182
 
                sys.exit(1);
183
 
        
184
 
        return (fname + '          ').upper()[0:8]
185
 
 
186
 
def mangle_ext(name):
187
 
        # FIXME: filter illegal characters
188
 
        parts = name.split('.')
189
 
        
190
 
        if len(parts) > 1:
191
 
                ext = parts[1]
192
 
        else:
193
 
                ext = ''
194
 
        
195
 
        if len(parts) > 2:
196
 
                sys.stdout.write("mkfat.py: error: Directory entry " + name +
197
 
                    " has more than one extension\n")
198
 
                sys.exit(1);
199
 
        
200
 
        if len(ext) > 3:
201
 
                sys.stdout.write("mkfat.py: error: Directory entry " + name +
202
 
                    " extension is longer than 3 characters\n")
203
 
                sys.exit(1);
204
 
        
205
 
        return (ext + '   ').upper()[0:3]
 
199
                name = parts[0]
 
200
                if len(name) > 8 :
 
201
                        lfn = True
 
202
 
 
203
        if len(parts) > 1 :
 
204
                ext = parts[-1]
 
205
                if len(ext) > 3 :
 
206
                        lfn = True
 
207
 
 
208
        if len(parts) > 2 :
 
209
                lfn = True
 
210
 
 
211
        if (lfn == False) :
 
212
                return (name.ljust(8)[0:8], ext.ljust(3)[0:3], False)
 
213
 
 
214
        # For filenames with multiple extensions, we treat the last one
 
215
        # as the actual extension. The rest of the filename is stripped
 
216
        # of dots and concatenated to form the short name
 
217
        for _name in parts[1:-1]:
 
218
                name = name + _name             
 
219
 
 
220
        global name83_list
 
221
        for number in range(1, 10000) :
 
222
                number_str = '~' + str(number)
 
223
 
 
224
                if len(name) + len(number_str) > 8 :
 
225
                        name = name[0:8 - len(number_str)]
 
226
 
 
227
                name = name + number_str;
 
228
 
 
229
                if (name + ext) not in name83_list :
 
230
                        break
 
231
                        
 
232
        name83_list.append(name + ext)  
 
233
 
 
234
        return (name.ljust(8)[0:8], ext.ljust(3)[0:3], True)
 
235
 
 
236
def get_utf16(name, l) :
 
237
        "Create a int array out of a string which we can store in uint16_t arrays"
 
238
 
 
239
        bs = [0xFFFF for i in range(l)]
 
240
 
 
241
        for i in range(len(name)) :
 
242
                bs[i] = ord(name[i])
 
243
        
 
244
        if (len(name) < l) :
 
245
                bs[len(name)] = 0;
 
246
        
 
247
        return bs
 
248
 
 
249
def create_lfn_entry((name, index)) :
 
250
        entry = xstruct.create(LFN_ENTRY)
 
251
 
 
252
        entry.name1 = get_utf16(name[0:5], 5)
 
253
        entry.name2 = get_utf16(name[5:11], 6)
 
254
        entry.name3 = get_utf16(name[11:13], 2)
 
255
        entry.pos = index
 
256
 
 
257
        entry.attr = 0xF
 
258
        entry.fc = 0
 
259
        entry.type = 0
 
260
 
 
261
        return entry
206
262
 
207
263
def create_dirent(name, directory, cluster, size):
 
264
        
208
265
        dir_entry = xstruct.create(DIR_ENTRY)
209
266
        
210
 
        dir_entry.name = mangle_fname(name).encode('ascii')
211
 
        dir_entry.ext = mangle_ext(name).encode('ascii')
212
 
        
 
267
        dir_entry.name, dir_entry.ext, lfn = name83(name)
 
268
 
 
269
        dir_entry.name = dir_entry.name.upper().encode('ascii')
 
270
        dir_entry.ext = dir_entry.ext.upper().encode('ascii')
 
271
 
213
272
        if (directory):
214
273
                dir_entry.attr = 0x30
215
274
        else:
229
288
        else:
230
289
                dir_entry.size = size
231
290
        
232
 
        return dir_entry
 
291
 
 
292
        if not lfn:
 
293
                return [dir_entry]
 
294
 
 
295
        n = len(name) / 13 + 1
 
296
        names = [(name[i * 13: (i + 1) * 13 + 1], i + 1) for i in range(n)]
 
297
 
 
298
        entries = sorted(map (create_lfn_entry, names), reverse = True, key = lambda e : e.pos)
 
299
        entries[0].pos |= 0x40
 
300
 
 
301
        fname11 = dir_entry.name + dir_entry.ext
 
302
 
 
303
        csum = 0
 
304
        for i in range(0, 11) :
 
305
                csum = ((csum & 1) << 7) + (csum  >> 1) + ord(fname11[i])
 
306
                csum = csum & 0xFF
 
307
        
 
308
        for e in entries :
 
309
                e.csum = csum;
 
310
        
 
311
        entries.append(dir_entry)
 
312
 
 
313
        return entries
233
314
 
234
315
def create_dot_dirent(empty_cluster):
235
316
        dir_entry = xstruct.create(DOT_DIR_ENTRY)
287
368
        for item in listdir_items(root):                
288
369
                if item.is_file:
289
370
                        rv = write_file(item, outf, cluster_size, data_start, fat, reserved_clusters)
290
 
                        directory.append(create_dirent(item.name, False, rv[0], rv[1]))
 
371
                        directory.extend(create_dirent(item.name, False, rv[0], rv[1]))
291
372
                elif item.is_dir:
292
373
                        rv = recursion(False, item.path, outf, cluster_size, root_start, data_start, fat, reserved_clusters, dirent_size, empty_cluster)
293
 
                        directory.append(create_dirent(item.name, True, rv[0], rv[1]))
 
374
                        directory.extend(create_dirent(item.name, True, rv[0], rv[1]))
294
375
        
295
376
        if (head):
296
377
                outf.seek(root_start)