153
# Win32 code to test whether the given file has the hidden property set.
154
def has_hidden_attribute(filepath):
155
if sys.platform != 'win32':
159
attrs = ctypes.windll.kernel32.GetFileAttributesW(unicode(filepath))
161
result = bool(attrs & 2)
162
except (AttributeError, AssertionError):
166
# The packager should never preload/embed any directories that have a component starting with '.' in them,
167
# or if the file is hidden (Win32). Note that this filter ONLY applies to directories. Explicitly specified single files
168
# are always preloaded/embedded, even if they start with a '.'.
169
def should_ignore(filename):
170
if has_hidden_attribute(filename):
173
components = filename.replace('\\\\', '/').replace('\\', '/').split('/')
175
if c.startswith('.') and c != '.' and c != '..':
153
179
# Expand directories into individual files
154
180
def add(arg, dirname, names):
155
181
# rootpathsrc: The path name of the root directory on the local FS we are adding to emscripten virtual FS.
158
184
for name in names:
159
185
fullname = os.path.join(dirname, name)
160
186
if not os.path.isdir(fullname):
161
dstpath = os.path.join(rootpathdst, os.path.relpath(fullname, rootpathsrc)) # Convert source filename relative to root directory of target FS.
162
data_files.append({ 'srcpath': fullname, 'dstpath': dstpath, 'mode': mode })
187
if should_ignore(fullname):
189
print >> sys.stderr, 'Skipping hidden file "' + fullname + '" from inclusion in the emscripten virtual file system.'
191
dstpath = os.path.join(rootpathdst, os.path.relpath(fullname, rootpathsrc)) # Convert source filename relative to root directory of target FS.
192
data_files.append({ 'srcpath': fullname, 'dstpath': dstpath, 'mode': mode })
164
194
for file_ in data_files:
165
195
if os.path.isdir(file_['srcpath']):
166
196
os.path.walk(file_['srcpath'], add, [file_['mode'], file_['srcpath'], file_['dstpath']])
167
197
data_files = filter(lambda file_: not os.path.isdir(file_['srcpath']), data_files)
199
# Absolutize paths, and check that they make sense
200
curr_abspath = os.path.abspath(os.getcwd())
201
for file_ in data_files:
202
if file_['srcpath'] == file_['dstpath']:
203
# This file was not defined with src@dst, so we inferred the destination from the source. In that case,
204
# we require that the destination not be under the current location
205
path = file_['dstpath']
206
abspath = os.path.abspath(path)
207
if DEBUG: print >> sys.stderr, path, abspath, curr_abspath
208
if not abspath.startswith(curr_abspath):
209
print >> sys.stderr, 'Error: Embedding "%s" which is below the current directory "%s". This is invalid since the current directory becomes the root that the generated code will see' % (path, curr_abspath)
211
file_['dstpath'] = abspath[len(curr_abspath)+1:]
212
if os.path.isabs(path):
213
print >> sys.stderr, 'Warning: Embedding an absolute file/directory name "' + path + '" to the virtual filesystem. The file will be made available in the relative path "' + file_['dstpath'] + '". You can use the explicit syntax --preload-file srcpath@dstpath to explicitly specify the target location the absolute source path should be directed to.'
169
215
for file_ in data_files:
170
216
file_['dstpath'] = file_['dstpath'].replace(os.path.sep, '/') # name in the filesystem, native and emulated
171
217
if file_['dstpath'].endswith('/'): # If user has submitted a directory name as the destination but omitted the destination filename, use the filename from source file
172
218
file_['dstpath'] = file_['dstpath'] + os.path.basename(file_['srcpath'])
173
if file_['dstpath'].startswith('./'): file_['dstpath'] = file_['dstpath'][2:] # remove redundant ./ prefix
219
# make destination path always relative to the root
220
file_['dstpath'] = posixpath.normpath(os.path.join('/', file_['dstpath']))
222
print >> sys.stderr, 'Packaging file "' + file_['srcpath'] + '" to VFS in path "' + file_['dstpath'] + '".'
175
224
# Remove duplicates (can occur naively, for example preload dir/, preload dir/subdir/)
281
330
# Data requests - for getting a block of data out of the big archive - have a similar API to XHRs
283
function DataRequest() {}
332
function DataRequest(start, end, crunched, audio) {
335
this.crunched = crunched;
284
338
DataRequest.prototype = {
286
340
open: function(mode, name) {
287
342
this.requests[name] = this;
343
Module['addRunDependency']('fp ' + this.name);
347
var byteArray = this.byteArray.subarray(this.start, this.end);
349
var ddsHeader = byteArray.subarray(0, 128);
351
requestDecrunch(this.name, byteArray.subarray(128), function(ddsData) {
352
byteArray = new Uint8Array(ddsHeader.length + ddsData.length);
353
byteArray.set(ddsHeader, 0);
354
byteArray.set(ddsData, 128);
355
that.finish(byteArray);
358
this.finish(byteArray);
361
finish: function(byteArray) {
363
Module['FS_createPreloadedFile'](this.name, null, byteArray, true, true, function() {
364
Module['removeRunDependency']('fp ' + that.name);
367
Module['removeRunDependency']('fp ' + that.name); // workaround for chromium bug 124926 (still no audio with this, but at least we don't hang)
369
Runtime.warn('Preloading file ' + that.name + ' failed');
371
}, false, true); // canOwn this data in the filesystem, it is a slide into the heap that will never change
372
this.requests[this.name] = null;
294
378
for file_ in data_files:
295
379
filename = file_['dstpath']
380
dirname = os.path.dirname(filename)
381
basename = os.path.basename(filename)
296
382
if file_['mode'] == 'embed':
298
384
data = map(ord, open(file_['srcpath'], 'rb').read())
302
chunk = data[:chunk_size]
303
data = data[chunk_size:]
305
str_data = str(chunk)
307
str_data += '.concat(' + str(chunk) + ')'
308
code += '''Module['FS_createDataFile']('/%s', '%s', %s, true, true);\n''' % (os.path.dirname(filename), os.path.basename(filename), str_data)
391
chunk = data[:chunk_size]
392
data = data[chunk_size:]
394
str_data = str(chunk)
396
str_data += '.concat(' + str(chunk) + ')'
397
code += '''Module['FS_createDataFile']('%s', '%s', %s, true, true);\n''' % (dirname, basename, str_data)
309
398
elif file_['mode'] == 'preload':
311
400
varname = 'filePreload%d' % counter
313
dds = crunch and filename.endswith(CRUNCH_INPUT_SUFFIX)
316
finish = "Module['removeRunDependency']('fp %s');\n" % filename
319
# decompress crunch format into dds
321
var ddsHeader = byteArray.subarray(0, %(dds_header_size)d);
322
requestDecrunch('%(filename)s', byteArray.subarray(%(dds_header_size)d), function(ddsData) {
323
byteArray = new Uint8Array(ddsHeader.length + ddsData.length);
324
byteArray.set(ddsHeader, 0);
325
byteArray.set(ddsData, %(dds_header_size)d);
326
''' % { 'filename': filename, 'dds_header_size': DDS_HEADER_SIZE }
333
var %(varname)s = new %(request)s();
334
%(varname)s.open('GET', '%(filename)s', true);
335
%(varname)s.responseType = 'arraybuffer';
336
%(varname)s.onload = function() {
337
var arrayBuffer = %(varname)s.response;
338
assert(arrayBuffer, 'Loading file %(filename)s failed.');
339
var byteArray = !arrayBuffer.subarray ? new Uint8Array(arrayBuffer) : arrayBuffer;
341
Module['FS_createPreloadedFile']('/%(dirname)s', '%(basename)s', byteArray, true, true, function() {
345
Module['addRunDependency']('fp %(filename)s');
346
%(varname)s.send(null);
402
code += ''' new DataRequest(%(start)d, %(end)d, %(crunched)s, %(audio)s).open('GET', '%(filename)s');
348
'request': 'DataRequest', # In the past we also supported XHRs here
350
'filename': filename,
351
'dirname': os.path.dirname(filename),
352
'basename': os.path.basename(filename),
355
'fail': '' if filename[-4:] not in AUDIO_SUFFIXES else ''', function() { Module['removeRunDependency']('fp %s') }''' % filename # workaround for chromium bug 124926 (still no audio with this, but at least we don't hang)
404
'filename': file_['dstpath'],
405
'start': file_['data_start'],
406
'end': file_['data_end'],
407
'crunched': '1' if crunch and filename.endswith(CRUNCH_INPUT_SUFFIX) else '0',
408
'audio': '1' if filename[-4:] in AUDIO_SUFFIXES else '0',
360
413
if has_preloaded:
361
414
# Get the big archive and split it up
416
// copy the entire loaded file into a spot in the heap. Files will refer to slices in that. They cannot be freed though.
417
var ptr = Module['_malloc'](byteArray.length);
418
Module['HEAPU8'].set(byteArray, ptr);
419
DataRequest.prototype.byteArray = Module['HEAPU8'].subarray(ptr, ptr+byteArray.length);
363
421
for file_ in data_files:
364
422
if file_['mode'] == 'preload':
366
curr = DataRequest.prototype.requests['%s'];
367
var data = byteArray.subarray(%d, %d);
368
var ptr = Module['_malloc'](%d);
369
Module['HEAPU8'].set(data, ptr);
370
curr.response = Module['HEAPU8'].subarray(ptr, ptr + %d);
372
''' % (file_['dstpath'], file_['data_start'], file_['data_end'], file_['data_end'] - file_['data_start'], file_['data_end'] - file_['data_start'])
423
use_data += ' DataRequest.prototype.requests["%s"].onload();\n' % (file_['dstpath'])
373
424
use_data += " Module['removeRunDependency']('datafile_%s');\n" % data_target
375
426
if Compression.on: