1 /*
2  * LDAT - Luola Datafile format archiver
3  * Copyright (C) 2002-2005 Calle Laakkonen
4  *
5  * File        : ldatar.c
6  * Description : A program to manipulate LDAT archives
7  * Author(s)   : Calle Laakkonen
8  *
9  * LDAT is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Luola is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23 
24 #include <stdlib.h>
25 #include <getopt.h>
26 #include <stdio.h>
27 
28 #include "ldat.h"
29 #include "archive.h"
30 
31 typedef enum {MODE_UNSET,LIST,PACK,EXTRACT} Mode;
32 static Mode ldat_mode = MODE_UNSET;
33 static int verbose = 0, pack_index = 1;
34 
35 /* Print out list of files in LDAT archive */
list_ldat(const char * filename)36 static int list_ldat(const char *filename) {
37     LDAT *ldat = ldat_open_file(filename);
38     if(!ldat) return 1;
39 
40     print_ldat_catalog(ldat, verbose);
41 
42     ldat_free(ldat);
43     return 0;
44 }
45 
46 /* Make a new LDAT archive */
pack_ldat(const char * filename,int filec,char * filev[])47 static int pack_ldat(const char *filename,int filec, char *filev[]) {
48     const char *outputfile;
49     LDAT *ldat = ldat_create();
50 
51     if(filec==0) {
52         /* No list of files specified, assume filename is a .pack file */
53         outputfile = pack_ldat_index(ldat,filename, pack_index,verbose);
54         if(outputfile==NULL)
55             return 1;
56     } else {
57         /* Pack listed files */
58         struct dllist *files=NULL;
59         int r;
60         for(r=0;r<filec;r++) {
61             struct Filename *newfile = make_file(filev[r],filev[r],0);
62             if(newfile == NULL)
63                 return 1;
64             if (files)
65                 dllist_append(files, newfile);
66             else
67                 files = dllist_append(NULL, newfile);
68         }
69         pack_ldat_files(ldat,files,verbose);
70         outputfile = filename;
71     }
72     if(verbose)
73         printf("Saving \"%s\"...\n",outputfile);
74     if(ldat_save_file(ldat, outputfile)) {
75         fputs("Error occured while saving",stderr);
76         ldat_free(ldat);
77         return 1;
78     }
79     if(verbose)
80         printf("\tOk.\n");
81     ldat_free(ldat);
82     return 0;
83 }
84 
85 /* Extract files from an LDAT archive */
extract_ldat(const char * filename,int filec,char * filev[])86 static int extract_ldat(const char *filename,int filec, char *filev[]) {
87     int rval=0;
88     if(filec==0) {
89         /* No list of files specified, assume filename is a .pack file */
90         if(unpack_ldat_index(filename, verbose))
91             rval=1;
92     } else {
93         /* Unpack listed files */
94         LDAT *ldat = ldat_open_file(filename);
95         if(ldat==NULL) {
96             rval=1;
97         } else {
98             struct dllist *files=NULL;
99             int r;
100             for(r=0;r<filec;r++) {
101                 struct Filename file;
102                 strcpy(file.filename,filev[r]);
103                 strcpy(file.id,filev[r]);
104                 file.index = 0;
105                 if(r+1<filec) {
106                     char *endptr=NULL;
107                     int tmpi = strtol(filev[r+1],&endptr,10);
108                     if(endptr==NULL) {
109                         file.index=tmpi;
110                         r++;
111                     }
112                 }
113                 if(unpack_ldat_file(ldat,&file,verbose)) {
114                     rval=1;
115                     break;
116                 }
117             }
118             ldat_free(ldat);
119         }
120     }
121 
122     return rval;
123 }
124 
set_mode(Mode mode)125 static void set_mode(Mode mode) {
126     if(ldat_mode!=MODE_UNSET) {
127         fputs("Use only one of -l, -p or -x\n",stderr);
128         exit(1);
129     }
130     ldat_mode = mode;
131 }
132 
main(int argc,char * argv[])133 int main(int argc, char *argv[]) {
134     const char *ldatfile;
135     int c=0,rval;
136     if(argc==1) {
137         puts("Luola Datafile tool");
138         puts("Usage: ldat <options> [files...]\nOptions:");
139         puts("\t-h, --help                Show this help");
140         puts("\t-l, --list <ldat>         List the contents of an archive");
141         puts("\t-p, --pack <ldat/pack>    Pack files into an archive");
142         puts("\t-x, --extract <ldat/pack> Extract files from an archive");
143         puts("\t-I, --noindex             Do not automatically insert index file");
144         puts("\t-v, --verbose             Print extra information");
145         exit(0);
146     }
147 
148     while(c!=-1) {
149         static struct option options[] = {
150             {"list",    required_argument,  0, 'l'},
151             {"pack",    required_argument,  0, 'p'},
152             {"extract", required_argument,  0, 'x'},
153             {"index",   no_argument,        0, 'i'},
154             {"noindex",no_argument,        0, 'I'},
155             {0,0,0,0}};
156         int option_index = 0;
157 
158         c = getopt_long(argc,argv,"l:p:x:Iv", options, &option_index);
159         switch(c) {
160             case 'l': set_mode(LIST); ldatfile=optarg; break;
161             case 'p': set_mode(PACK); ldatfile=optarg; break;
162             case 'x': set_mode(EXTRACT); ldatfile=optarg; break;
163             case 'I': pack_index = 0; break;
164             case 'v': verbose = 1; break;
165             case '?': exit(1);
166         }
167     }
168 
169     switch(ldat_mode) {
170         case MODE_UNSET:
171             fputs("No action selected\n",stderr);
172             rval=1;
173             break;
174         case LIST:
175             rval=list_ldat(ldatfile);
176             break;
177         case PACK:
178             rval=pack_ldat(ldatfile,argc-optind,argv+optind);
179             break;
180         case EXTRACT:
181             rval=extract_ldat(ldatfile,argc-optind,argv+optind);
182             break;
183     }
184 
185     return rval;
186 }
187 
188