00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifdef HAVE_CONFIG_H
00020 # include <config.h>
00021 #endif
00022
00023 #ifndef ALPHA_LINUX_CXX
00024 # include <unistd.h>
00025 # include <fstream>
00026 # include <cstdio>
00027 # include <cstdlib>
00028 # include <cstring>
00029 #endif
00030 #include <iostream>
00031 #include <iomanip>
00032 #include <vector>
00033 #include <string>
00034 #include "U7file.h"
00035 #include "Flex.h"
00036 #include "utils.h"
00037 #include "databuf.h"
00038 #include "crc.h"
00039 #include "exceptions.h"
00040
00041 using std::atoi;
00042 using std::cerr;
00043 using std::cout;
00044 using std::endl;
00045 using std::exit;
00046 using std::FILE;
00047 using std::ifstream;
00048 using std::ofstream;
00049 using std::size_t;
00050 using std::strrchr;
00051 using std::strncpy;
00052 using std::strncat;
00053 using std::strlen;
00054 using std::vector;
00055 using std::string;
00056
00057 enum Arch_mode { NONE, LIST, EXTRACT, CREATE, ADD, RESPONSE };
00058
00059 bool is_text_file(const char *fname)
00060 {
00061 int len = strlen(fname);
00062
00063
00064 if (len > 4 && fname[len-4] == '.' &&
00065 (fname[len-3] == 't' || fname[len-3] == 'T') &&
00066 (fname[len-2] == 'x' || fname[len-2] == 'X') &&
00067 (fname[len-1] == 't' || fname[len-1] == 'T'))
00068 {
00069 return true;
00070 }
00071
00072 return false;
00073 }
00074
00075 bool is_null_entry(const char *fname)
00076 {
00077 int len = strlen(fname);
00078
00079 if (len >= 4 && fname[len-4] == 'N' && fname[len-3] == 'U' &&
00080 fname[len-2] == 'L' && fname[len-1] == 'L')
00081 return true;
00082
00083 return false;
00084
00085 }
00086
00087 void set_mode(Arch_mode &mode, Arch_mode new_mode)
00088 {
00089 if(mode!=NONE) {
00090 cerr << "Error: cannot specify multiple modes" << endl;
00091 exit(1);
00092 } else
00093 mode = new_mode;
00094 }
00095
00096
00097 void make_header_name(char *filename)
00098 {
00099 int i = strlen (filename);
00100
00101 while (i--) if (filename[i] == '.') filename[i] = '_';
00102 else if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':') break;
00103 }
00104
00105
00106 void make_uppercase (char *name)
00107 {
00108 int i = strlen (name);
00109
00110 while (i--) if (name[i] >= 'a' && name[i] <= 'z') name[i] -= 'a' - 'A';
00111 }
00112
00113
00114 void strip_path (char *filename)
00115 {
00116 int i = strlen (filename);
00117
00118 while (i--)
00119 {
00120 if (filename[i] == '\\' || filename[i] == '/' || filename[i] == ':')
00121 break;
00122 }
00123
00124
00125 if (i >= 0)
00126 {
00127 int j = 0;
00128
00129 for (i++, j = 0; filename[j+i]; j++)
00130 filename[j] = filename[j+i];
00131
00132 filename[j] = 0;
00133 }
00134 }
00135
00136 long get_file_size(const char *fname)
00137 {
00138 if (is_null_entry(fname))
00139 return 0;
00140
00141 const char *mode = "rb";
00142 bool text = is_text_file(fname);
00143 if (text)
00144 mode = "r";
00145
00146 FILE *fp;
00147 try {
00148 fp = U7open (fname, mode);
00149 } catch (const file_open_exception& e) {
00150 cerr << e.what() << endl;
00151 exit(1);
00152 }
00153
00154 long len = 0;
00155 if (!text)
00156 {
00157 fseek(fp, 0, SEEK_END);
00158 len = ftell(fp);
00159 }
00160 else while (fgetc(fp) != EOF)
00161 len++;
00162
00163 fclose(fp);
00164 return len;
00165 }
00166
00167
00168
00169
00170 void getline(ifstream& file, char* buf, int size)
00171 {
00172 int i = 0;
00173 char c;
00174 file.get(c);
00175
00176 while (i < size-1 && (c>=' ' || c=='\t') && file.good()) {
00177 buf[i++] = c;
00178 file.get(c);
00179 }
00180 buf[i] = '\0';
00181
00182 while (!(file.peek()>=' ' || file.peek()=='\t') && file.good())
00183 file.get(c);
00184 }
00185
00186
00187 #ifdef MACOS
00188
00189 int mac_main(int argc, char **argv);
00190
00191 int main()
00192 {
00193 const int mac_argc = 3;
00194 char *mac_argv[mac_argc] =
00195 {
00196 "expack",
00197 "-i",
00198 "flx.in"
00199 };
00200
00201 mac_main( mac_argc, mac_argv );
00202
00203 char *mac_argv2[mac_argc] =
00204 {
00205 "expack",
00206 "-i",
00207 "bg/flx.in"
00208 };
00209
00210 mac_main( mac_argc, mac_argv2 );
00211
00212 char *mac_argv3[mac_argc] =
00213 {
00214 "expack",
00215 "-i",
00216 "si/flx.in"
00217 };
00218
00219 mac_main( mac_argc, mac_argv3 );
00220 }
00221
00222
00223 int mac_main(int argc, char **argv)
00224 #else
00225 int main(int argc, char **argv)
00226 #endif
00227 {
00228 Arch_mode mode = NONE;
00229 char fname[1024];
00230 char hname[1024];
00231 char hprefix[1024];
00232 char ext[] = "u7o";
00233 int index;
00234 vector<string> file_names;
00235 hname[0] = 0;
00236
00237 if(argc>2) {
00238 strncpy(fname, argv[2], 1024);
00239 if((argv[1][0]=='-')&&(strlen(argv[1])==2)) {
00240 switch(argv[1][1]) {
00241 case 'i':
00242 {
00243 char temp[1024];
00244 char path_prefix[1024];
00245
00246 ifstream respfile;
00247 char *slash = strrchr(fname, '/');
00248 if(slash) {
00249 int len = slash-fname+1;
00250 strncpy(path_prefix, fname, len);
00251 path_prefix[len] = 0;
00252 } else
00253 path_prefix[0] = 0;
00254
00255 set_mode(mode,RESPONSE);
00256 try {
00257 U7open(respfile, fname, true);
00258 } catch (const file_open_exception& e) {
00259 cerr << e.what() << endl;
00260 exit(1);
00261 }
00262
00263
00264 getline(respfile, temp, 1024);
00265 strncpy(fname, path_prefix, 1024);
00266 strncat(fname, temp, 1024);
00267
00268
00269 strncpy (hprefix, temp, 1024);
00270 make_header_name(hprefix);
00271 strncpy (hname, path_prefix, 1024);
00272 strncat (hname, hprefix, 1024);
00273 strncat (hname, ".h", 1024);
00274 strip_path (hprefix);
00275 make_uppercase (hprefix);
00276
00277 while(respfile.good()) {
00278 getline(respfile, temp, 1024);
00279 if(strlen(temp)>0) {
00280 char temp2[1024];
00281 strncpy(temp2, path_prefix,1024);
00282 strncat(temp2, temp, 1024);
00283 file_names.push_back(temp2);
00284 }
00285 }
00286 respfile.close();
00287 }
00288 break;
00289 case 'l':
00290 set_mode(mode,LIST);
00291 break;
00292 case 'x':
00293 set_mode(mode,EXTRACT);
00294 break;
00295 case 'c':
00296 {
00297 for(int i=0;i<argc-3;i++) {
00298 file_names.push_back(argv[i+3]);
00299 }
00300 set_mode(mode,CREATE);
00301 break;
00302 }
00303 case 'a':
00304 set_mode(mode,ADD);
00305 break;
00306 default:
00307 mode = NONE;
00308 break;
00309 }
00310 }
00311 }
00312
00313 switch(mode) {
00314 case LIST:
00315 {
00316 if(argc!=3)
00317 break;
00318 U7FileManager fm;
00319 U7file *f = fm.get_file_object(fname);
00320 int count = f->number_of_objects();
00321 cout << "Archive: " << fname << endl;
00322 cout << "Type: " << f->get_archive_type() << endl;
00323 cout << "Size: " << count << endl;
00324 cout << "-------------------------" << endl;
00325 for(int i=0; i<count; i++) {
00326 char *buf;
00327 size_t len;
00328
00329 buf = f->retrieve(i, len);
00330 cout << i << "\t" << len << endl;
00331 delete [] buf;
00332 }
00333 }
00334 break;
00335 case EXTRACT:
00336 {
00337 if(argc==4) {
00338 U7object f(fname,atoi(argv[3]));
00339 int nobjs = f.number_of_objects();
00340 int n = atoi(argv[3]);
00341 if (n >= nobjs) {
00342 cerr << "Obj. #(" << n <<
00343 ") is too large. ";
00344 cerr << "Flex size is " <<
00345 nobjs << '.' << endl;
00346 exit(1);
00347 }
00348 char outfile[32];
00349 snprintf(outfile,32,"%d.%s", n, ext);
00350 f.retrieve(outfile);
00351 } else {
00352 U7FileManager fm;
00353 U7file *f = fm.get_file_object(fname);
00354 int count = f->number_of_objects();
00355 for(index=0; index<count; index++) {
00356 U7object o(fname,index);
00357 char outfile[32];
00358 snprintf(outfile,32,"%d.%s",index,ext);
00359 o.retrieve(outfile);
00360 }
00361 delete f;
00362 }
00363 }
00364 break;
00365 case RESPONSE:
00366 case CREATE:
00367 {
00368 ofstream flex;
00369 try {
00370 U7open(flex, fname);
00371 } catch (const file_open_exception& e) {
00372 cerr << e.what() << endl;
00373 exit(1);
00374 }
00375
00376 char hline[1024];
00377 ofstream header;
00378 if (!hname[0]) {
00379 strncpy (hprefix, fname, 1024);
00380 make_header_name(hprefix);
00381 strncat (hname, hprefix, 1024);
00382 strncat (hname, ".h", 1024);
00383 }
00384 try {
00385 U7open(header, hname, true);
00386 } catch (const file_open_exception& e) {
00387 cerr << e.what() << endl;
00388 exit(1);
00389 }
00390
00391
00392 Flex_writer writer(flex, "Exult Archive", file_names.size());
00393
00394
00395 header << "// Header for \"" << fname << "\" Created by expack" << std::endl << std::endl;
00396 header << "// DO NOT MODIFY" << std::endl << std::endl;
00397 header << "#ifndef " << hprefix << "_INCLUDED" << std::endl;
00398 header << "#define " << hprefix << "_INCLUDED" << std::endl << std::endl;
00399
00400
00401 {
00402 for(int i=0; i<file_names.size(); i++) {
00403 int fsize = get_file_size(file_names[i].c_str());
00404 if(fsize) {
00405 ifstream infile;
00406 try {
00407 U7open(infile, file_names[i].c_str(), is_text_file(file_names[i].c_str()));
00408 } catch (const file_open_exception& e) {
00409 cerr << e.what() << endl;
00410 exit(1);
00411 }
00412 StreamDataSource ifs(&infile);
00413 char *buf = new char[fsize];
00414 ifs.read(buf, fsize);
00415 flex.write(buf, fsize);
00416 delete [] buf;
00417 infile.close();
00418
00419 strncpy (hline, file_names[i].c_str(), 1024);
00420 strip_path(hline);
00421 make_header_name(hline);
00422 make_uppercase(hline);
00423 header << "#define\t" << hprefix << "_" << hline << "\t\t" << i << std::endl;
00424 }
00425 writer.mark_section_done();
00426 }
00427 }
00428 if (!writer.close())
00429 cerr << "Error writing " << fname << endl;
00430
00431 uint32 crc32val = crc32_syspath(fname);
00432 header << std::endl << "#define\t" << hprefix << "_CRC32\t0x";
00433 header << std::hex << crc32val << std::dec << "U" << std::endl;
00434
00435 header << std::endl << "#endif" << std::endl << std::endl;
00436 header.close();
00437
00438 }
00439 break;
00440 default:
00441 cout << "Usage:" << endl
00442 << argv[0] << " -[l|x|c] file [index]" << endl
00443 << argv[0] << " -i indexfile" << endl;
00444 break;
00445 }
00446 return 0;
00447 }
00448