vita-pack-vpk.c (4713B)
1 #include <stdio.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <sys/stat.h> 6 #include <dirent.h> 7 #include <getopt.h> 8 #include <zip.h> 9 10 #define DEFAULT_OUTPUT_FILE "output.vpk" 11 #ifndef PATH_MAX 12 #define PATH_MAX 4096 13 #endif 14 15 static void usage(const char *arg); 16 17 static const struct option long_options[] = { 18 {"sfo", required_argument, NULL, 's'}, 19 {"eboot", required_argument, NULL, 'b'}, 20 {"add", required_argument, NULL, 'a'}, 21 {"help", no_argument, NULL, 'h'}, 22 {NULL, 0, NULL, 0} 23 }; 24 25 static int add_file_zip(zip_t *zip, const char *src, const char *dst) 26 { 27 struct stat s; 28 if (stat(src,&s)) { 29 return 0; 30 } 31 if (S_ISDIR(s.st_mode)) { 32 DIR *dir = opendir(src); 33 struct dirent *entry; 34 while((entry = readdir(dir))){ 35 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) 36 continue; 37 char src_dir[PATH_MAX]; 38 char dst_dir[PATH_MAX]; 39 int src_len = snprintf(src_dir, sizeof(src_dir)-1, "%s/%s", src, entry->d_name); 40 int dst_len = snprintf(dst_dir, sizeof(dst_dir)-1, "%s/%s", dst, entry->d_name); 41 src_dir[src_len] = 0; 42 dst_dir[dst_len] = 0; 43 add_file_zip(zip, src_dir, dst_dir); 44 } 45 closedir(dir); 46 }else if(S_ISREG(s.st_mode)){ 47 zip_file_add(zip, dst, zip_source_file(zip, src, 0, 0), 0); 48 } else { // symlink etc. 49 return 0; 50 } 51 return 1; 52 } 53 54 static struct { 55 char **src; 56 char **dst; 57 int num; 58 } additional_list; 59 60 static void additional_list_add(char *src, char *dst) 61 { 62 additional_list.src = realloc(additional_list.src, 63 sizeof(*additional_list.src) * (additional_list.num + 1)); 64 additional_list.dst = realloc(additional_list.dst, 65 sizeof(*additional_list.dst) * (additional_list.num + 1)); 66 67 additional_list.src[additional_list.num] = src; 68 additional_list.dst[additional_list.num] = dst; 69 70 additional_list.num++; 71 } 72 73 static void additional_list_init() 74 { 75 additional_list.src = NULL; 76 additional_list.dst = NULL; 77 additional_list.num = 0; 78 } 79 80 static void additional_list_free() 81 { 82 int i; 83 84 for (i = 0; i < additional_list.num; i++) { 85 free(additional_list.src[i]); 86 free(additional_list.dst[i]); 87 } 88 89 free(additional_list.src); 90 free(additional_list.dst); 91 } 92 93 static void parse_add_subopt(char *optarg) 94 { 95 char *src; 96 char *dst; 97 const char *equals; 98 size_t src_len; 99 size_t dst_len; 100 size_t len = strlen(optarg); 101 102 equals = strchr(optarg, '='); 103 if (!equals || (equals == optarg + len - 1)) 104 return; 105 106 src_len = equals - optarg; 107 dst_len = len - (equals - optarg + 1); 108 109 src = malloc(sizeof(char) * (src_len + 1)); 110 dst = malloc(sizeof(char) * (dst_len + 1)); 111 112 strncpy(src, optarg, src_len); 113 src[src_len] = '\0'; 114 115 strncpy(dst, optarg + src_len + 1, dst_len); 116 dst[dst_len] = '\0'; 117 118 additional_list_add(src, dst); 119 } 120 121 int main(int argc, char *argv[]) 122 { 123 int i; 124 int err; 125 zip_t *zip; 126 int opt; 127 char *output = NULL; 128 char *sfo = NULL; 129 char *eboot = NULL; 130 131 if (argc < 2) { 132 usage(argv[0]); 133 return -1; 134 } 135 136 additional_list_init(); 137 138 while ((opt = getopt_long(argc, argv, "hs:b:a:", long_options, NULL)) != -1) { 139 switch (opt) { 140 case 's': 141 sfo = strdup(optarg); 142 break; 143 case 'b': 144 eboot = strdup(optarg); 145 break; 146 case 'a': 147 parse_add_subopt(optarg); 148 break; 149 case 'h': 150 usage(argv[0]); 151 goto error_wrong_args; 152 } 153 } 154 155 if (!sfo) { 156 printf(".sfo file missing.\n"); 157 goto error_wrong_args; 158 } 159 160 if (!eboot) { 161 printf(".bin file missing.\n"); 162 goto error_wrong_args; 163 } 164 165 argc -= optind; 166 argv += optind; 167 168 if (argc > 0) 169 output = strdup(argv[0]); 170 else 171 output = strdup(DEFAULT_OUTPUT_FILE); 172 173 zip = zip_open(output, ZIP_CREATE | ZIP_TRUNCATE, &err); 174 if (!zip) { 175 printf("Error creating: \'%s\': %s\n", output, 176 zip_strerror(zip)); 177 goto error_create_zip; 178 } 179 180 if (!add_file_zip(zip, sfo, "sce_sys/param.sfo")) 181 goto error_add_zip; 182 183 if (!add_file_zip(zip, eboot, "eboot.bin")) 184 goto error_add_zip; 185 186 for (i = 0; i < additional_list.num; i++) { 187 if (!add_file_zip(zip, additional_list.src[i], 188 additional_list.dst[i])) 189 goto error_add_zip; 190 } 191 192 err = zip_close(zip); 193 if (err == -1) { 194 printf("Error creating: \'%s\': %s\n", output, 195 zip_strerror(zip)); 196 goto error_add_zip; 197 } 198 199 free(output); 200 free(sfo); 201 free(eboot); 202 additional_list_free(); 203 204 return 0; 205 206 error_add_zip: 207 zip_discard(zip); 208 209 error_create_zip: 210 free(output); 211 212 error_wrong_args: 213 if (sfo) 214 free(sfo); 215 if (eboot) 216 free(eboot); 217 218 additional_list_free(); 219 220 return -1; 221 } 222 223 void usage(const char *arg) 224 { 225 printf("Usage:\n\t%s [OPTIONS] output.vpk\n\n" 226 " -s, --sfo=param.sfo sets the param.sfo file\n" 227 " -b, --eboot=eboot.bin sets the eboot.bin file\n" 228 " -a, --add src=dst adds the file or directory src to the vpk as dst\n" 229 " -h, --help displays this help and exit\n" 230 , arg); 231 }