|
92 | 92 |
|
93 | 93 | using namespace std; |
94 | 94 |
|
| 95 | +// This I shamelessly lifted from https://web.archive.org/web/20090907131154/http://www.cs.toronto.edu:80/~ramona/cosmin/TA/prog/sysconf/ |
| 96 | +// (credit to this StackOverflow answer for pointing me to it https://stackoverflow.com/a/1613677) |
| 97 | +// It allows us to portably (at least for Windows/Linux/Mac) set a std stream as binary |
| 98 | +#define STDIN 0 |
| 99 | +#define STDOUT 1 |
| 100 | +#define STDERR 2 |
| 101 | +#ifndef __unix |
| 102 | +# define SET_BINARY_MODE(handle) setmode(handle, O_BINARY) |
| 103 | +#else |
| 104 | +# define SET_BINARY_MODE(handle) ((void)0) |
| 105 | +#endif |
| 106 | + |
95 | 107 | #include "contrib/bzip2/bzlib.h" |
96 | 108 | #include "contrib/giflib/precomp_gif.h" |
97 | 109 | #include "contrib/packjpg/precomp_jpg.h" |
@@ -125,6 +137,8 @@ int cb; // "checkbuf" |
125 | 137 | unsigned char in[CHUNK]; |
126 | 138 | unsigned char out[CHUNK]; |
127 | 139 |
|
| 140 | +bool header_already_read = false; |
| 141 | + |
128 | 142 | // name of temporary files |
129 | 143 | char metatempfile[18] = "~temp00000000.dat"; |
130 | 144 | char tempfile0[19] = "~temp000000000.dat"; |
@@ -1090,7 +1104,7 @@ int init(int argc, char* argv[]) { |
1090 | 1104 |
|
1091 | 1105 | // dot in output file name? If not, use .pcf extension |
1092 | 1106 | char* dot_at_pos = strrchr(output_file_name, '.'); |
1093 | | - if ((dot_at_pos == NULL) || ((backslash_at_pos != NULL) && (backslash_at_pos > dot_at_pos))) { |
| 1107 | + if (strcmp(output_file_name, "stdout") != 0 && ((dot_at_pos == NULL) || ((backslash_at_pos != NULL) && (backslash_at_pos > dot_at_pos)))) { |
1094 | 1108 | strcpy(output_file_name + strlen(argv[i]) - 2, ".pcf"); |
1095 | 1109 | appended_pcf = true; |
1096 | 1110 | } |
@@ -1139,13 +1153,24 @@ int init(int argc, char* argv[]) { |
1139 | 1153 | input_file_given = true; |
1140 | 1154 | input_file_name = argv[i]; |
1141 | 1155 |
|
1142 | | - fin_length = fileSize64(argv[i]); |
| 1156 | + if (strcmp(input_file_name, "stdin") == 0) { |
| 1157 | + if (operation != P_DECOMPRESS) { |
| 1158 | + print_to_console("ERROR: Reading from stdin only supported for recompressing.\n"); |
| 1159 | + exit(1); |
| 1160 | + } |
| 1161 | + // Read binary from stdin |
| 1162 | + SET_BINARY_MODE(STDIN); |
| 1163 | + fin = stdin; |
| 1164 | + } |
| 1165 | + else { |
| 1166 | + fin_length = fileSize64(argv[i]); |
1143 | 1167 |
|
1144 | | - fin = fopen(argv[i],"rb"); |
1145 | | - if (fin == NULL) { |
1146 | | - printf("ERROR: Input file \"%s\" doesn't exist\n", input_file_name); |
| 1168 | + fin = fopen(argv[i], "rb"); |
| 1169 | + if (fin == NULL) { |
| 1170 | + printf("ERROR: Input file \"%s\" doesn't exist\n", input_file_name); |
1147 | 1171 |
|
1148 | | - exit(1); |
| 1172 | + exit(1); |
| 1173 | + } |
1149 | 1174 | } |
1150 | 1175 |
|
1151 | 1176 | // output file given? If not, use input filename with .pcf extension |
@@ -1255,24 +1280,31 @@ int init(int argc, char* argv[]) { |
1255 | 1280 | read_header(); |
1256 | 1281 | } |
1257 | 1282 |
|
1258 | | - if (file_exists(output_file_name)) { |
1259 | | - printf("Output file \"%s\" exists. Overwrite (y/n)? ", output_file_name); |
1260 | | - char ch = get_char_with_echo(); |
1261 | | - if ((ch != 'Y') && (ch != 'y')) { |
1262 | | - printf("\n"); |
1263 | | - exit(0); |
1264 | | - } else { |
1265 | | - #ifndef __unix |
1266 | | - printf("\n\n"); |
1267 | | - #else |
1268 | | - printf("\n"); |
1269 | | - #endif |
1270 | | - } |
| 1283 | + if (output_file_given && strcmp(output_file_name, "stdout") == 0) { |
| 1284 | + // Write binary to stdout |
| 1285 | + SET_BINARY_MODE(STDOUT); |
| 1286 | + fout = stdout; |
1271 | 1287 | } |
1272 | | - fout = fopen(output_file_name,"wb"); |
1273 | | - if (fout == NULL) { |
1274 | | - printf("ERROR: Can't create output file \"%s\"\n", output_file_name); |
1275 | | - exit(1); |
| 1288 | + else { |
| 1289 | + if (file_exists(output_file_name)) { |
| 1290 | + printf("Output file \"%s\" exists. Overwrite (y/n)? ", output_file_name); |
| 1291 | + char ch = get_char_with_echo(); |
| 1292 | + if ((ch != 'Y') && (ch != 'y')) { |
| 1293 | + printf("\n"); |
| 1294 | + exit(0); |
| 1295 | + } else { |
| 1296 | + #ifndef __unix |
| 1297 | + printf("\n\n"); |
| 1298 | + #else |
| 1299 | + printf("\n"); |
| 1300 | + #endif |
| 1301 | + } |
| 1302 | + } |
| 1303 | + fout = fopen(output_file_name,"wb"); |
| 1304 | + if (fout == NULL) { |
| 1305 | + printf("ERROR: Can't create output file \"%s\"\n", output_file_name); |
| 1306 | + exit(1); |
| 1307 | + } |
1276 | 1308 | } |
1277 | 1309 |
|
1278 | 1310 | printf("Input file: %s\n",input_file_name); |
@@ -2374,14 +2406,17 @@ void denit_compress() { |
2374 | 2406 | } |
2375 | 2407 |
|
2376 | 2408 | #ifndef PRECOMPDLL |
2377 | | - long long fout_length = fileSize64(output_file_name); |
2378 | | - if (recursion_depth == 0) { |
2379 | | - if (!DEBUG_MODE) { |
2380 | | - printf("%s", string(14,'\b').c_str()); |
2381 | | - cout << "100.00% - New size: " << fout_length << " instead of " << fin_length << " " << endl; |
2382 | | - } else { |
2383 | | - cout << "New size: " << fout_length << " instead of " << fin_length << " " << endl; |
2384 | | - } |
| 2409 | + if (strcmp(output_file_name, "stdout") != 0) { |
| 2410 | + long long fout_length = fileSize64(output_file_name); |
| 2411 | + if (recursion_depth == 0) { |
| 2412 | + if (!DEBUG_MODE) { |
| 2413 | + printf("%s", string(14, '\b').c_str()); |
| 2414 | + cout << "100.00% - New size: " << fout_length << " instead of " << fin_length << " " << endl; |
| 2415 | + } |
| 2416 | + else { |
| 2417 | + cout << "New size: " << fout_length << " instead of " << fin_length << " " << endl; |
| 2418 | + } |
| 2419 | + } |
2385 | 2420 | } |
2386 | 2421 | #else |
2387 | 2422 | if (recursion_depth == 0) { |
@@ -4571,14 +4606,17 @@ void decompress_file() { |
4571 | 4606 |
|
4572 | 4607 | fin_pos = tell_64(fin); |
4573 | 4608 |
|
4574 | | -while (fin_pos < fin_length) { |
| 4609 | + auto otf_none_end_check = [](){ return compression_otf_method == OTF_NONE && (feof(fin) || ferror(fin)); }; |
| 4610 | + |
| 4611 | +while (!otf_none_end_check() || compression_otf_method != OTF_NONE && decompress_otf_end) { |
4575 | 4612 |
|
4576 | 4613 | if ((recursion_depth == 0) && (!DEBUG_MODE)) { |
4577 | 4614 | float percent = (fin_pos / (float)fin_length) * 100; |
4578 | 4615 | show_progress(percent, true, true); |
4579 | 4616 | } |
4580 | 4617 |
|
4581 | 4618 | unsigned char header1 = fin_fgetc(); |
| 4619 | + if (otf_none_end_check()) break; |
4582 | 4620 | if (header1 == 0) { // uncompressed data |
4583 | 4621 | long long uncompressed_data_length; |
4584 | 4622 | uncompressed_data_length = fin_fget_vlint(); |
@@ -5390,6 +5428,7 @@ void write_header() { |
5390 | 5428 |
|
5391 | 5429 | #ifdef COMFORT |
5392 | 5430 | bool check_for_pcf_file() { |
| 5431 | + if (header_already_read) return true; |
5393 | 5432 | seek_64(fin, 0); |
5394 | 5433 |
|
5395 | 5434 | fread(in, 1, 3, fin); |
@@ -5429,12 +5468,13 @@ bool check_for_pcf_file() { |
5429 | 5468 | strcpy(output_file_name, header_filename.c_str()); |
5430 | 5469 | } |
5431 | 5470 |
|
| 5471 | + header_already_read = true; |
5432 | 5472 | return true; |
5433 | 5473 | } |
5434 | 5474 | #endif |
5435 | 5475 |
|
5436 | 5476 | void read_header() { |
5437 | | - seek_64(fin, 0); |
| 5477 | + if (header_already_read) return; |
5438 | 5478 |
|
5439 | 5479 | fread(in, 1, 3, fin); |
5440 | 5480 | if ((in[0] == 'P') && (in[1] == 'C') && (in[2] == 'F')) { |
@@ -5465,6 +5505,8 @@ void read_header() { |
5465 | 5505 | output_file_name = new char[strlen(header_filename.c_str()) + 1]; |
5466 | 5506 | strcpy(output_file_name, header_filename.c_str()); |
5467 | 5507 | } |
| 5508 | + |
| 5509 | + header_already_read = true; |
5468 | 5510 | } |
5469 | 5511 |
|
5470 | 5512 | void convert_header() { |
|
0 commit comments