/* flac - Command-line FLAC encoder/decoder
- * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Josh Coalson
+ * Copyright (C) 2000-2009 Josh Coalson
+ * Copyright (C) 2011-2013 Xiph.Org Foundation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
#include "share/alloc.h"
#include "share/grabbag.h"
#include "share/compat.h"
+#include "share/safe_str.h"
#include "analyze.h"
#include "decode.h"
#include "encode.h"
int format_channels;
int format_bps;
int format_sample_rate;
- off_t format_input_size;
+ FLAC__off_t format_input_size;
char requested_seek_points[5000]; /* bad MAGIC NUMBER but buffer overflow is checked */
int num_requested_seek_points; /* -1 => no -S options were given, 0 => -S- was given */
const char *cuesheet_filename;
_response(&argc, &argv);
_wildcard(&argc, &argv);
#endif
+#ifdef _WIN32
+ if (get_utf8_argv(&argc, &argv) != 0) {
+ fprintf(stderr, "ERROR: failed to convert command line parameters to UTF-8\n");
+ return 1;
+ }
+#endif
srand((unsigned)time(0));
setlocale(LC_ALL, "");
}
flac__utils_printf(stderr, 2, "\n");
- flac__utils_printf(stderr, 2, "flac %s, Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Josh Coalson\n", FLAC__VERSION_STRING);
+ flac__utils_printf(stderr, 2, "flac %s, Copyright (C) 2000-2009, 2011-2013 Josh Coalson & Xiph.Org Foundation\n", FLAC__VERSION_STRING);
flac__utils_printf(stderr, 2, "flac comes with ABSOLUTELY NO WARRANTY. This is free software, and you are\n");
flac__utils_printf(stderr, 2, "welcome to redistribute it under certain conditions. Type `flac' for details.\n\n");
option_values.format_channels = -1;
option_values.format_bps = -1;
option_values.format_sample_rate = -1;
- option_values.format_input_size = (off_t)(-1);
+ option_values.format_input_size = (FLAC__off_t)(-1);
option_values.requested_seek_points[0] = '\0';
option_values.num_requested_seek_points = -1;
option_values.cuesheet_filename = 0;
int parse_option(int short_option, const char *long_option, const char *option_argument)
{
const char *violation;
- char *p;
- int i;
if(short_option == 0) {
FLAC__ASSERT(0 != long_option);
FLAC__ASSERT(0 != option_argument);
{
char *end;
- FLAC__int64 i;
- i = strtoll(option_argument, &end, 10);
+ FLAC__int64 ix;
+ ix = strtoll(option_argument, &end, 10);
if(0 == strlen(option_argument) || *end)
return usage_error("ERROR: --%s must be a number\n", long_option);
- option_values.format_input_size = (off_t)i;
- if(option_values.format_input_size != i) /* check if off_t is smaller than long long */
+ option_values.format_input_size = (FLAC__off_t)ix;
+ if(option_values.format_input_size != ix) /* check if FLAC__off_t is smaller than long long */
return usage_error("ERROR: --%s too large; this build of flac does not support filesizes over 2GB\n", long_option);
if(option_values.format_input_size <= 0)
return usage_error("ERROR: --%s must be > 0\n", long_option);
return usage_error("ERROR: too many seekpoints requested\n");
}
else {
- strcat(option_values.requested_seek_points, option_argument);
- strcat(option_values.requested_seek_points, ";");
+ size_t len = strlen(option_values.requested_seek_points);
+ flac_snprintf(option_values.requested_seek_points+len, sizeof(option_values.requested_seek_points) - len, "%s;", option_argument);
}
}
break;
return usage_error("ERROR: argument to -%c must be >= 0; for no padding use -%c-\n", short_option, short_option);
break;
case 'b':
- FLAC__ASSERT(0 != option_argument);
- i = atoi(option_argument);
- if((i < (int)FLAC__MIN_BLOCK_SIZE || i > (int)FLAC__MAX_BLOCK_SIZE))
- return usage_error("ERROR: invalid blocksize (-%c) '%d', must be >= %u and <= %u\n", short_option, i, FLAC__MIN_BLOCK_SIZE, FLAC__MAX_BLOCK_SIZE);
- add_compression_setting_unsigned(CST_BLOCKSIZE, (unsigned)i);
+ {
+ unsigned i ;
+ FLAC__ASSERT(0 != option_argument);
+ i = atoi(option_argument);
+ if((i < (int)FLAC__MIN_BLOCK_SIZE || i > (int)FLAC__MAX_BLOCK_SIZE))
+ return usage_error("ERROR: invalid blocksize (-%c) '%d', must be >= %u and <= %u\n", short_option, i, FLAC__MIN_BLOCK_SIZE, FLAC__MAX_BLOCK_SIZE);
+ add_compression_setting_unsigned(CST_BLOCKSIZE, (unsigned)i);
+ }
break;
case 'e':
add_compression_setting_bool(CST_DO_EXHAUSTIVE_MODEL_SEARCH, true);
add_compression_setting_bool(CST_DO_ESCAPE_CODING, true);
break;
case 'l':
- FLAC__ASSERT(0 != option_argument);
- i = atoi(option_argument);
- if((i < 0 || i > (int)FLAC__MAX_LPC_ORDER))
- return usage_error("ERROR: invalid LPC order (-%c) '%d', must be >= %u and <= %u\n", short_option, i, 0, FLAC__MAX_LPC_ORDER);
- add_compression_setting_unsigned(CST_MAX_LPC_ORDER, (unsigned)i);
+ {
+ unsigned i ;
+ FLAC__ASSERT(0 != option_argument);
+ i = atoi(option_argument);
+ if(i > FLAC__MAX_LPC_ORDER)
+ return usage_error("ERROR: invalid LPC order (-%c) '%d', must be >= %u and <= %u\n", short_option, i, 0, FLAC__MAX_LPC_ORDER);
+ add_compression_setting_unsigned(CST_MAX_LPC_ORDER, i);
+ }
break;
case 'A':
FLAC__ASSERT(0 != option_argument);
add_compression_setting_bool(CST_DO_QLP_COEFF_PREC_SEARCH, true);
break;
case 'q':
- FLAC__ASSERT(0 != option_argument);
- i = atoi(option_argument);
- if(i < 0 || (i > 0 && (i < (int)FLAC__MIN_QLP_COEFF_PRECISION || i > (int)FLAC__MAX_QLP_COEFF_PRECISION)))
- return usage_error("ERROR: invalid value '%d' for qlp coeff precision (-%c), must be 0 or between %u and %u, inclusive\n", i, short_option, FLAC__MIN_QLP_COEFF_PRECISION, FLAC__MAX_QLP_COEFF_PRECISION);
- add_compression_setting_unsigned(CST_QLP_COEFF_PRECISION, (unsigned)i);
- break;
- case 'r':
- FLAC__ASSERT(0 != option_argument);
- p = strchr(option_argument, ',');
- if(0 == p) {
- add_compression_setting_unsigned(CST_MIN_RESIDUAL_PARTITION_ORDER, 0);
+ {
+ unsigned i ;
+ FLAC__ASSERT(0 != option_argument);
i = atoi(option_argument);
- if(i < 0)
- return usage_error("ERROR: invalid value '%d' for residual partition order (-%c), must be between 0 and %u, inclusive\n", i, short_option, FLAC__MAX_RICE_PARTITION_ORDER);
- add_compression_setting_unsigned(CST_MAX_RESIDUAL_PARTITION_ORDER, (unsigned)i);
+ if((i > 0 && (i < FLAC__MIN_QLP_COEFF_PRECISION || i > FLAC__MAX_QLP_COEFF_PRECISION)))
+ return usage_error("ERROR: invalid value '%d' for qlp coeff precision (-%c), must be 0 or between %u and %u, inclusive\n", i, short_option, FLAC__MIN_QLP_COEFF_PRECISION, FLAC__MAX_QLP_COEFF_PRECISION);
+ add_compression_setting_unsigned(CST_QLP_COEFF_PRECISION, i);
}
- else {
- i = atoi(option_argument);
- if(i < 0)
- return usage_error("ERROR: invalid value '%d' for min residual partition order (-%c), must be between 0 and %u, inclusive\n", i, short_option, FLAC__MAX_RICE_PARTITION_ORDER);
- add_compression_setting_unsigned(CST_MIN_RESIDUAL_PARTITION_ORDER, (unsigned)i);
- i = atoi(++p);
- if(i < 0)
- return usage_error("ERROR: invalid value '%d' for max residual partition order (-%c), must be between 0 and %u, inclusive\n", i, short_option, FLAC__MAX_RICE_PARTITION_ORDER);
- add_compression_setting_unsigned(CST_MAX_RESIDUAL_PARTITION_ORDER, (unsigned)i);
+ break;
+ case 'r':
+ {
+ unsigned i;
+ char * p;
+ FLAC__ASSERT(0 != option_argument);
+ p = strchr(option_argument, ',');
+ if(0 == p) {
+ add_compression_setting_unsigned(CST_MIN_RESIDUAL_PARTITION_ORDER, 0);
+ i = atoi(option_argument);
+ if(i > FLAC__MAX_RICE_PARTITION_ORDER)
+ return usage_error("ERROR: invalid value '%d' for residual partition order (-%c), must be between 0 and %u, inclusive\n", i, short_option, FLAC__MAX_RICE_PARTITION_ORDER);
+ add_compression_setting_unsigned(CST_MAX_RESIDUAL_PARTITION_ORDER, i);
+ }
+ else {
+ i = atoi(option_argument);
+ if(i > FLAC__MAX_RICE_PARTITION_ORDER)
+ return usage_error("ERROR: invalid value '%d' for min residual partition order (-%c), must be between 0 and %u, inclusive\n", i, short_option, FLAC__MAX_RICE_PARTITION_ORDER);
+ add_compression_setting_unsigned(CST_MIN_RESIDUAL_PARTITION_ORDER, i);
+ i = atoi(++p);
+ if(i > FLAC__MAX_RICE_PARTITION_ORDER)
+ return usage_error("ERROR: invalid value '%d' for max residual partition order (-%c), must be between 0 and %u, inclusive\n", i, short_option, FLAC__MAX_RICE_PARTITION_ORDER);
+ add_compression_setting_unsigned(CST_MAX_RESIDUAL_PARTITION_ORDER, i);
+ }
}
break;
case 'R':
- i = atoi(option_argument);
- if(i < 0)
- return usage_error("ERROR: invalid value '%d' for Rice parameter search distance (-%c), must be >= 0\n", i, short_option);
- add_compression_setting_unsigned(CST_RICE_PARAMETER_SEARCH_DIST, (unsigned)i);
+ {
+ unsigned i;
+ i = atoi(option_argument);
+ add_compression_setting_unsigned(CST_RICE_PARAMETER_SEARCH_DIST, i);
+ }
break;
default:
FLAC__ASSERT(0);
{
printf("===============================================================================\n");
printf("flac - Command-line FLAC encoder/decoder version %s\n", FLAC__VERSION_STRING);
- printf("Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Josh Coalson\n");
+ printf("Copyright (C) 2000-2009 Josh Coalson\n");
+ printf("Copyright (C) 2011-2013 Xiph.Org Foundation\n");
printf("\n");
printf("This program is free software; you can redistribute it and/or\n");
printf("modify it under the terms of the GNU General Public License\n");
printf(" --force-wave64-format Force decoding to Wave64 format\n");
printf("negative options:\n");
printf(" --no-adaptive-mid-side\n");
+ printf(" --no-cued-seekpoints\n");
printf(" --no-decode-through-errors\n");
printf(" --no-delete-input-file\n");
printf(" --no-preserve-modtime\n");
printf(" --input-size=# Size of the raw input in bytes. If you are\n");
printf(" encoding raw samples from stdin, you must set\n");
printf(" this option in order to be able to use --skip,\n");
- printf(" --until, --cue-sheet, or other options that need\n");
+ printf(" --until, --cuesheet, or other options that need\n");
printf(" to know the size of the input beforehand. If\n");
printf(" the size given is greater than what is found in\n");
printf(" the input stream, the encoder will complain\n");
printf(" auto-detected.\n");
printf("negative options:\n");
printf(" --no-adaptive-mid-side\n");
+ printf(" --no-cued-seekpoints\n");
printf(" --no-decode-through-errors\n");
printf(" --no-delete-input-file\n");
printf(" --no-preserve-modtime\n");
unsigned lookahead_length = 0;
FileFormat input_format = FORMAT_RAW;
int retval;
- off_t infilesize;
+ FLAC__off_t infilesize;
encode_options_t encode_options;
const char *outfilename = get_encoded_outfilename(infilename); /* the final name of the encoded file */
/* internal_outfilename is the file we will actually write to; it will be a temporary name if infilename==outfilename */
}
if(0 == strcmp(infilename, "-")) {
- infilesize = (off_t)(-1);
+ infilesize = (FLAC__off_t)(-1);
encode_infile = grabbag__file_get_binary_stdin();
}
else {
infilesize = grabbag__file_get_filesize(infilename);
- if(0 == (encode_infile = fopen(infilename, "rb"))) {
+ if(0 == (encode_infile = flac_fopen(infilename, "rb"))) {
flac__utils_printf(stderr, 1, "ERROR: can't open input file %s: %s\n", infilename, strerror(errno));
return 1;
}
input_format = FORMAT_WAVE;
else if(!memcmp(lookahead, "RF64", 4) && !memcmp(lookahead+8, "WAVE", 4))
input_format = FORMAT_RF64;
- else if(!memcmp(lookahead, "riff\x2E\x91\xCF\x11\xD6\xA5\x28\xDB", 12)) /* just check 1st 12 bytes of GUID */
+ else if(!memcmp(lookahead, "riff\x2E\x91\xCF\x11\xA5\xD6\x28\xDB", 12)) /* just check 1st 12 bytes of GUID */
input_format = FORMAT_WAVE64;
else if(!memcmp(lookahead, "FORM", 4) && !memcmp(lookahead+8, "AIFF", 4))
input_format = FORMAT_AIFF;
* Error if output file already exists (and -f not used).
* Use grabbag__file_get_filesize() as a cheap way to check.
*/
- if(!option_values.test_only && !option_values.force_file_overwrite && strcmp(outfilename, "-") && grabbag__file_get_filesize(outfilename) != (off_t)(-1)) {
+ if(!option_values.test_only && !option_values.force_file_overwrite && strcmp(outfilename, "-") && grabbag__file_get_filesize(outfilename) != (FLAC__off_t)(-1)) {
if(input_format == FORMAT_FLAC) {
/* need more detailed error message when re-flac'ing to avoid confusing the user */
flac__utils_printf(stderr, 1,
/* if infilename and outfilename point to the same file, we need to write to a temporary file */
if(encode_infile != stdin && grabbag__file_are_same(infilename, outfilename)) {
static const char *tmp_suffix = ".tmp,fl-ac+en'c";
+ size_t dest_len = strlen(outfilename) + strlen(tmp_suffix) + 1;
/*@@@@ still a remote possibility that a file with this filename exists */
- if(0 == (internal_outfilename = safe_malloc_add_3op_(strlen(outfilename), /*+*/strlen(tmp_suffix), /*+*/1))) {
+ if(0 == (internal_outfilename = safe_malloc_(dest_len))) {
flac__utils_printf(stderr, 1, "ERROR allocating memory for tempfile name\n");
conditional_fclose(encode_infile);
return 1;
}
- strcpy(internal_outfilename, outfilename);
- strcat(internal_outfilename, tmp_suffix);
+ safe_strncpy(internal_outfilename, outfilename, dest_len);
+ safe_strncat(internal_outfilename, tmp_suffix, dest_len);
}
if(input_format == FORMAT_RAW) {
/* rename temporary file if necessary */
if(retval == 0 && internal_outfilename != 0) {
- if(rename(internal_outfilename, outfilename) < 0) {
+ if(flac_rename(internal_outfilename, outfilename) < 0) {
#if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
- /* on some flavors of windows, rename() will fail if the destination already exists, so we unlink and try again */
- if(unlink(outfilename) < 0) {
+ /* on some flavors of windows, flac_rename() will fail if the destination already exists, so we unlink and try again */
+ if(flac_unlink(outfilename) < 0) {
flac__utils_printf(stderr, 1, "ERROR: moving new FLAC file %s back on top of original FLAC file %s, keeping both\n", internal_outfilename, outfilename);
retval = 1;
}
- else if(rename(internal_outfilename, outfilename) < 0) {
+ else if(flac_rename(internal_outfilename, outfilename) < 0) {
flac__utils_printf(stderr, 1, "ERROR: moving new FLAC file %s back on top of original FLAC file %s, you must do it\n", internal_outfilename, outfilename);
retval = 1;
}
/* handle --delete-input-file, but don't want to delete if piping from stdin, or if input filename and output filename are the same */
if(retval == 0 && option_values.delete_input && strcmp(infilename, "-") && internal_outfilename == 0)
- unlink(infilename);
+ flac_unlink(infilename);
if(internal_outfilename != 0)
free(internal_outfilename);
* Error if output file already exists (and -f not used).
* Use grabbag__file_get_filesize() as a cheap way to check.
*/
- if(!option_values.test_only && !option_values.force_file_overwrite && strcmp(outfilename, "-") && grabbag__file_get_filesize(outfilename) != (off_t)(-1)) {
+ if(!option_values.test_only && !option_values.force_file_overwrite && strcmp(outfilename, "-") && grabbag__file_get_filesize(outfilename) != (FLAC__off_t)(-1)) {
flac__utils_printf(stderr, 1, "ERROR: output file %s already exists, use -f to override\n", outfilename);
return 1;
}
if(option_values.preserve_modtime && strcmp(outfilename, "-"))
grabbag__file_copy_metadata(infilename, outfilename);
if(option_values.delete_input && !option_values.test_only && !option_values.analyze)
- unlink(infilename);
+ flac_unlink(infilename);
}
return retval;
static char buffer[4096]; /* @@@ bad MAGIC NUMBER */
if(0 == strcmp(infilename, "-") || option_values.force_to_stdout) {
- strcpy(buffer, "-");
+ safe_strncpy(buffer, "-", sizeof(buffer));
}
else {
char *p;