]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/missing.cpp
Merge pull request #19 from merlin1991/scons-update
[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         FILE *src, *dst;
52         void* buf;
53         int l;
54         bool ret = false;
55         char realsrc[PATH_MAX], realdest[PATH_MAX];
56
57         realpath( lpExistingFileName, realsrc );
58         realpath( lpNewFileName, realdest );
59
60         src = fopen( realsrc, "rb" );
61         if ( !src ) {
62                 return false;
63         }
64         dst = fopen( realdest, "wb" );
65         if ( !dst ) {
66                 fclose( src );
67                 return false;
68         }
69
70         fseek( src, 0, SEEK_END );
71         l = ftell( src );
72         rewind( src );
73         buf = g_malloc( l );
74
75         if ( buf != NULL ) {
76                 if ( fread( buf, l, 1, src ) == 1 ) {
77                         if ( fwrite( buf, l, 1, dst ) == 1 ) {
78                                 ret = true;
79                         }
80                 }
81         }
82
83         g_free( buf );
84         fclose( src );
85         fclose( dst );
86
87         return ret;
88 }
89
90 bool radCreateDirectory( const char *directory ) {
91         if ( mkdir( directory, 0777 ) == -1 ) {
92                 Sys_Printf( "mkdir %s failed\n", directory );
93                 return false;
94         }
95         return true;
96 }
97
98 int GetFullPathName( const char *lpFileName, int nBufferLength, char *lpBuffer, char **lpFilePart ){
99         if ( lpFileName[0] == '/' ) {
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
109         strcat( lpBuffer, "/" );
110         *lpFilePart = lpBuffer + strlen( lpBuffer );
111         strcat( lpBuffer, lpFileName );
112
113         char *scr = lpBuffer, *dst = lpBuffer;
114         for ( int i = 0; ( i < nBufferLength ) && ( *scr != 0 ); i++ )
115         {
116                 if ( *scr == '/' && *( scr + 1 ) == '.' && *( scr + 2 ) == '.' ) {
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 FindFiles::FindFiles( const char *_directory ) {
146         findHandle = opendir( _directory );
147 }
148
149 FindFiles::~FindFiles() {
150         if ( findHandle != NULL ) {
151                 closedir( findHandle );
152                 findHandle = NULL;
153         }
154 }
155
156 const char* FindFiles::NextFile() {
157         struct dirent *d;
158
159         if ( findHandle == NULL ) {
160                 return NULL;
161         }
162
163         d = readdir( findHandle );
164         if ( d ) {
165                 return d->d_name;
166         }
167         return NULL;
168 }
169
170 #else
171
172 FindFiles::FindFiles( const char *_directory ) {
173         char endChar;
174         directory = _directory;
175         if ( directory.GetLength() > 0 ) {
176                 endChar = directory.GetAt( directory.GetLength() - 1 );
177                 if ( !( endChar == '/' || endChar == '\\' ) ) {
178                         // We're only using '/' as the path separator throughout this code, not '\'.
179                         // However, I'd hate to see the code silently fail due to a trailing '\', so
180                         // I added the check for it.
181                         directory += '/';
182                 }
183         }
184         directory += '*';
185         findHandle = INVALID_HANDLE_VALUE;
186 }
187
188 FindFiles::~FindFiles() {
189         if ( findHandle != INVALID_HANDLE_VALUE ) {
190                 FindClose( findHandle );
191                 findHandle = INVALID_HANDLE_VALUE;
192         }
193 }
194
195 const char* FindFiles::NextFile() {
196         if ( findHandle == INVALID_HANDLE_VALUE ) {
197                 findHandle = FindFirstFile( directory.GetBuffer(), &findFileData );
198                 if ( findHandle == INVALID_HANDLE_VALUE ) {
199                         return NULL;
200                 }
201                 return findFileData.cFileName;
202         }
203         if ( FindNextFile( findHandle, &findFileData ) == 0 ) {
204                 FindClose( findHandle );
205                 findHandle = INVALID_HANDLE_VALUE;
206                 return NULL;
207         }
208         return findFileData.cFileName;
209 }
210
211 EPathCheck CheckFile( const char *path ) {
212         struct _stat sbuf;
213         if ( _stat( path, &sbuf ) == -1 ) {
214                 return PATH_FAIL;
215         }
216         if ( ( sbuf.st_mode & _S_IFDIR ) != 0 ) {
217                 return PATH_DIRECTORY;
218         }
219         return PATH_FILE;
220 }
221
222 bool radCreateDirectory( const char *directory ) {
223         return ( CreateDirectory( directory, NULL ) != false );
224 }
225
226 bool radCopyFile( const char *lpExistingFileName, const char *lpNewFileName ) {
227         return ( CopyFile( lpExistingFileName, lpNewFileName, FALSE ) != false );
228 }
229
230 #endif
231
232 bool CopyTree( const char *source, const char *dest ) {
233         Str srcEntry;
234         Str dstEntry;
235         const char      *dirname;
236         FindFiles fileScan( source );
237
238         while ( ( dirname = fileScan.NextFile() ) != NULL ) {
239                 if ( strcmp( dirname, "." ) == 0 || strcmp( dirname, ".." ) == 0 ) {
240                         continue;
241                 }
242                 if ( strcmp( dirname, ".svn" ) == 0 ) {
243                         continue;
244                 }
245                 srcEntry = source;
246                 srcEntry += "/";
247                 srcEntry += dirname;
248                 dstEntry = dest;
249                 dstEntry += "/";
250                 dstEntry += dirname;
251                 switch ( CheckFile( srcEntry.GetBuffer() ) ) {
252                 case PATH_DIRECTORY: {
253                         if ( CheckFile( dstEntry.GetBuffer() ) == PATH_FAIL ) {
254                                 if ( !radCreateDirectory( dstEntry.GetBuffer() ) ) {
255                                         Sys_Printf( "create directory %s failed\n", dstEntry.GetBuffer() );
256                                         return false;
257                                 }
258                         }
259                         bool ret;
260                         ret = CopyTree( srcEntry.GetBuffer(), dstEntry.GetBuffer() );
261                         if ( !ret ) {
262                                 return false;
263                         }
264                         break;
265                 }
266                 case PATH_FILE: {
267                         Sys_Printf( "copy %s -> %s\n", srcEntry.GetBuffer(), dstEntry.GetBuffer() );
268                         bool ret = radCopyFile( srcEntry.GetBuffer(), dstEntry.GetBuffer() );
269                         if ( !ret ) {
270                                 return false;
271                         }
272                         break;
273                 }
274                 }
275         }
276         return true;
277 }