/js/lib/Socket.IO-node/support/expresso/deps/jscoverage/instrument.c
C | 226 lines | 166 code | 33 blank | 27 comment | 43 complexity | 9a37774a7c2ec1fc71c4119d45552e8f MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause
- /*
- instrument.c - file and directory instrumentation routines
- Copyright (C) 2007, 2008 siliconforks.com
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
- #include <config.h>
- #include "instrument.h"
- #include <assert.h>
- #include <errno.h>
- #include <string.h>
- #include <dirent.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include "encoding.h"
- #include "global.h"
- #include "instrument-js.h"
- #include "resource-manager.h"
- #include "util.h"
- static int g_verbose = 0;
- static int string_ends_with(const char * s, const char * suffix) {
- size_t length = strlen(s);
- size_t suffix_length = strlen(suffix);
- if (length < suffix_length) {
- return 0;
- }
- return strcasecmp(s + (length - suffix_length), suffix) == 0;
- }
- static enum FileType get_file_type(const char * file) {
- if (string_ends_with(file, ".js")) {
- return FILE_TYPE_JS;
- }
- else if (string_ends_with(file, ".html") || string_ends_with(file, ".htm")) {
- return FILE_TYPE_HTML;
- }
- else {
- return FILE_TYPE_OTHER;
- }
- }
- static void check_same_file(const char * file1, const char * file2) {
- if (is_same_file(file1, file2)) {
- fatal("source and destination are the same");
- }
- }
- static void check_contains_file(const char * file1, const char * file2) {
- if (contains_file(file1, file2)) {
- fatal("%s contains %s", file1, file2);
- }
- }
- 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);
- }
- }
- 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_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);
- }
- /* 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);
- }