PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/js/lib/Socket.IO-node/support/expresso/deps/jscoverage/instrument.c

http://github.com/onedayitwillmake/RealtimeMultiplayerNodeJs
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
  1. /*
  2. instrument.c - file and directory instrumentation routines
  3. Copyright (C) 2007, 2008 siliconforks.com
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #include <config.h>
  17. #include "instrument.h"
  18. #include <assert.h>
  19. #include <errno.h>
  20. #include <string.h>
  21. #include <dirent.h>
  22. #include <sys/stat.h>
  23. #include <sys/types.h>
  24. #include "encoding.h"
  25. #include "global.h"
  26. #include "instrument-js.h"
  27. #include "resource-manager.h"
  28. #include "util.h"
  29. static int g_verbose = 0;
  30. static int string_ends_with(const char * s, const char * suffix) {
  31. size_t length = strlen(s);
  32. size_t suffix_length = strlen(suffix);
  33. if (length < suffix_length) {
  34. return 0;
  35. }
  36. return strcasecmp(s + (length - suffix_length), suffix) == 0;
  37. }
  38. static enum FileType get_file_type(const char * file) {
  39. if (string_ends_with(file, ".js")) {
  40. return FILE_TYPE_JS;
  41. }
  42. else if (string_ends_with(file, ".html") || string_ends_with(file, ".htm")) {
  43. return FILE_TYPE_HTML;
  44. }
  45. else {
  46. return FILE_TYPE_OTHER;
  47. }
  48. }
  49. static void check_same_file(const char * file1, const char * file2) {
  50. if (is_same_file(file1, file2)) {
  51. fatal("source and destination are the same");
  52. }
  53. }
  54. static void check_contains_file(const char * file1, const char * file2) {
  55. if (contains_file(file1, file2)) {
  56. fatal("%s contains %s", file1, file2);
  57. }
  58. }
  59. static void instrument_file(const char * source_file, const char * destination_file, const char * id, int instrumenting) {
  60. if (g_verbose) {
  61. printf("Instrumenting file %s\n", id);
  62. }
  63. /* check if they are the same */
  64. char * canonical_source_file = make_canonical_path(source_file);
  65. char * canonical_destination_file = make_canonical_path(destination_file);
  66. check_same_file(canonical_source_file, canonical_destination_file);
  67. free(canonical_source_file);
  68. free(canonical_destination_file);
  69. if (instrumenting) {
  70. enum FileType file_type = get_file_type(source_file);
  71. switch (file_type) {
  72. case FILE_TYPE_OTHER:
  73. case FILE_TYPE_HTML:
  74. copy_file(source_file, destination_file);
  75. break;
  76. case FILE_TYPE_JS:
  77. {
  78. FILE * input = xfopen(source_file, "rb");
  79. FILE * output = xfopen(destination_file, "wb");
  80. Stream * input_stream = Stream_new(0);
  81. Stream * output_stream = Stream_new(0);
  82. Stream_write_file_contents(input_stream, input);
  83. size_t num_characters = input_stream->length;
  84. uint16_t * characters = NULL;
  85. int result = jscoverage_bytes_to_characters(jscoverage_encoding, input_stream->data, input_stream->length, &characters, &num_characters);
  86. if (result == JSCOVERAGE_ERROR_ENCODING_NOT_SUPPORTED) {
  87. fatal("encoding %s not supported", jscoverage_encoding);
  88. }
  89. else if (result == JSCOVERAGE_ERROR_INVALID_BYTE_SEQUENCE) {
  90. fatal("error decoding %s in file %s", jscoverage_encoding, id);
  91. }
  92. jscoverage_instrument_js(id, characters, num_characters, output_stream);
  93. free(characters);
  94. if (fwrite(output_stream->data, 1, output_stream->length, output) != output_stream->length) {
  95. fatal("cannot write to file: %s", destination_file);
  96. }
  97. Stream_delete(input_stream);
  98. Stream_delete(output_stream);
  99. fclose(input);
  100. fclose(output);
  101. }
  102. break;
  103. }
  104. }
  105. else {
  106. copy_file(source_file, destination_file);
  107. }
  108. }
  109. void jscoverage_instrument(const char * source,
  110. const char * destination,
  111. int verbose,
  112. char ** exclude,
  113. int num_exclude,
  114. char ** no_instrument,
  115. int num_no_instrument)
  116. {
  117. assert(source != NULL);
  118. assert(destination != NULL);
  119. g_verbose = verbose;
  120. /* check if they are the same */
  121. check_same_file(source, destination);
  122. /* check if source directory is an ancestor of destination directory */
  123. check_contains_file(source, destination);
  124. /* check that the source exists and is a directory */
  125. struct stat buf;
  126. xstat(source, &buf);
  127. if (! S_ISDIR(buf.st_mode)) {
  128. fatal("not a directory: %s", source);
  129. }
  130. /* if the destination directory exists, check that it is a jscoverage directory */
  131. if (stat(destination, &buf) == 0) {
  132. /* it exists */
  133. if (! S_ISDIR(buf.st_mode)) {
  134. fatal("not a directory: %s", destination);
  135. }
  136. if (! directory_is_empty(destination)) {
  137. char * expected_file = NULL;
  138. if (jscoverage_mozilla) {
  139. char * modules_directory = make_path(destination, "modules");
  140. expected_file = make_path(modules_directory, "jscoverage.jsm");
  141. free(modules_directory);
  142. }
  143. else {
  144. expected_file = make_path(destination, "jscoverage.html");
  145. }
  146. if (stat(expected_file, &buf) == -1) {
  147. fatal("refusing to overwrite directory: %s", destination);
  148. }
  149. free(expected_file);
  150. }
  151. }
  152. else if (errno == ENOENT) {
  153. xmkdir(destination);
  154. }
  155. else {
  156. fatal("cannot stat directory: %s", destination);
  157. }
  158. /* finally: copy the directory */
  159. struct DirListEntry * list = make_recursive_dir_list(source);
  160. for (struct DirListEntry * p = list; p != NULL; p = p->next) {
  161. char * s = make_path(source, p->name);
  162. char * d = make_path(destination, p->name);
  163. /* check if it's on the exclude list */
  164. for (int i = 0; i < num_exclude; i++) {
  165. char * x = make_path(source, exclude[i]);
  166. if (is_same_file(x, s) || contains_file(x, s)) {
  167. free(x);
  168. goto cleanup;
  169. }
  170. free(x);
  171. }
  172. char * dd = make_dirname(d);
  173. mkdirs(dd);
  174. free(dd);
  175. int instrument_this = 1;
  176. /* check if it's on the no-instrument list */
  177. for (int i = 0; i < num_no_instrument; i++) {
  178. char * ni = make_path(source, no_instrument[i]);
  179. if (is_same_file(ni, s) || contains_file(ni, s)) {
  180. instrument_this = 0;
  181. }
  182. free(ni);
  183. }
  184. instrument_file(s, d, p->name, instrument_this);
  185. cleanup:
  186. free(s);
  187. free(d);
  188. }
  189. free_dir_list(list);
  190. }