]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - radiant/missing.cpp
error check and bail if permission denied during gamepack install
[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 #include "qe3.h"
40
41 #if defined ( __linux__ ) || defined ( __APPLE__ )
42
43 #include <stdio.h>
44 #include <unistd.h>
45 #include <sys/time.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <stdlib.h>
49 #include <dirent.h>
50
51 bool radCopyFile( const char *lpExistingFileName, const char *lpNewFileName, bool fatal_on_error ){
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       if ( fatal_on_error ) {
64         Error( "Failed to open source for copy: %s\n", realsrc );
65       }
66       Sys_Printf( "Failed to open source for copy: %s\n", realsrc );      
67       return false;
68         }
69         dst = fopen( realdest, "wb" );
70         if ( !dst ) {
71       if ( fatal_on_error ) {
72         Error( "Failed to open destination for copy: %s\n", realdest );
73       }
74       Sys_Printf( "Failed to open destination for copy: %s\n", realdest );
75       fclose( src );
76       return false;
77         }
78
79         fseek( src, 0, SEEK_END );
80         l = ftell( src );
81         rewind( src );
82         buf = g_malloc( l );
83
84         if ( buf != NULL ) {
85                 if ( fread( buf, l, 1, src ) == 1 ) {
86                         if ( fwrite( buf, l, 1, dst ) == 1 ) {
87                                 ret = true;
88                         }
89                 }
90         }
91         if ( !ret ) {
92       if ( fatal_on_error ) {
93         Error( "short read or short write while copying %s to %s\n", realsrc, realdest );
94       }
95       Sys_Printf( "short read or short write while copying %s to %s\n", realsrc, realdest );
96     }
97
98         g_free( buf );
99         fclose( src );
100         fclose( dst );
101
102         return ret;
103 }
104
105 bool radCreateDirectory( const char *directory, bool fatal_on_error ) {
106   if ( mkdir( directory, 0777 ) >= 0 ) {
107     return true;
108   }
109   if ( fatal_on_error ) {
110     Error( "mkdir %s failed - check your permissions", directory );
111   }
112   Sys_Printf( "mkdir %s failed - check your permissions\n", directory );
113   return false;
114 }
115
116 int GetFullPathName( const char *lpFileName, int nBufferLength, char *lpBuffer, char **lpFilePart ){
117         if ( lpFileName[0] == '/' ) {
118                 strcpy( lpBuffer, lpFileName );
119                 *lpFilePart = strrchr( lpBuffer, '/' );
120                 return strlen( lpBuffer );
121         }
122
123         if ( getcwd( lpBuffer, nBufferLength ) == NULL ) {
124                 return 0;
125         }
126
127         strcat( lpBuffer, "/" );
128         *lpFilePart = lpBuffer + strlen( lpBuffer );
129         strcat( lpBuffer, lpFileName );
130
131         char *scr = lpBuffer, *dst = lpBuffer;
132         for ( int i = 0; ( i < nBufferLength ) && ( *scr != 0 ); i++ )
133         {
134                 if ( *scr == '/' && *( scr + 1 ) == '.' && *( scr + 2 ) == '.' ) {
135                         scr += 4;
136                         while ( dst != lpBuffer && *dst != '/' )
137                         {
138                                 dst--;
139                                 i--;
140                         }
141                 }
142
143                 *dst = *scr;
144
145                 scr++; dst++;
146         }
147         *dst = 0;
148
149         return strlen( lpBuffer );
150 }
151
152 EPathCheck CheckFile( const char *path ) {
153         struct stat sbuf;
154         if ( stat( path, &sbuf ) == -1 ) {
155                 return PATH_FAIL;
156         }
157         if ( S_ISDIR( sbuf.st_mode ) ) {
158                 return PATH_DIRECTORY;
159         }
160         return PATH_FILE;
161 }
162
163 FindFiles::FindFiles( const char *_directory ) {
164         findHandle = opendir( _directory );
165 }
166
167 FindFiles::~FindFiles() {
168         if ( findHandle != NULL ) {
169                 closedir( findHandle );
170                 findHandle = NULL;
171         }
172 }
173
174 const char* FindFiles::NextFile() {
175         struct dirent *d;
176
177         if ( findHandle == NULL ) {
178                 return NULL;
179         }
180
181         d = readdir( findHandle );
182         if ( d ) {
183                 return d->d_name;
184         }
185         return NULL;
186 }
187
188 #else
189
190 FindFiles::FindFiles( const char *_directory ) {
191         char endChar;
192         directory = _directory;
193         if ( directory.GetLength() > 0 ) {
194                 endChar = directory.GetAt( directory.GetLength() - 1 );
195                 if ( !( endChar == '/' || endChar == '\\' ) ) {
196                         // We're only using '/' as the path separator throughout this code, not '\'.
197                         // However, I'd hate to see the code silently fail due to a trailing '\', so
198                         // I added the check for it.
199                         directory += '/';
200                 }
201         }
202         directory += '*';
203         findHandle = INVALID_HANDLE_VALUE;
204 }
205
206 FindFiles::~FindFiles() {
207         if ( findHandle != INVALID_HANDLE_VALUE ) {
208                 FindClose( findHandle );
209                 findHandle = INVALID_HANDLE_VALUE;
210         }
211 }
212
213 const char* FindFiles::NextFile() {
214         if ( findHandle == INVALID_HANDLE_VALUE ) {
215                 findHandle = FindFirstFile( directory.GetBuffer(), &findFileData );
216                 if ( findHandle == INVALID_HANDLE_VALUE ) {
217                         return NULL;
218                 }
219                 return findFileData.cFileName;
220         }
221         if ( FindNextFile( findHandle, &findFileData ) == 0 ) {
222                 FindClose( findHandle );
223                 findHandle = INVALID_HANDLE_VALUE;
224                 return NULL;
225         }
226         return findFileData.cFileName;
227 }
228
229 EPathCheck CheckFile( const char *path ) {
230         struct _stat sbuf;
231         if ( _stat( path, &sbuf ) == -1 ) {
232                 return PATH_FAIL;
233         }
234         if ( ( sbuf.st_mode & _S_IFDIR ) != 0 ) {
235                 return PATH_DIRECTORY;
236         }
237         return PATH_FILE;
238 }
239
240 bool radCreateDirectory( const char *directory, bool fatal_on_error ) {
241   if ( CreateDirectory( directory, NULL ) ) {
242     return true;
243   }
244   if ( fatal_on_error ) {
245     Error( "mkdir %s failed - check your permissions", directory );
246   }
247   Sys_Printf( "mkdir %s failed - check your permissions\n", directory );
248   return false;
249 }
250
251 bool radCopyFile( const char *lpExistingFileName, const char *lpNewFileName, bool fatal_on_error ) {
252   if ( CopyFile( lpExistingFileName, lpNewFileName, FALSE ) ) {
253     return true;
254   }
255   if ( fatal_on_error ) {
256     Error( "copy %s %s failed - check your permissions", lpExistingFileName, lpNewFileName );
257   }
258   Sys_Printf( "copy %s %s failed - check your permissions\n", lpExistingFileName, lpNewFileName );
259   return false;
260 }
261
262 #endif
263
264 bool radCopyTree( const char *source, const char *dest, bool fatal_on_error ) {
265         Str srcEntry;
266         Str dstEntry;
267         const char      *dirname;
268         FindFiles fileScan( source );
269
270         while ( ( dirname = fileScan.NextFile() ) != NULL ) {
271                 if ( strcmp( dirname, "." ) == 0 || strcmp( dirname, ".." ) == 0 ) {
272                         continue;
273                 }
274                 if ( strcmp( dirname, ".svn" ) == 0 ) {
275                         continue;
276                 }
277                 srcEntry = source;
278                 srcEntry += "/";
279                 srcEntry += dirname;
280                 dstEntry = dest;
281                 dstEntry += "/";
282                 dstEntry += dirname;
283                 switch ( CheckFile( srcEntry.GetBuffer() ) ) {
284         case PATH_FAIL: {
285           if ( fatal_on_error ) {
286             Error( "%s does not exist. check your permissions", srcEntry.GetBuffer() );
287           }
288         }
289                 case PATH_DIRECTORY: {
290                         if ( CheckFile( dstEntry.GetBuffer() ) == PATH_FAIL ) {
291               Sys_Printf( "Create directory %s\n", dstEntry.GetBuffer() );
292               if ( !radCreateDirectory( dstEntry.GetBuffer(), fatal_on_error ) ) {
293                                         return false;
294                                 }
295                         }
296                         bool ret;
297                         ret = radCopyTree( srcEntry.GetBuffer(), dstEntry.GetBuffer(), fatal_on_error );
298                         if ( !ret ) {
299                                 return false;
300                         }
301                         break;
302                 }
303                 case PATH_FILE: {
304                         Sys_Printf( "Copy %s -> %s\n", srcEntry.GetBuffer(), dstEntry.GetBuffer() );
305                         bool ret = radCopyFile( srcEntry.GetBuffer(), dstEntry.GetBuffer(), fatal_on_error );
306                         if ( !ret ) {
307                                 return false;
308                         }
309                         break;
310                 }
311                 }
312         }
313         return true;
314 }