static void instrument_file(const char * source_file, const char * destination_file, const char * id, int instrumenting) { if (g_verbose) { printf("Instrumenting file %s\n", id); } /* check if they are the same */ char * canonical_source_file = make_canonical_path(source_file); char * canonical_destination_file = make_canonical_path(destination_file); check_same_file(canonical_source_file, canonical_destination_file); free(canonical_source_file); free(canonical_destination_file); if (instrumenting) { enum FileType file_type = get_file_type(source_file); switch (file_type) { case FILE_TYPE_OTHER: case FILE_TYPE_HTML: copy_file(source_file, destination_file); break; case FILE_TYPE_JS: { FILE * input = xfopen(source_file, "rb"); FILE * output = xfopen(destination_file, "wb"); Stream * input_stream = Stream_new(0); Stream * output_stream = Stream_new(0); Stream_write_file_contents(input_stream, input); size_t num_characters = input_stream->length; uint16_t * characters = NULL; int result = jscoverage_bytes_to_characters(jscoverage_encoding, input_stream->data, input_stream->length, &characters, &num_characters); if (result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED) { fatal("encoding %s not supported", jscoverage_encoding); } else if (result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE) { fatal("error decoding %s in file %s", jscoverage_encoding, id); } jscoverage_instrument_js(id, characters, num_characters, output_stream); free(characters); if (fwrite(output_stream->data, 1, output_stream->length, output) != output_stream->length) { fatal("cannot write to file: %s", destination_file); } Stream_delete(input_stream); Stream_delete(output_stream); fclose(input); fclose(output); } break; } } else { copy_file(source_file, destination_file); } }
static void instrument_file(const char * source_file, const char * destination_file, const char * id, int instrumenting) { /* check if they are the same */ char * canonical_source_file = make_canonical_path(source_file); char * canonical_destination_file = make_canonical_path(destination_file); check_same_file(canonical_source_file, canonical_destination_file); free(canonical_source_file); free(canonical_destination_file); if (instrumenting) { enum FileType file_type = get_file_type(source_file); switch (file_type) { case FILE_TYPE_OTHER: case FILE_TYPE_HTML: if (g_verbose) { printf("Copying file %s\n", id); } copy_file(source_file, destination_file); break; case FILE_TYPE_JS: { if (g_verbose) { printf("Instrumenting file %s\n", id); } FILE * input = xfopen(source_file, "rb"); FILE * output = xfopen(destination_file, "wb"); Stream * input_stream = Stream_new(0); Stream * output_stream = Stream_new(0); Stream_write_file_contents(input_stream, input); /* Check if the source file looks like an instrumented JavaScript file. */ if (input_stream->length >= JSCOVERAGE_INSTRUMENTED_HEADER_LENGTH && memcmp(input_stream->data, JSCOVERAGE_INSTRUMENTED_HEADER, JSCOVERAGE_INSTRUMENTED_HEADER_LENGTH) == 0) { fatal_command_line("file %s in the source directory appears to be already instrumented", id); } size_t num_characters = input_stream->length; uint16_t * characters = NULL; int result = jscoverage_bytes_to_characters(jscoverage_encoding, input_stream->data, input_stream->length, &characters, &num_characters); if (result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED) { fatal("encoding %s not supported", jscoverage_encoding); } else if (result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE) { fatal("error decoding %s in file %s", jscoverage_encoding, id); } jscoverage_instrument_js(id, characters, num_characters, output_stream); free(characters); if (fwrite(output_stream->data, 1, output_stream->length, output) != output_stream->length) { fatal("cannot write to file: %s", destination_file); } Stream_delete(input_stream); Stream_delete(output_stream); fclose(input); fclose(output); } break; } } else { if (g_verbose) { printf("Copying file %s (on --no-instrument list)\n", id); } copy_file(source_file, destination_file); } }
void jscoverage_instrument(const char * source, const char * destination, int verbose, char ** exclude, int num_exclude, char ** no_instrument, int num_no_instrument) { assert(source != NULL); assert(destination != NULL); g_verbose = verbose; /* check if they are the same */ check_same_file(source, destination); /* check if source directory is an ancestor of destination directory */ check_contains_file(source, destination); /* check that the source exists and is a directory */ struct stat buf; xstat(source, &buf); if (! S_ISDIR(buf.st_mode)) { fatal("not a directory: %s", source); } /* if the destination directory exists, check that it is a jscoverage directory */ if (stat(destination, &buf) == 0) { /* it exists */ if (! S_ISDIR(buf.st_mode)) { fatal("not a directory: %s", destination); } if (! directory_is_empty(destination)) { char * expected_file = NULL; if (jscoverage_mode == JSCOVERAGE_MOZILLA) { char * modules_directory = make_path(destination, "modules"); expected_file = make_path(modules_directory, "jscoverage.jsm"); free(modules_directory); } else { expected_file = make_path(destination, "jscoverage.html"); } if (stat(expected_file, &buf) == -1) { fatal("refusing to overwrite directory: %s", destination); } free(expected_file); } } else if (errno == ENOENT) { xmkdir(destination); } else { fatal("cannot stat directory: %s", destination); } /* copy the resources */ if (jscoverage_mode == JSCOVERAGE_MOZILLA) { char * chrome_directory = make_path(destination, "chrome"); char * jscoverage_chrome_directory = make_path(chrome_directory, "jscoverage"); mkdirs(jscoverage_chrome_directory); copy_resource("jscoverage.manifest", chrome_directory); copy_resource("jscoverage.html", jscoverage_chrome_directory); copy_resource("jscoverage.css", jscoverage_chrome_directory); copy_resource("jscoverage.js", jscoverage_chrome_directory); copy_resource("jscoverage-throbber.gif", jscoverage_chrome_directory); copy_resource("jscoverage-highlight.css", jscoverage_chrome_directory); copy_resource("jscoverage.xul", jscoverage_chrome_directory); copy_resource("jscoverage-overlay.js", jscoverage_chrome_directory); free(jscoverage_chrome_directory); free(chrome_directory); char * modules_directory = make_path(destination, "modules"); mkdirs(modules_directory); copy_resource("jscoverage.jsm", modules_directory); free(modules_directory); } else { jscoverage_copy_resources(destination); } /* finally: copy the directory */ struct DirListEntry * list = make_recursive_dir_list(source); for (struct DirListEntry * p = list; p != NULL; p = p->next) { char * s = make_path(source, p->name); char * d = make_path(destination, p->name); /* check if it's on the exclude list */ for (int i = 0; i < num_exclude; i++) { char * x = make_path(source, exclude[i]); if (is_same_file(x, s) || contains_file(x, s)) { free(x); goto cleanup; } free(x); } char * dd = make_dirname(d); mkdirs(dd); free(dd); int instrument_this = 1; /* check if it's on the no-instrument list */ for (int i = 0; i < num_no_instrument; i++) { char * ni = make_path(source, no_instrument[i]); if (is_same_file(ni, s) || contains_file(ni, s)) { instrument_this = 0; } free(ni); } instrument_file(s, d, p->name, instrument_this); cleanup: free(s); free(d); } free_dir_list(list); }