Skip to content

Commit 57057e8

Browse files
authored
Implement support for unicode file names in Windows. (#1491)
1 parent eaa4e2e commit 57057e8

File tree

15 files changed

+1228
-904
lines changed

15 files changed

+1228
-904
lines changed

Makefile.am

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ bin_PROGRAMS = yara yarac
3737
yara_SOURCES = \
3838
cli/args.c \
3939
cli/args.h \
40+
cli/common.c \
4041
cli/common.h \
4142
cli/threading.c \
4243
cli/threading.h \
@@ -48,6 +49,7 @@ yara_DEPENDENCIES = libyara/.libs/libyara.la
4849
yarac_SOURCES = \
4950
cli/args.c \
5051
cli/args.h \
52+
cli/common.c \
5153
cli/common.h \
5254
cli/yarac.c
5355

cli/args.c

+52-36
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2014. The YARA Authors. All Rights Reserved.
2+
Copyright (c) 2014-2021. The YARA Authors. All Rights Reserved.
33
44
Redistribution and use in source and binary forms, with or without modification,
55
are permitted provided that the following conditions are met:
@@ -34,14 +34,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3434
#include <string.h>
3535
#include <yara.h>
3636

37-
#define args_is_long_arg(arg) (arg[0] == '-' && arg[1] == '-' && arg[2] != '\0')
37+
#include "args.h"
38+
#include "common.h"
39+
#include "unicode.h"
3840

41+
#define args_is_long_arg(arg) (arg[0] == '-' && arg[1] == '-' && arg[2] != '\0')
3942

4043
#define args_is_short_arg(arg) \
4144
(arg[0] == '-' && arg[1] != '-' && arg[1] != '\0')
4245

43-
44-
args_option_t* args_get_short_option(args_option_t* options, const char opt)
46+
args_option_t* args_get_short_option(args_option_t* options, const char_t opt)
4547
{
4648
while (options->type != ARGS_OPT_END)
4749
{
@@ -54,19 +56,18 @@ args_option_t* args_get_short_option(args_option_t* options, const char opt)
5456
return NULL;
5557
}
5658

57-
58-
args_option_t* args_get_long_option(args_option_t* options, const char* arg)
59+
args_option_t* args_get_long_option(args_option_t* options, const char_t* arg)
5960
{
6061
arg += 2; // skip starting --
6162

6263
while (options->type != ARGS_OPT_END)
6364
{
6465
if (options->long_name != NULL)
6566
{
66-
size_t l = strlen(options->long_name);
67+
size_t l = _tcslen(options->long_name);
6768

6869
if ((arg[l] == '\0' || arg[l] == '=') &&
69-
strstr(arg, options->long_name) == arg)
70+
_tcsstr(arg, options->long_name) == arg)
7071
{
7172
return options;
7273
}
@@ -78,13 +79,12 @@ args_option_t* args_get_long_option(args_option_t* options, const char* arg)
7879
return NULL;
7980
}
8081

81-
8282
args_error_type_t args_parse_option(
8383
args_option_t* opt,
84-
const char* opt_arg,
84+
const char_t* opt_arg,
8585
int* opt_arg_was_used)
8686
{
87-
char* endptr = NULL;
87+
char_t* endptr = NULL;
8888

8989
if (opt_arg_was_used != NULL)
9090
*opt_arg_was_used = 0;
@@ -99,11 +99,10 @@ args_error_type_t args_parse_option(
9999
break;
100100

101101
case ARGS_OPT_INTEGER:
102-
103102
if (opt_arg == NULL)
104103
return ARGS_ERROR_REQUIRED_INTEGER_ARG;
105104

106-
*(int*) opt->value = strtol(opt_arg, &endptr, 0);
105+
*(long*) opt->value = _tcstol(opt_arg, &endptr, 0);
107106

108107
if (*endptr != '\0')
109108
return ARGS_ERROR_REQUIRED_INTEGER_ARG;
@@ -114,14 +113,20 @@ args_error_type_t args_parse_option(
114113
break;
115114

116115
case ARGS_OPT_STRING:
117-
118116
if (opt_arg == NULL)
119117
return ARGS_ERROR_REQUIRED_STRING_ARG;
120118

119+
#ifdef _UNICODE
120+
if (opt->max_count > 1)
121+
((const char**) opt->value)[opt->count] = unicode_to_ansi(opt_arg);
122+
else
123+
*(const char**) opt->value = unicode_to_ansi(opt_arg);
124+
#else
121125
if (opt->max_count > 1)
122126
((const char**) opt->value)[opt->count] = opt_arg;
123127
else
124128
*(const char**) opt->value = opt_arg;
129+
#endif
125130

126131
if (opt_arg_was_used != NULL)
127132
*opt_arg_was_used = 1;
@@ -137,33 +142,31 @@ args_error_type_t args_parse_option(
137142
return ARGS_ERROR_OK;
138143
}
139144

140-
141-
void args_print_error(args_error_type_t error, const char* option)
145+
void args_print_error(args_error_type_t error, const char_t* option)
142146
{
143147
switch (error)
144148
{
145149
case ARGS_ERROR_UNKNOWN_OPT:
146-
fprintf(stderr, "unknown option `%s`\n", option);
150+
_ftprintf(stderr, _T("unknown option `%s`\n"), option);
147151
break;
148152
case ARGS_ERROR_TOO_MANY:
149-
fprintf(stderr, "too many `%s` options\n", option);
153+
_ftprintf(stderr, _T("too many `%s` options\n"), option);
150154
break;
151155
case ARGS_ERROR_REQUIRED_INTEGER_ARG:
152-
fprintf(stderr, "option `%s` requires an integer argument\n", option);
156+
_ftprintf(stderr, _T("option `%s` requires an integer argument\n"), option);
153157
break;
154158
case ARGS_ERROR_REQUIRED_STRING_ARG:
155-
fprintf(stderr, "option `%s` requires a string argument\n", option);
159+
_ftprintf(stderr, _T("option `%s` requires a string argument\n"), option);
156160
break;
157161
case ARGS_ERROR_UNEXPECTED_ARG:
158-
fprintf(stderr, "option `%s` doesn't expect an argument\n", option);
162+
_ftprintf(stderr, _T("option `%s` doesn't expect an argument\n"), option);
159163
break;
160164
default:
161165
return;
162166
}
163167
}
164168

165-
166-
int args_parse(args_option_t* options, int argc, const char** argv)
169+
int args_parse(args_option_t* options, int argc, const char_t** argv)
167170
{
168171
args_error_type_t error = ARGS_ERROR_OK;
169172

@@ -172,15 +175,15 @@ int args_parse(args_option_t* options, int argc, const char** argv)
172175

173176
while (i < argc)
174177
{
175-
const char* arg = argv[i];
178+
const char_t* arg = argv[i];
176179

177180
if (args_is_long_arg(arg))
178181
{
179182
args_option_t* opt = args_get_long_option(options, arg);
180183

181184
if (opt != NULL)
182185
{
183-
const char* equal = strchr(arg, '=');
186+
const char_t* equal = _tcschr(arg, '=');
184187

185188
if (equal)
186189
error = args_parse_option(opt, equal + 1, NULL);
@@ -242,38 +245,51 @@ int args_parse(args_option_t* options, int argc, const char** argv)
242245
i++;
243246
}
244247

248+
// Initialize to NULL the value pointers for all options.
249+
for (; options->type != ARGS_OPT_END; options++) options->value = NULL;
250+
245251
return o;
246252
}
247253

248-
249254
void args_print_usage(args_option_t* options, int help_alignment)
250255
{
251-
char buffer[128];
256+
char_t buffer[128];
252257

253258
for (; options->type != ARGS_OPT_END; options++)
254259
{
255-
int len = sprintf(buffer, " ");
260+
int len = _stprintf(buffer, _T(" "));
256261

257262
if (options->short_name != '\0')
258-
len += sprintf(buffer + len, "-%c", options->short_name);
263+
len += _stprintf(buffer + len, _T("-%c"), options->short_name);
259264
else
260-
len += sprintf(buffer + len, " ");
265+
len += _stprintf(buffer + len, _T(" "));
261266

262267
if (options->short_name != '\0' && options->long_name != NULL)
263-
len += sprintf(buffer + len, ", ");
268+
len += _stprintf(buffer + len, _T( ", "));
264269

265270
if (options->long_name != NULL)
266-
len += sprintf(buffer + len, "--%s", options->long_name);
271+
len += _stprintf(buffer + len, _T("--%s"), options->long_name);
267272

268273
if (options->type == ARGS_OPT_STRING || options->type == ARGS_OPT_INTEGER)
269274
{
270-
len += sprintf(
275+
len += _stprintf(
271276
buffer + len,
272-
"%s%s",
273-
(options->long_name != NULL) ? "=" : " ",
277+
_T("%s%s"),
278+
(options->long_name != NULL) ? _T("=") : _T(" "),
274279
options->type_help);
275280
}
276281

277-
printf("%-*s%s\n", help_alignment, buffer, options->help);
282+
_tprintf(_T("%-*s%s\n"), help_alignment, buffer, options->help);
283+
}
284+
}
285+
286+
void args_free(args_option_t* options)
287+
{
288+
for (; options->type != ARGS_OPT_END; options++)
289+
{
290+
if (options->type == ARGS_OPT_STRING && options->value != NULL)
291+
{
292+
free(options->value);
293+
}
278294
}
279295
}

cli/args.h

+40-35
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
Copyright (c) 2014. The YARA Authors. All Rights Reserved.
2+
Copyright (c) 2014-2021. The YARA Authors. All Rights Reserved.
33
44
Redistribution and use in source and binary forms, with or without modification,
55
are permitted provided that the following conditions are met:
@@ -31,49 +31,49 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3131
#define ARGPARSE_H
3232

3333
#include <stdio.h>
34+
#include "unicode.h"
3435

3536

3637
#ifdef __cplusplus
3738
extern "C"
3839
{
3940
#endif
4041

41-
42-
typedef enum _args_error_type
43-
{
42+
typedef enum _args_error_type
43+
{
4444
ARGS_ERROR_OK,
4545
ARGS_ERROR_UNKNOWN_OPT,
4646
ARGS_ERROR_TOO_MANY,
4747
ARGS_ERROR_REQUIRED_INTEGER_ARG,
4848
ARGS_ERROR_REQUIRED_STRING_ARG,
4949
ARGS_ERROR_UNEXPECTED_ARG,
50-
} args_error_type_t;
51-
52-
53-
typedef enum _args_option_type
54-
{
55-
// special
56-
ARGS_OPT_END,
57-
ARGS_OPT_GROUP,
58-
// options with no arguments
59-
ARGS_OPT_BOOLEAN,
60-
// options with arguments (optional or required)
61-
ARGS_OPT_INTEGER,
62-
ARGS_OPT_STRING,
63-
} args_option_type_t;
64-
65-
66-
typedef struct _args_option
67-
{
68-
args_option_type_t type;
69-
const char short_name;
70-
const char *long_name;
71-
void *value;
72-
int max_count;
73-
const char *help;
74-
const char *type_help;
75-
int count;
76-
} args_option_t;
50+
} args_error_type_t;
51+
52+
53+
typedef enum _args_option_type
54+
{
55+
// special
56+
ARGS_OPT_END,
57+
ARGS_OPT_GROUP,
58+
// options with no arguments
59+
ARGS_OPT_BOOLEAN,
60+
// options with arguments (optional or required)
61+
ARGS_OPT_INTEGER,
62+
ARGS_OPT_STRING,
63+
} args_option_type_t;
64+
65+
66+
typedef struct _args_option
67+
{
68+
args_option_type_t type;
69+
const char_t short_name;
70+
const char_t *long_name;
71+
void *value;
72+
int max_count;
73+
const char_t *help;
74+
const char_t *type_help;
75+
int count;
76+
} args_option_t;
7777

7878

7979
#define OPT_BOOLEAN(short_name, long_name, value, ...) \
@@ -99,12 +99,17 @@ extern "C"
9999
ARGS_OPT_END, 0 \
100100
}
101101

102+
int args_parse(
103+
args_option_t *options,
104+
int argc,
105+
const char_t **argv);
102106

103-
int args_parse(args_option_t *options, int argc, const char **argv);
104-
105-
106-
void args_print_usage(args_option_t *options, int alignment);
107+
void args_print_usage(
108+
args_option_t *options,
109+
int alignment);
107110

111+
void args_free(
112+
args_option_t *options);
108113

109114
#ifdef __cplusplus
110115
}

0 commit comments

Comments
 (0)