5f37538db6fa5458521dcb4d265946d74bf9ead0
[xonotic/netradiant.git] / radiant / missing.cpp
1 /*
2 Copyright (c) 2001, Loki software, inc.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, 
6 are permitted provided that the following conditions are met:
7
8 Redistributions of source code must retain the above copyright notice, this list 
9 of conditions and the following disclaimer.
10
11 Redistributions in binary form must reproduce the above copyright notice, this
12 list of conditions and the following disclaimer in the documentation and/or
13 other materials provided with the distribution.
14
15 Neither the name of Loki software nor the names of its contributors may be used 
16 to endorse or promote products derived from this software without specific prior 
17 written permission. 
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
22 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
23 DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
29 */
30
31 //
32 // Missing functions
33 //
34 // Leonardo Zide (leo@lokigames.com)
35 //
36
37 #include "missing.h"
38 #include "qsysprintf.h"
39
40 #if defined (__linux__) || defined (__APPLE__)
41
42 #include <stdio.h>
43 #include <unistd.h>
44 #include <sys/time.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <stdlib.h>
48 #include <dirent.h>
49
50 bool radCopyFile(const char *lpExistingFileName, const char *lpNewFileName)
51 {
52   FILE *src, *dst;
53   void* buf;
54   int l;
55   bool ret = false;
56   char realsrc[PATH_MAX], realdest[PATH_MAX];
57
58   realpath (lpExistingFileName, realsrc);
59   realpath (lpNewFileName, realdest);
60
61   src = fopen (realsrc, "rb");
62   if ( !src ) {
63     return false;
64   }
65   dst = fopen (realdest, "wb");
66   if (!dst) {
67     fclose (src);
68     return false;
69   }
70  
71   fseek (src, 0, SEEK_END);
72   l = ftell (src);
73   rewind (src);
74   buf = g_malloc (l);
75
76   if (buf != NULL)
77     if (fread (buf, l, 1, src) == 1)
78       if (fwrite (buf, l, 1, dst) == 1)
79         ret = true;
80
81   g_free (buf);
82   fclose (src);
83   fclose (dst);
84
85   return ret;
86 }
87
88 bool radCreateDirectory( const char *directory ) {
89         if ( mkdir( directory, 0777 ) == -1 ) {
90                 Sys_Printf( "mkdir %s failed\n", directory );
91                 return false;
92         }
93         return true;
94 }
95
96 int GetFullPathName(const char *lpFileName, int nBufferLength, char *lpBuffer, char **lpFilePart)
97 {
98   if (lpFileName[0] == '/')
99   {
100     strcpy (lpBuffer, lpFileName);
101     *lpFilePart = strrchr (lpBuffer, '/');
102     return strlen (lpBuffer);
103   }
104
105   if (getcwd (lpBuffer, nBufferLength) == NULL)
106     return 0;
107
108   strcat (lpBuffer, "/");
109   *lpFilePart = lpBuffer + strlen (lpBuffer);
110   strcat (lpBuffer, lpFileName);
111
112   char *scr = lpBuffer, *dst = lpBuffer;
113   for (int i = 0; (i < nBufferLength) && (*scr != 0); i++)
114   {
115     if (*scr == '/' && *(scr+1) == '.' && *(scr+2) == '.')
116     {
117       scr += 4;
118       while (dst != lpBuffer && *dst != '/')
119       {
120         dst--;
121         i--;
122       }
123     }
124
125     *dst = *scr;
126
127     scr++; dst++;
128   }
129   *dst = 0;
130
131   return strlen (lpBuffer);
132 }
133
134 EPathCheck CheckFile( const char *path ) {
135         struct stat             sbuf;
136         if ( stat( path, &sbuf ) == -1 ) {
137                 return PATH_FAIL;
138         }
139         if ( S_ISDIR( sbuf.st_mode ) ) {
140                 return PATH_DIRECTORY;
141         }
142         return PATH_FILE;
143 }
144
145 #else
146
147 FindFiles::FindFiles( const char *_directory ) {
148         directory = _directory;
149         findHandle = INVALID_HANDLE_VALUE;
150 }
151
152 FindFiles::~FindFiles() {
153         if ( findHandle != NULL ) {
154                 FindClose( findHandle );
155         }
156 }
157
158 const char* FindFiles::NextFile() {
159         if ( findHandle == INVALID_HANDLE_VALUE ) {
160                 findHandle = FindFirstFile( directory.GetBuffer(), &findFileData );
161                 if ( findHandle == INVALID_HANDLE_VALUE ) {
162                         return NULL;
163                 }
164                 return findFileData.cFileName;
165         }
166         if ( FindNextFile( findHandle, &findFileData ) == 0 ) {
167                 FindClose( findHandle );
168                 return NULL;
169         }
170         return findFileData.cFileName;
171 }
172
173 EPathCheck CheckFile( const char *path ) {
174         struct _stat sbuf;
175         if ( _stat( path, &sbuf ) == -1 ) {
176                 return PATH_FAIL;
177         }
178         if ( ( sbuf.st_mode & _S_IFDIR ) != 0 ) {
179                 return PATH_DIRECTORY;
180         }
181         return PATH_FILE;
182 }
183
184 bool radCreateDirectory( const char *directory ) {
185         return CreateDirectory( directory, NULL );
186 }
187
188 bool radCopyFile( const char *lpExistingFileName, const char *lpNewFileName ) {
189         return CopyFile( lpExistingFileName, lpNewFileName, FALSE );
190 }
191
192 #endif
193
194 bool CopyTree( const char *source, const char *dest ) {
195         Str                             srcEntry;
196         Str                             dstEntry;
197         const char              *dirname;
198         FindFiles               fileScan( source );
199
200         while ( ( dirname = fileScan.NextFile() ) != NULL ) {
201                 if ( strcmp( dirname, "." ) == 0 || strcmp( dirname, ".." ) == 0 ) {
202                         continue;
203                 }
204                 if ( strcmp( dirname, ".svn" ) == 0 ) {
205                         continue;
206                 }
207                 srcEntry = source;
208                 srcEntry += "/";
209                 srcEntry += dirname;
210                 dstEntry = dest;
211                 dstEntry += "/";
212                 dstEntry += dirname;
213                 switch ( CheckFile( srcEntry.GetBuffer() ) ) {
214                         case PATH_DIRECTORY: {
215                                 if ( CheckFile( dstEntry.GetBuffer() ) == PATH_FAIL ) {
216                                         radCreateDirectory( dstEntry.GetBuffer() );
217                                 }
218                                 bool ret;
219                                 ret = CopyTree( srcEntry.GetBuffer(), dstEntry.GetBuffer() );
220                                 if ( !ret ) {
221                                         return false;
222                                 }
223                                 break;
224                         }
225                         case PATH_FILE: {
226                                 Sys_Printf( "copy %s -> %s\n", srcEntry.GetBuffer(), dstEntry.GetBuffer() );
227                                 bool ret = radCopyFile( srcEntry.GetBuffer(), dstEntry.GetBuffer() );
228                                 if ( !ret ) {
229                                         return false;
230                                 }
231                                 break;
232                         }
233                 }
234         }
235         return true;
236 }