f26052d0688b4c0b64ee845fc6735a44e7bb41e3
[fp-git.git] / PR / src / lib / layers / disk.c
1 /*  Princed V3 - Prince of Persia Level Editor for PC Version
2     Copyright (C) 2003 Princed Development Team
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
18     The authors of this program may be contacted at http://forum.princed.com.ar
19 */
20
21 /*
22 disk.c: Princed Resources : Disk Access & File handling functions
23 ¯¯¯¯¯¯
24  Copyright 2003 Princed Development Team
25   Created: 29 Oct 2003
26
27   Author: Enrique Calot <ecalot.cod@princed.com.ar>
28   Version: 1.00 (2003-Oct-29)
29
30   Modified by: Enrique Calot <ecalot.cod@princed.com.ar>
31   Version: 1.10 (2003-Dec-03)
32
33  Note:
34   DO NOT remove this copyright notice
35 */
36
37 //Defines
38 #include "memory.h"
39 #include <string.h>
40 #include "pr.h"
41 #include "disk.h"
42 #include "xml.h" /* equalsIgnoreCase */
43
44 #include <sys/types.h>
45 #include <sys/stat.h>
46
47 #ifdef UNIX
48         #define defmkdir(a) mkdir (a,(mode_t)0755)
49         #include <dirent.h>
50 #else
51         #include <direct.h>
52         #include "direntwin.h"
53         #define defmkdir(a) mkdir (a)
54 #endif
55
56 #define isDirSep(a,i) ((a[i]=='\\')||(a[i]=='/'))
57
58 /***************************************************************\
59 |              Disk Access & File handling functions            |
60 \***************************************************************/
61
62 //Repair folders
63 const char *repairFolders(const char* a) {
64         int i,k;
65         static char result[260];
66
67         for (i=0,k=0;a[i]&&(k<260);) {
68                 if (isDirSep(a,i)) {
69                         result[k]=DIR_SEPARATOR;
70                         i++;
71                         while (isDirSep(a,i)) i++;
72                 } else {
73                         result[k]=a[i];
74                         i++;
75                 }
76                 k++;
77         }
78         result[k]=0;
79         return result;
80 }
81
82
83 //Create base directory of a file
84 int makebase(const char* p) {
85         /*
86                 Creates the base directory of the given file "p"
87                 Returns 0 if created
88                 Returns -1 if an error occurred
89
90                 Note: if the base dir already exists it will return -1!
91         */
92
93         //Declare variables
94         int i,a;
95         int size;
96         char* aux;
97
98         //Initialize variables
99         aux=(char*)malloc(size=(strlen(p)+1));
100         memset(aux,0,size);
101
102         //Make directories
103         for (i=0;i<size;i++) {
104                 if (p[i]==DIR_SEPARATOR) a=defmkdir(aux);
105                 aux[i]=p[i];
106         }
107         free(aux);
108
109         return a;
110 }
111
112 char writeOpen(const char* vFileext, FILE* *fp) {
113         /*
114                 Opens vFileext for write access
115                  if the path does't exist it is created
116                  if the file doesn't exist it is created
117                  if the file does exist it is overwriten
118
119                 Sets the file pointer and returns 1 if Ok or 0 if error
120
121                 Returns
122                  0 if error
123                  1 if ok
124         */
125         const char* file;
126
127         //Create base dir and save file
128         file=repairFolders(vFileext);
129         makebase(file);
130
131         return ((*fp=fopen(file,"wb"))!=NULL);
132 }
133
134
135 char writeData(const unsigned char* data, int ignoreChars, char* vFileext, int size) {
136         /*
137                 Creates vFileext and saves data in it. In case the directory doesn't
138                 exist it will be created.
139
140                 Data is read from ignoreChars to size.
141                 Example:
142                         if data="123456789", ignoreChars=3, size=8
143                         saved file will contain "45678"
144
145                 Returns
146                  0 if error
147                  1 if ok
148         */
149
150         //Declare variables
151         FILE* target;
152         char  ok;
153
154         //Verify parameters
155         size-=ignoreChars;
156         if (size<=0) return 0;
157
158         //Save file
159         ok=writeOpen(vFileext,&target);
160         ok=ok&&fwrite(data+ignoreChars,size,1,target);
161         ok=ok&&(!fclose(target));
162         return ok;
163 }
164
165 int mLoadFileArray(const char* vFile,unsigned char** array) {
166         /*
167                 Using the string in vFile, it opens the file and returns the
168                 number of bytes in it and the content of the file in array.
169                 In case the file couldn't be open or memory allocated returns 0.
170         */
171
172         //declare variables
173         FILE *fp;
174         int  aux;
175
176         //Open the file
177         if ((fp=fopen(repairFolders(vFile),"rb"))==NULL) {
178                 return 0;
179         } else {
180                 //get file size
181                 fseek(fp,0,SEEK_END);
182                 aux=ftell(fp);
183                 if ( !aux || (aux>SIZE_OF_FILE) || ( ((*array=(unsigned char*)malloc(sizeof(char)*aux))==NULL) ) ) {
184                         //if the file was null or bigger than the max size or couldn't allocate the file in memory
185                         fclose(fp);
186                         return 0;
187                 } else {
188                         //if the filewas succesfully open
189                         fseek(fp,0,SEEK_SET);
190                         aux=fread (*array,1,aux,fp);
191                         fclose(fp);
192                         return aux;
193                 }
194         }
195 }
196
197 #define mSaveRaw(f,d,s) writeData(d,0,f,s)
198 /*
199 char mSaveRaw(const char* vFile,const unsigned char* output, int size) {
200         /*
201                 Using the given string in vFile, it opens the file and saves the
202                 first "size" bytes from the "output" in it.
203                 In case the file couldn't be open or there was no size returns 0,
204                 otherways returns 1.
205         /
206
207   FILE * pFile;
208
209         if (!size) return 0;
210   if (!writeOpen(vFile,&pFile)) return 0;
211
212   fwrite (output, 1, size, pFile);
213   fclose (pFile);
214   return 1;
215 }
216 */
217
218 char mDiskVealidateFileHeader(unsigned char* text, int size, FILE* fp) {
219         /*
220                 Validates if the file contains the following text in the stream.
221                 1 if it does
222                 0 if error or doesn't
223
224                 Moves the file pointer to the next position
225         */
226
227         //Declare vars
228         int i;
229         unsigned char* readText;
230
231         //Reserves memory to allocate the read bytes
232         readText=getMemory(size);
233         if (readText==NULL) return 0; //memory error, abort
234
235         //Read the file and move the file pointer
236         if (!fread(readText,size,1,fp)) {
237                 free(readText);
238                 return 0;
239         }
240
241         //Make the binary compare
242         for (i=0;(i<size)&&(readText[i]==text[i]);i++);
243
244         //Frees memory and returns the result
245         free(readText);
246         return (i==size); //0 if the compare for was stopped before end reached
247 }
248
249 const char* getFileNameFromPath(const char* path) {
250         /*
251                 If you give a path you get the filename,
252                 if you give a filename, you get the same filename
253         */
254         int size;
255         size=strlen(path);
256         while (size) {
257                 if (isDirSep(path,size)) {
258                         return path+size+1;
259                 }
260                 size--;
261         }
262         return path;
263 }
264
265 whatIs isDir(const char *path) {
266         /*
267                 1 if nombre is a directory
268                 0 if nombre isn't a directory or doesn't exist
269         */
270         struct stat buf;
271
272         if(stat(path,&buf)==-1) return eNotFound;
273         return (S_IFDIR&buf.st_mode)?eDirectory:eFile;
274 }
275
276 int recurseDirectory(const char* path,int* pOption, const char* extension,const char* dirName,const char* resFile, const char* datfilename,const char* datAuthor,FILE* output) {
277         /*
278                 Searchs for all .dat files in the directory
279                 if recursive flag is set searchs over the dubdirectories
280                 if verbose flag is set shows some messages in the screen
281                 when .dat files are found it runs prMain form each of them
282         */
283
284         //Declare variables
285         char*          recursive;
286         struct dirent* directoryStructure;
287         DIR*           dir;
288
289         //Opens directory
290         if ((dir = opendir(path))==NULL) {
291                 return 0;
292         }
293
294         //Shows some messages
295         if ((optionflag&recursive_flag)&&(optionflag&verbose_flag)) { //Only recurse if recursive and verbose flags are set
296                 printf("Processing '%s'...\n",path);
297         }
298
299         //Main cicle: while there are still more files left
300         while ((directoryStructure = readdir(dir))!=NULL) {
301                 if /* Don't look over the system directories */
302                         (!(
303                                 !strcmp(directoryStructure->d_name,".")||
304                                 !strcmp(directoryStructure->d_name,"..")
305                 )) {
306                         //Declare variables
307                         int sizeOfPath=strlen(path);
308                         int sizeOfFile=strlen(directoryStructure->d_name);
309
310                         //Generate recursive path
311                         recursive=getMemory(sizeOfPath+1+sizeOfFile);
312                         memcpy(recursive,path,sizeOfPath);
313                         recursive[sizeOfPath]=DIR_SEPARATOR;
314                         memcpy(recursive+sizeOfPath+1,directoryStructure->d_name,sizeOfFile+1);
315
316                         /*
317                                 If recursive path is a directory and recursive flag is set recurse into it
318                                 if recursive path is a directory and recursive flag wasn't set, just ignore
319                                 if recursive path is not a directory and is a dat file, do prMain
320                                 if recursive path is not a directory and is not a dat file, ignore
321                         */
322                         if (isDir(recursive)==eDirectory) {
323                                 if (optionflag&recursive_flag) { //Only recurse if recursive flag is set
324                                         recurseDirectory(recursive,pOption,extension,dirName,resFile,datfilename,datAuthor,output);
325                                 }
326                         } else {
327                                 char aux[]=".dat";
328                                 if (sizeOfFile>4) {
329                                         if (equalsIgnoreCase(aux,directoryStructure->d_name+sizeOfFile-4)) {
330                                                 prMain(pOption,extension,dirName,resFile,recursive,directoryStructure->d_name,datAuthor,output);
331                                         }
332                                 }
333                         }
334                         //Free all allocated mem
335                         free(recursive);
336                 }
337         }
338         return 1;
339 }