Вам скинули PNG файл с присученным зип архивом. Что делать?
convert orig.png new.png
Вам скинули JPG файл с присученным зип архивом. Что блять делать?
jpegtran < orig.jpg > new.jpg
Вам скинули WEBP файл с присученным зип архивом. Ну сука! Но и здесь есть выход, не привлекающий дополнительные потери.
#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <libgen.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// DEBUG
#include <mcheck.h>
char *
normal_person_strcat_2 (const char *fst, const char *snd) {
char *cat;
int fstLen, sndLen;
fstLen = strlen(fst);
sndLen = strlen(snd);
cat = malloc(sizeof(char) * (fstLen + sndLen + 1));
memset(cat, '\0', sizeof(char) * (fstLen + sndLen + 1));
int i;
for (i = 0; i < fstLen + sndLen; i++) {
if (i < fstLen)
cat[i] = fst[i];
else
cat[i] = snd[i - fstLen];
}
return cat;
}
char *
normal_person_strcat (int cnt, ...) {
va_list args;
char *cat, *buf;
va_start(args, cnt);
cat = malloc(sizeof(char));
cat[0] = '\0';
int i;
for (i = 0; i < cnt; i++) {
buf = va_arg (args, char *);
buf = normal_person_strcat_2 (cat, buf);
free(cat);
cat = buf;
}
va_end (args);
return cat;
}
void
print_usage (FILE *stream, const char *argv0) {
char *msg;
char *name, *buf;
buf = strdup(argv0);
name = basename(buf);
msg = normal_person_strcat(
3,
"usage: ",
name,
" filename\n"
);
fprintf(stream, msg);
free(msg);
free(buf);
}
void
fread_write_fail (const char *read_write, size_t ret, size_t expected) {
char *verb;
if (strcmp(read_write, "read") == 0)
verb = strdup("read");
else
verb = strdup("written");
if (ret != expected) {
fprintf(
stderr, "%s() failed: %zu chunks %s\n",
read_write,
ret,
verb
);
exit(EXIT_FAILURE);
}
free(verb);
}
#define fread_fail(a, b) { fread_write_fail ("read", a, b); }
#define fwrite_fail(a, b) { fread_write_fail ("write", a, b); }
size_t
my_fread (void *ptr, size_t size, size_t nmemb, FILE *stream) {
size_t ret;
ret = fread (ptr, size, nmemb, stream);
fread_fail (ret, nmemb);
return ret;
}
size_t
my_fwrite (const void *ptr, size_t size, size_t nmemb, FILE *stream) {
size_t ret;
ret = fwrite (ptr, size, nmemb, stream);
fwrite_fail (ret, nmemb);
return ret;
}
int
main (int argc, char **argv) {
/* DEBUG */
// https://www.gnu.org/software/libc/manual/html_node/Tracing-malloc.html
mtrace();
if (argc != 2) {
print_usage (stderr, argv[0]);
return EXIT_FAILURE;
}
int ret;
/* Check if it's regular file, LOL */
struct stat sb;
ret = stat (argv[0], &sb);
if (ret) {
fprintf(stderr, "stat() failed: ");
perror(argv[0]);
return EXIT_FAILURE;
}
if (!S_ISREG(sb.st_mode)) {
fprintf(stderr, "%s is not regular file!\n", argv[0]);
return EXIT_FAILURE;
}
FILE *webp_file;
webp_file = fopen(argv[1], "r");
if (NULL == webp_file) {
perror(argv[1]);
return EXIT_FAILURE;
}
/* Read WEBP header */
fprintf(stderr, "Reading webp header...\n");
char chunk[4];
uint32_t filesize;
my_fread (chunk, 1, 4, webp_file);
printf("This must be 'RIFF': %s\n", chunk);
if (strncmp("RIFF", chunk, sizeof(char) * 4)) {
fprintf(stderr, "'%s' is not webp file.\n", argv[1]);
return EXIT_FAILURE;
}
my_fread (&filesize, 1, 4, webp_file);
printf("This must be filesize: %u\n", filesize);
my_fread (chunk, 1, 4, webp_file);
printf("This must be 'WEBP': %s\n", chunk);
if (strncmp("WEBP", chunk, sizeof(char) * 4)) {
fprintf(stderr, "'%s' is not webp file.\n", argv[1]);
return EXIT_FAILURE;
}
/* Read WEBP payload */
fprintf(stderr, "Reading webp payload...\n");
fprintf(stderr, "Expected read size: %u\n", filesize - 4);
char webp_payload[filesize - 4];
my_fread (webp_payload, 1, filesize - 4, webp_file);
fclose(webp_file);
/* Write stripped file */
fprintf(stderr, "Writing new file...\n");
ret = strlen(argv[1]) + strlen("/_orig") + 1;
char new_webp_name[ret];
char *dir, *name, *path;
FILE *new_webp;
path = strdup(argv[1]);
dir = dirname(path);
name = basename(path);
memset(new_webp_name, '\0', sizeof(char) * ret);
sprintf(new_webp_name, "%s/%s%s", dir, "orig_", name);
free(path);
errno = 0;
ret = access(new_webp_name, F_OK);
if (errno != 0 && errno != ENOENT) {
perror(new_webp_name);
return EXIT_FAILURE;
}
if (!ret) {
printf("%s alread exists.\n", new_webp_name);
return EXIT_FAILURE;
}
new_webp = fopen(new_webp_name, "w+");
if (NULL == new_webp) {
perror(new_webp_name);
return EXIT_FAILURE;
}
my_fwrite("RIFF", sizeof(char), 4, new_webp);
my_fwrite(&filesize, sizeof(uint32_t), 1, new_webp);
my_fwrite("WEBP", sizeof(char), 4, new_webp);
my_fwrite(webp_payload, sizeof(char), filesize - 4, new_webp);
fclose(new_webp);
}
По идее, это ламерское говно, но посколько оно работает, мне как-то похуй. Если хотите улучшайте-дополняйте.