24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 */ |
25 */ |
26 |
26 |
27 |
27 |
28 #include "scanner.h" |
28 #include "scanner.h" |
29 #include "suffix_fnc.h" |
|
30 #include "bfile_heuristics.h" |
29 #include "bfile_heuristics.h" |
31 #include "regex_parser.h" |
30 #include "regex_parser.h" |
32 #include <sys/stat.h> |
31 #include <sys/stat.h> |
33 |
32 |
34 typedef struct filelist filelist_t; |
33 typedef struct filelist filelist_t; |
35 |
34 |
36 struct filelist { |
35 struct filelist { |
37 char *displayname; |
36 char *displayname; |
38 int displayname_len; |
37 int displayname_len; |
39 char *filename; |
38 char *filename; |
|
39 char *ext; |
40 int st_mode; |
40 int st_mode; |
41 filelist_t *next; |
41 filelist_t *next; |
42 }; |
42 }; |
43 |
43 |
44 filelist_t *buildFileList(scanner_t scanner, settings_t* settings, |
44 static bool testSuffix(char* filename, string_list_t* list) { |
|
45 bool ret = false; |
|
46 int tokenlen, fnamelen = strlen(filename); |
|
47 for (int t = 0 ; t < list->count ; t++) { |
|
48 tokenlen = strlen(list->items[t]); |
|
49 if (fnamelen >= tokenlen && tokenlen > 0) { |
|
50 if (strncmp(filename+fnamelen-tokenlen, |
|
51 list->items[t], tokenlen) == 0) { |
|
52 ret = true; |
|
53 break; |
|
54 } |
|
55 } |
|
56 } |
|
57 return ret; |
|
58 } |
|
59 |
|
60 static void addLinesPerExtension(scanresult_ext_t* result, |
|
61 char* ext, int lines) { |
|
62 if (!result) return; |
|
63 |
|
64 if (!ext) ext = "w/o"; |
|
65 |
|
66 for (int i = 0 ; i < result->count ; i++) { |
|
67 if (strcasecmp(result->extensions[i], ext) == 0) { |
|
68 result->lines[i] += lines; |
|
69 return; |
|
70 } |
|
71 } |
|
72 |
|
73 if (result->count == result->capacity) { |
|
74 int newcap = result->capacity+8; |
|
75 char** extarr = realloc(result->extensions, newcap*sizeof(char*)); |
|
76 int* linesarr = realloc(result->lines, newcap*sizeof(int)); |
|
77 if (!extarr || !linesarr) { |
|
78 fprintf(stderr, "Memory allocation error.\n"); |
|
79 abort(); |
|
80 } |
|
81 result->extensions = extarr; |
|
82 result->lines = linesarr; |
|
83 result->capacity = newcap; |
|
84 } |
|
85 |
|
86 result->extensions[result->count] = strdup(ext); |
|
87 result->lines[result->count] = lines; |
|
88 result->count++; |
|
89 } |
|
90 |
|
91 scanresult_t* new_scanresult_t(settings_t* settings) { |
|
92 scanresult_t* result = calloc(1, sizeof(scanresult_t)); |
|
93 if (settings->individual_sums) { |
|
94 result->ext = calloc(1, sizeof(scanresult_ext_t)); |
|
95 } |
|
96 return result; |
|
97 } |
|
98 |
|
99 void destroy_scanresult_t(scanresult_t* result) { |
|
100 if (result->ext) { |
|
101 if (result->ext->count > 0) { |
|
102 for (int i = 0 ; i < result->ext->count ; i++) { |
|
103 free(result->ext->extensions[i]); |
|
104 } |
|
105 free(result->ext->extensions); |
|
106 free(result->ext->lines); |
|
107 } |
|
108 free(result->ext); |
|
109 } |
|
110 free(result); |
|
111 } |
|
112 |
|
113 |
|
114 static filelist_t *buildFileList(scanner_t scanner, settings_t* settings, |
45 filelist_t* list) { |
115 filelist_t* list) { |
46 |
116 |
47 DIR *dirf; |
117 DIR *dirf; |
48 struct dirent *entry; |
118 struct dirent *entry; |
49 struct stat statbuf; |
119 struct stat statbuf; |
74 memcpy(filename, scanner.dir, dirnamelen); |
144 memcpy(filename, scanner.dir, dirnamelen); |
75 filename[dirnamelen] = settings->fileSeparator; |
145 filename[dirnamelen] = settings->fileSeparator; |
76 memcpy(filename+dirnamelen+1, entry->d_name, newentry->displayname_len); |
146 memcpy(filename+dirnamelen+1, entry->d_name, newentry->displayname_len); |
77 filename[1+dirnamelen+newentry->displayname_len] = 0; |
147 filename[1+dirnamelen+newentry->displayname_len] = 0; |
78 newentry->filename = filename; |
148 newentry->filename = filename; |
|
149 |
|
150 /* Obtain file extension */ |
|
151 newentry->ext = strrchr(newentry->displayname, '.'); |
79 |
152 |
80 /* Check for subdirectory */ |
153 /* Check for subdirectory */ |
81 if (stat(filename, &statbuf) == 0) { |
154 if (stat(filename, &statbuf) == 0) { |
82 newentry->st_mode = statbuf.st_mode; |
155 newentry->st_mode = statbuf.st_mode; |
83 } else { |
156 } else { |
113 } |
186 } |
114 |
187 |
115 void scanDirectory(scanner_t scanner, settings_t* settings, |
188 void scanDirectory(scanner_t scanner, settings_t* settings, |
116 string_list_t* output, scanresult_t* result) { |
189 string_list_t* output, scanresult_t* result) { |
117 |
190 |
118 result->directory = 0; |
191 result->lines = 0; |
119 int a; |
192 int a; |
120 bool bfile; |
193 bool bfile; |
121 char *outbuf; |
194 char *outbuf; |
122 |
195 |
123 filelist_t *filelist = buildFileList(scanner, settings, NULL); |
196 filelist_t *filelist = buildFileList(scanner, settings, NULL); |
127 /* Scan subdirectories */ |
200 /* Scan subdirectories */ |
128 if (!S_ISREG(filelist->st_mode)) { |
201 if (!S_ISREG(filelist->st_mode)) { |
129 if (settings->recursive && S_ISDIR(filelist->st_mode)) { |
202 if (settings->recursive && S_ISDIR(filelist->st_mode)) { |
130 string_list_t *recoutput = new_string_list_t(); |
203 string_list_t *recoutput = new_string_list_t(); |
131 scanresult_t recresult; |
204 scanresult_t recresult; |
|
205 recresult.ext = result->ext; |
132 scanDirectory( |
206 scanDirectory( |
133 (scanner_t) {filelist->filename, scanner.spaces+1}, |
207 (scanner_t) {filelist->filename, scanner.spaces+1}, |
134 settings, recoutput, &recresult); |
208 settings, recoutput, &recresult); |
135 result->directory += recresult.directory; |
209 result->lines += recresult.lines; |
136 if (!settings->matchesOnly || recoutput->count > 0) { |
210 if (!settings->matchesOnly || recoutput->count > 0) { |
137 outbuf = (char*) malloc(81); |
211 outbuf = (char*) malloc(81); |
138 snprintf(outbuf, 81, "%*s/%*s%13d lines\n", |
212 snprintf(outbuf, 81, "%*s/%*s%13d lines\n", |
139 filelist->displayname_len+scanner.spaces, filelist->displayname, |
213 filelist->displayname_len+scanner.spaces, filelist->displayname, |
140 60-filelist->displayname_len-scanner.spaces-1, "", |
214 60-filelist->displayname_len-scanner.spaces-1, "", |
141 recresult.directory); |
215 recresult.lines); |
142 add_string(output, outbuf); |
216 add_string(output, outbuf); |
143 for (int i = 0 ; i < recoutput->count ; i++) { |
217 for (int i = 0 ; i < recoutput->count ; i++) { |
144 add_string(output, recoutput->items[i]); |
218 add_string(output, recoutput->items[i]); |
145 } |
219 } |
146 } |
220 } |
209 filelist->displayname, |
283 filelist->displayname, |
210 60-filelist->displayname_len-scanner.spaces, "", "binary"); |
284 60-filelist->displayname_len-scanner.spaces, "", "binary"); |
211 add_string(output, outbuf); |
285 add_string(output, outbuf); |
212 } |
286 } |
213 } else { |
287 } else { |
214 result->directory += lines; |
288 addLinesPerExtension(result->ext, filelist->ext, lines); |
|
289 result->lines += lines; |
215 outbuf = (char*) malloc(81); |
290 outbuf = (char*) malloc(81); |
216 snprintf(outbuf, 81, "%*s%*s%13d lines\n", |
291 snprintf(outbuf, 81, "%*s%*s%13d lines\n", |
217 filelist->displayname_len+scanner.spaces, filelist->displayname, |
292 filelist->displayname_len+scanner.spaces, filelist->displayname, |
218 60-filelist->displayname_len-scanner.spaces, "", lines); |
293 60-filelist->displayname_len-scanner.spaces, "", lines); |
219 add_string(output, outbuf); |
294 add_string(output, outbuf); |