Mercurial > msvpvf
comparison src/main.c @ 85:1acd477da42f
posix: improvements
| author | Paper <paper@paper.us.eu.org> |
|---|---|
| date | Mon, 17 Jun 2024 21:18:37 -0400 |
| parents | c06dcab17923 |
| children | af4ed765c1ac |
comparison
equal
deleted
inserted
replaced
| 84:7d4db3e24487 | 85:1acd477da42f |
|---|---|
| 1 #include <stdio.h> | 1 #include <stdio.h> |
| 2 #include <stdint.h> | 2 #include <stdint.h> |
| 3 #include <stdlib.h> | 3 #include <stdlib.h> |
| 4 #include <stdarg.h> | |
| 4 #include <string.h> | 5 #include <string.h> |
| 5 | 6 |
| 6 #include <getopt.h> | 7 #include <getopt.h> |
| 7 #include <libgen.h> | 8 #include <libgen.h> |
| 8 | 9 |
| 9 #include "common.h" | 10 #include "common.h" |
| 10 | 11 |
| 11 /* non-portable functions */ | 12 /* non-portable functions */ |
| 12 static inline char* msvpvf_internal_strdup(const char* str) { | 13 static char* msvpvf_internal_strdup(const char* str) { |
| 13 size_t len = strlen(str) + 1; | 14 size_t len = strlen(str) + 1; |
| 14 | 15 |
| 15 char* copy = malloc(len); | 16 char* copy = malloc(len); |
| 16 if (!copy) | 17 if (!copy) |
| 17 return NULL; | 18 return NULL; |
| 18 | 19 |
| 19 memcpy(copy, str, len); | 20 memcpy(copy, str, len); |
| 20 return copy; | 21 return copy; |
| 21 } | 22 } |
| 22 | 23 |
| 24 static char *msvpvf_internal_asnprintf(const char *format, ...) { | |
| 25 va_list args; | |
| 26 int needed_size; | |
| 27 char *output = NULL; | |
| 28 | |
| 29 va_start(args, format); | |
| 30 | |
| 31 needed_size = vsnprintf(NULL, 0, format, args); | |
| 32 if (needed_size < 0) | |
| 33 return NULL; | |
| 34 | |
| 35 va_end(args); | |
| 36 | |
| 37 output = malloc((needed_size + 1) * sizeof(char)); | |
| 38 if (!output) | |
| 39 return NULL; | |
| 40 | |
| 41 va_start(args, format); | |
| 42 | |
| 43 needed_size = vsnprintf(output, needed_size + 1, format, args); | |
| 44 if (needed_size < 0) { | |
| 45 free(output); | |
| 46 return NULL; | |
| 47 } | |
| 48 | |
| 49 va_end(args); | |
| 50 | |
| 51 return output; | |
| 52 } | |
| 53 | |
| 23 /* source needs read permissions, target needs write permissions, both must be in binary mode */ | 54 /* source needs read permissions, target needs write permissions, both must be in binary mode */ |
| 24 static inline int copy_file(FILE* source, FILE* target) { | 55 static int copy_file(FILE* source, FILE* target) { |
| 25 char ch[4096]; | 56 char ch[4096]; |
| 26 | 57 |
| 27 while (!feof(source)) { | 58 while (!feof(source)) { |
| 28 size_t b = fread(ch, 1, sizeof(ch), source); | 59 size_t b = fread(ch, 1, sizeof(ch), source); |
| 29 if (b) | 60 if (b) |
| 31 } | 62 } |
| 32 | 63 |
| 33 return 0; | 64 return 0; |
| 34 } | 65 } |
| 35 | 66 |
| 36 static inline const char* type_to_string(enum types type) { | 67 static const char* type_names[] = { |
| 37 switch (type) { | 68 [TYPES_VF] = "Movie Studio", |
| 38 case TYPES_VF: return "Movie Studio"; | 69 [TYPES_VEG] = "Vegas Pro", |
| 39 case TYPES_VEG: return "Vegas Pro"; | 70 [TYPES_UNKNOWN] = "Unknown", |
| 40 case TYPES_UNKNOWN: | 71 }; |
| 41 default: return "Unknown"; | 72 |
| 42 } | 73 static const char* type_extensions[] = { |
| 43 } | 74 [TYPES_VF] = "vf", |
| 44 | 75 [TYPES_VEG] = "veg", |
| 45 static inline const char* type_to_extension(enum types type) { | 76 }; |
| 46 switch (type) { | |
| 47 case TYPES_VF: return "vf"; | |
| 48 case TYPES_VEG: | |
| 49 case TYPES_UNKNOWN: | |
| 50 default: return "veg"; | |
| 51 } | |
| 52 } | |
| 53 | 77 |
| 54 #ifndef ARRAYSIZE | 78 #ifndef ARRAYSIZE |
| 55 #define ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0])) | 79 #define ARRAYSIZE(x) (sizeof(x) / sizeof((x)[0])) |
| 56 #endif | 80 #endif |
| 57 | 81 |
| 58 static const char* help_text = | 82 static const char* help_text = |
| 59 "msvpvf by Paper\n" | 83 "msvpvf help text\n" |
| 84 "author: Paper <paper@paper.us.eu.org>\n" | |
| 60 "usage: %s <input>... (arguments)\n" | 85 "usage: %s <input>... (arguments)\n" |
| 61 "\n" | 86 "\n" |
| 62 "arguments:\n" | 87 "arguments:\n" |
| 63 " -t, --type one of [vf,veg] (required)\n" | 88 " -t, --type one of [vf,veg] (required)\n" |
| 64 " -v, --version version to convert to (required)\n" | 89 " -v, --version version to convert to (required)\n" |
| 65 " -h, --help show this screen (optional)\n"; | 90 " -h, --help show this screen (optional)\n"; |
| 66 | 91 |
| 67 static struct option options_long[] = { | 92 static struct option options_long[] = { |
| 68 {"version", required_argument, NULL, 'v'}, | 93 {"version", required_argument, NULL, 'v'}, |
| 69 {"type", required_argument, NULL, 't'}, | 94 {"type", required_argument, NULL, 't'}, |
| 70 {"help", 0, NULL, 'h'} | 95 {"help", 0, NULL, 'h'}, |
| 71 }; | 96 }; |
| 72 | 97 |
| 73 int main(int argc, char *argv[]) { | 98 int main(int argc, char *argv[]) { |
| 74 uint8_t version = 0; | 99 uint8_t version = 0; |
| 75 enum types type = TYPES_UNKNOWN; | 100 enum types type = TYPES_VEG; /* ...? */ |
| 76 | 101 |
| 77 int c; | 102 int c; |
| 78 int option_index = 0; | 103 int option_index = 0; |
| 79 while ((c = getopt_long(argc, argv, "v:t:h", options_long, &option_index)) != -1) { | 104 while ((c = getopt_long(argc, argv, "v:t:h", options_long, &option_index)) != -1) { |
| 80 /* option argument */ | 105 /* option argument */ |
| 99 break; | 124 break; |
| 100 } | 125 } |
| 101 } | 126 } |
| 102 | 127 |
| 103 if (argc <= optind) { | 128 if (argc <= optind) { |
| 104 fprintf(stderr, "[ERROR]: Missing input file!\n"); | 129 fprintf(stderr, "[ERROR]: Missing input file(s)!\n"); |
| 105 printf(help_text, argv[0]); | 130 printf(help_text, argv[0]); |
| 106 return 1; | 131 return 1; |
| 107 } | 132 } |
| 108 | 133 |
| 109 if (!version || !type) { | 134 if (!version || !type) { |
| 110 printf(help_text, (argc > 0) ? argv[0] : "msvpvf"); | 135 printf(help_text, (argc > 0) ? argv[0] : "msvpvf"); |
| 111 return 1; | 136 return 1; |
| 112 } | 137 } |
| 113 | 138 |
| 114 /* this progressively */ | |
| 115 while (optind < argc) { | 139 while (optind < argc) { |
| 116 const char* input = argv[optind++]; | 140 const char* input = argv[optind++]; |
| 117 FILE* output_file = NULL; | 141 FILE *input_file, *output_file = NULL; |
| 142 uint8_t file_version = 0; | |
| 143 enum types file_type = TYPES_UNKNOWN; | |
| 144 | |
| 145 printf("Input file name: %s\n", input); | |
| 146 | |
| 147 /* print information about the input file */ | |
| 148 input_file = fopen(input, "rb"); | |
| 149 if (!input_file) { | |
| 150 fprintf(stderr, "[ERROR]: Error opening input file %s!\n\n", input); | |
| 151 continue; | |
| 152 } | |
| 153 | |
| 154 if (fgetc(input_file) == EOF) { | |
| 155 fprintf(stderr, "[ERROR]: Input file \"%s\" is empty.\n", input); | |
| 156 fclose(input_file); | |
| 157 continue; | |
| 158 } | |
| 159 | |
| 160 if (get_file_information(input_file, &file_version, &file_type)) { | |
| 161 fprintf(stderr, "[ERROR]: Failed to get file information for input file \"%s\"!\n", input); | |
| 162 fclose(input_file); | |
| 163 continue; | |
| 164 } | |
| 165 | |
| 166 printf("Input file version: %u\n", file_version); | |
| 167 printf("Input file type: %s\n\n", type_names[file_type]); | |
| 118 | 168 |
| 119 { | 169 { |
| 120 uint8_t file_version = 0; | 170 /* open the output file... */ |
| 121 enum types file_type = TYPES_UNKNOWN; | 171 char* basec = msvpvf_internal_strdup(input); |
| 122 | 172 char* bname = basename(basec); |
| 123 printf("Input file name: %s\n", input); | 173 int ext = strrchr(bname, '.') - bname; |
| 124 /* print information about the input file */ | 174 |
| 125 FILE* input_file = fopen(input, "rb"); | 175 char *output = msvpvf_internal_asnprintf("V%u_%.*s.%s", version, ext, bname, type_extensions[type]); |
| 126 if (!input_file) { | 176 if (!output) { |
| 127 fprintf(stderr, "[ERROR]: Error opening input file %s!\n\n", input); | 177 fprintf(stderr, "[ERROR]: msvpvf_internal_asnprintf failed!\n"); |
| 128 continue; | 178 free(basec); |
| 129 } | 179 free(output); |
| 130 | |
| 131 if (fgetc(input_file) == EOF) { | |
| 132 fprintf(stderr, "[ERROR]: Input file \"%s\" is empty.\n", input); | |
| 133 fclose(input_file); | 180 fclose(input_file); |
| 134 continue; | 181 continue; |
| 135 } | 182 } |
| 136 | 183 |
| 137 if (get_file_information(input_file, &file_version, &file_type)) { | 184 output_file = fopen(output, "w+b"); |
| 138 fprintf(stderr, "[ERROR]: Failed to get file information for input file \"%s\"!\n", input); | 185 if (!output_file) { |
| 186 fprintf(stderr, "[ERROR]: Failed to open output file %s! Do you have write permissions?\n", output); | |
| 187 free(basec); | |
| 188 free(output); | |
| 139 fclose(input_file); | 189 fclose(input_file); |
| 140 continue; | 190 continue; |
| 141 } | 191 } |
| 142 | 192 |
| 143 printf("Input file version: %u\n", file_version); | 193 free(basec); |
| 144 printf("Input file type: %s\n\n", type_to_string(file_type)); | 194 free(output); |
| 145 | 195 } |
| 146 { | 196 |
| 147 /* open the output file... */ | 197 copy_file(input_file, output_file); |
| 148 char* basec = msvpvf_internal_strdup(input); | 198 |
| 149 char* bname = basename(basec); | 199 fflush(stdout); |
| 150 int ext = strrchr(bname, '.') - bname; | 200 fclose(input_file); |
| 151 | |
| 152 /* create the output filename */ | |
| 153 int needed_size = snprintf(NULL, 0, "V%u_%.*s.%s", version, ext, bname, type_to_extension(type)); | |
| 154 char* output = malloc((needed_size + 1) * sizeof(char)); | |
| 155 if (!output) { | |
| 156 fprintf(stderr, "[ERROR]: Failed to allocate memory for output string!\n"); | |
| 157 free(basec); | |
| 158 return 1; | |
| 159 } | |
| 160 | |
| 161 snprintf(output, needed_size + 1, "V%u_%.*s.%s", version, ext, bname, type_to_extension(type)); | |
| 162 printf("Output filename: %s\n", output); | |
| 163 | |
| 164 output_file = fopen(output, "w+b"); | |
| 165 if (!output_file) { | |
| 166 fprintf(stderr, "[ERROR]: Failed to open output file %s! Do you have write permissions?\n", output); | |
| 167 free(basec); | |
| 168 free(output); | |
| 169 continue; | |
| 170 } | |
| 171 free(basec); | |
| 172 free(output); | |
| 173 } | |
| 174 | |
| 175 copy_file(input_file, output_file); | |
| 176 | |
| 177 fflush(stdout); | |
| 178 fclose(input_file); | |
| 179 } | |
| 180 | 201 |
| 181 set_file_information(output_file, version, type); | 202 set_file_information(output_file, version, type); |
| 182 fclose(output_file); | 203 fclose(output_file); |
| 183 } | 204 } |
| 184 | 205 |
