Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/programs/find/find.c
4387 views
1
/*
2
* Copyright 2018 Fabian Maurer
3
*
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
8
*
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
13
*
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17
*/
18
19
#include <windows.h>
20
#include <stdlib.h>
21
#include <shlwapi.h>
22
23
#include "wine/debug.h"
24
#include "resources.h"
25
26
WINE_DEFAULT_DEBUG_CHANNEL(find);
27
28
static int flag_case_sensitive = 1;
29
static int flag_line_count;
30
31
static unsigned int line_count;
32
33
static BOOL read_char_from_handle(HANDLE handle, char *char_out)
34
{
35
static char buffer[4096];
36
static DWORD buffer_max = 0;
37
static DWORD buffer_pos = 0;
38
39
/* Read next content into buffer */
40
if (buffer_pos >= buffer_max)
41
{
42
BOOL success = ReadFile(handle, buffer, 4096, &buffer_max, NULL);
43
if (!success || !buffer_max)
44
return FALSE;
45
buffer_pos = 0;
46
}
47
48
*char_out = buffer[buffer_pos++];
49
return TRUE;
50
}
51
52
/* Read a line from a handle, returns NULL if the end is reached */
53
static WCHAR* read_line_from_handle(HANDLE handle)
54
{
55
int line_max = 4096;
56
int length = 0;
57
WCHAR *line_converted;
58
int line_converted_length;
59
BOOL success;
60
char *line = malloc(line_max);
61
62
for (;;)
63
{
64
char c;
65
success = read_char_from_handle(handle, &c);
66
67
/* Check for EOF */
68
if (!success)
69
{
70
if (length == 0)
71
return NULL;
72
else
73
break;
74
}
75
76
if (c == '\n')
77
break;
78
79
/* Make sure buffer is large enough */
80
if (length + 1 >= line_max)
81
{
82
line_max *= 2;
83
line = realloc(line, line_max);
84
}
85
86
line[length++] = c;
87
}
88
89
line[length] = 0;
90
if (length - 1 >= 0 && line[length - 1] == '\r') /* Strip \r of windows line endings */
91
line[length - 1] = 0;
92
93
line_converted_length = MultiByteToWideChar(CP_ACP, 0, line, -1, 0, 0);
94
line_converted = malloc(line_converted_length * sizeof(WCHAR));
95
MultiByteToWideChar(CP_ACP, 0, line, -1, line_converted, line_converted_length);
96
97
free(line);
98
99
return line_converted;
100
}
101
102
static void write_to_stdout(const WCHAR *str)
103
{
104
char *str_converted;
105
UINT str_converted_length;
106
DWORD bytes_written;
107
UINT str_length = lstrlenW(str);
108
int codepage = CP_ACP;
109
110
str_converted_length = WideCharToMultiByte(codepage, 0, str, str_length, NULL, 0, NULL, NULL);
111
str_converted = malloc(str_converted_length);
112
WideCharToMultiByte(codepage, 0, str, str_length, str_converted, str_converted_length, NULL, NULL);
113
114
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), str_converted, str_converted_length, &bytes_written, NULL);
115
if (bytes_written < str_converted_length)
116
ERR("Failed to write output\n");
117
118
free(str_converted);
119
}
120
121
static BOOL run_find_for_line(const WCHAR *line, const WCHAR *tofind)
122
{
123
void *found;
124
125
if (lstrlenW(line) == 0 || lstrlenW(tofind) == 0)
126
return FALSE;
127
128
found = flag_case_sensitive ? wcsstr(line, tofind) : StrStrIW(line, tofind);
129
130
if (found)
131
{
132
if (flag_line_count) line_count++;
133
else
134
{
135
write_to_stdout(line);
136
write_to_stdout(L"\r\n");
137
}
138
return TRUE;
139
}
140
141
return FALSE;
142
}
143
144
static void output_resource_message(int id)
145
{
146
WCHAR buffer[64];
147
LoadStringW(GetModuleHandleW(NULL), id, buffer, ARRAY_SIZE(buffer));
148
write_to_stdout(buffer);
149
}
150
151
int __cdecl wmain(int argc, WCHAR *argv[])
152
{
153
WCHAR *line;
154
WCHAR *tofind = NULL;
155
int i;
156
int exitcode;
157
int file_paths_len = 0;
158
int file_paths_max = 0;
159
WCHAR** file_paths = NULL;
160
161
TRACE("running find:");
162
for (i = 0; i < argc; i++)
163
{
164
TRACE(" %s", wine_dbgstr_w(argv[i]));
165
}
166
TRACE("\n");
167
168
for (i = 1; i < argc; i++)
169
{
170
if (argv[i][0] == '/')
171
{
172
switch (argv[i][1])
173
{
174
case 'i':
175
case 'I':
176
flag_case_sensitive = 0;
177
break;
178
179
case 'c':
180
case 'C':
181
flag_line_count = 1;
182
break;
183
184
default:
185
output_resource_message(IDS_INVALID_SWITCH);
186
return 2;
187
}
188
}
189
else if (tofind == NULL)
190
{
191
tofind = argv[i];
192
}
193
else
194
{
195
if (file_paths_len >= file_paths_max)
196
{
197
file_paths_max = file_paths_max ? file_paths_max * 2 : 2;
198
file_paths = realloc(file_paths, sizeof(WCHAR*) * file_paths_max);
199
}
200
file_paths[file_paths_len++] = argv[i];
201
}
202
}
203
204
if (tofind == NULL)
205
{
206
output_resource_message(IDS_INVALID_PARAMETER);
207
return 2;
208
}
209
210
exitcode = 1;
211
212
if (file_paths_len > 0)
213
{
214
for (i = 0; i < file_paths_len; i++)
215
{
216
HANDLE input;
217
WCHAR file_path_upper[MAX_PATH], buf[11];
218
219
wcscpy(file_path_upper, file_paths[i]);
220
wcsupr(file_path_upper);
221
222
input = CreateFileW(file_paths[i], GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
223
224
if (input == INVALID_HANDLE_VALUE)
225
{
226
WCHAR buffer_message[64];
227
WCHAR message[300];
228
229
LoadStringW(GetModuleHandleW(NULL), IDS_FILE_NOT_FOUND, buffer_message, ARRAY_SIZE(buffer_message));
230
231
wsprintfW(message, buffer_message, file_path_upper);
232
write_to_stdout(message);
233
continue;
234
}
235
236
write_to_stdout(L"\r\n---------- ");
237
write_to_stdout(file_path_upper);
238
if (flag_line_count) write_to_stdout(L": ");
239
else write_to_stdout(L"\r\n");
240
241
while ((line = read_line_from_handle(input)) != NULL)
242
{
243
if (run_find_for_line(line, tofind))
244
exitcode = 0;
245
246
free(line);
247
}
248
249
if (flag_line_count)
250
{
251
wsprintfW(buf, L"%u\r\n\r\n", line_count);
252
write_to_stdout(buf);
253
}
254
CloseHandle(input);
255
}
256
}
257
else
258
{
259
HANDLE input = GetStdHandle(STD_INPUT_HANDLE);
260
while ((line = read_line_from_handle(input)) != NULL)
261
{
262
if (run_find_for_line(line, tofind))
263
exitcode = 0;
264
265
free(line);
266
}
267
}
268
269
free(file_paths);
270
return exitcode;
271
}
272
273