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 |
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 |