]> icculus.org git repositories - taylor/freespace2.git/blob - src/platform/unix.cpp
recursively create directories (hurt more on OSX) and update all _mkdir() calls accor...
[taylor/freespace2.git] / src / platform / unix.cpp
1 #include <unistd.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <ctype.h>
7 #include <errno.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10
11 #include "pstypes.h"
12
13 // use system versions of this stuff in here rather than the vm_* versions
14 #undef malloc
15 #undef free
16 #undef strdup
17
18
19 #define MAX_LINE_WIDTH 128
20
21 void strlwr (char * str)
22 {
23         while (*str) {*str = tolower (*str); str++; }
24 }
25
26 void strupr (char * str)
27 {
28         while (*str) {*str = toupper (*str); str++; }
29 }
30
31 int filelength (int fd)
32 {
33         struct stat buf;
34         if (fstat (fd, &buf) == -1)
35                 return -1;
36                 
37         return buf.st_size;
38 }
39
40 unsigned long _beginthread (void (*pfuncStart)(void *), unsigned unStackSize, void* pArgList)
41 {
42         STUB_FUNCTION;
43         
44         return 0;
45 }
46
47 void Sleep (int mili)
48 {
49         SDL_Delay( long(mili) );
50 }
51
52 void OutputDebugString (const char *str)
53 {
54         fprintf(stderr, "OutputDebugString: %s\n", str);
55 }
56
57 int WSAGetLastError()
58 {
59         return errno;
60 }
61
62 // make specified directory, recursively
63 // NOTE: since this is for use with CFILE this code assumes that there will be a trailing '/'
64 //       or a trailing filename.  any directory name not followed by a '/' will be considered a file
65 int _mkdir(const char *path)
66 {
67         int status = 1;         // if we don't ever call mkdir() to update this then assume we are in error
68         char *c, tmp_path[MAX_PATH];
69
70         memset(tmp_path, 0, MAX_PATH);
71         strncpy(tmp_path, path, MAX_PATH-1);
72
73         c = &tmp_path[1];
74
75         while (c++) {
76                 c = strchr(c, '/');
77
78                 if (c) {
79                         *c = '\0';
80
81                         status = mkdir(tmp_path, 0700);
82
83 #ifndef NDEBUG
84                         int m_error = errno;
85
86                         if (status && (m_error != EEXIST) ) {
87                                 Warning(__FILE__, __LINE__, "Cannot mkdir %s: %s", tmp_path, strerror(m_error));
88                         }
89 #endif
90
91                         *c = '/';
92                 }
93         }
94
95         return status;
96 }
97
98 void _splitpath (const char *path, char *drive, char *dir, char *fname, char *ext)
99 {
100         if (path == NULL)
101                 return;
102
103         /* fs2 only uses fname */
104         if (fname != NULL) {
105                 const char *ls = strrchr(path, '/');
106                 if (ls != NULL) {
107                         ls++;           // move past '/'
108                 } else {
109                         ls = path;
110                 }
111         
112                 const char *lp = strrchr(path, '.');
113                 if (lp == NULL) {
114                         lp = ls + strlen(ls);   // move to the end
115                 }
116         
117                 int dist = lp-ls;
118                 if (dist > (_MAX_FNAME-1))
119                         dist = _MAX_FNAME-1;
120                 
121                 strncpy(fname, ls, dist);
122                 fname[dist] = 0;        // add null, just in case
123         }
124 }
125
126 int MulDiv(int a, int b, int c)
127 {
128         /* slow long long version */
129         __extension__ long long aa = a;
130         __extension__ long long bb = b;
131         __extension__ long long cc = c;
132         
133         __extension__ long long dd = aa * bb;
134         __extension__ long long ee = dd / cc;
135         
136         int retr = (int) ee;
137         
138         return retr;
139 }
140
141 /* mem debug junk */
142 #ifndef NDEBUG
143 //#define WANT_DEBUG
144 #endif
145
146 int TotalRam = 0;
147
148 #ifdef WANT_DEBUG
149 typedef struct RAM {
150         void *addr;
151         int size;
152         
153         char *file;
154         int line;
155         
156         RAM *next;
157 } RAM;
158
159 static RAM *RamTable;
160 #endif
161
162 #ifndef NDEBUG
163 void vm_free(void* ptr, char *file, int line)
164 #else
165 void vm_free(void* ptr)
166 #endif
167 {
168 #ifdef WANT_DEBUG
169         fprintf(stderr, "FREE: %s:%d addr = %p\n", file, line, ptr);
170         
171         RAM *item = RamTable;
172         RAM **mark = &RamTable;
173         
174         while (item != NULL) {
175                 if (item->addr == ptr) {
176                         RAM *tmp = item;
177                         
178                         *mark = item->next;
179                         
180                         free(tmp->addr);
181                         free(tmp);
182                         
183                         return;
184                 }
185                 
186                 mark = &(item->next);
187                 
188                 item = item->next;
189         }
190         
191         fprintf(stderr, "ERROR: vm_free caught invalid free: addr = %p, file = %s/%d\n", ptr, file, line);
192 #else   
193         free(ptr);
194 #endif
195 }
196
197 #ifndef NDEBUG
198 void *vm_malloc(int size, char *file, int line)
199 #else
200 void *vm_malloc(int size)
201 #endif
202 {
203 #ifdef WANT_DEBUG
204         fprintf(stderr, "MALLOC: %s:%d %d bytes\n", file, line, size);
205         
206         RAM *next = (RAM *)malloc(sizeof(RAM));
207         
208         next->addr = malloc(size);
209         next->size = size;
210         next->file = file;
211         next->line = line;
212         
213         next->next = RamTable;
214         RamTable = next;
215         
216         return next->addr;
217 #else
218         return malloc(size);
219 #endif  
220 }
221
222 #ifndef NDEBUG
223 char *vm_strdup(char const* str, char *file, int line)
224 #else
225 char *vm_strdup(char const* str)
226 #endif
227 {
228 #ifdef WANT_DEBUG
229         fprintf(stderr, "STRDUP: %s:%d\n", file, line);
230         
231         RAM *next = (RAM *)malloc(sizeof(RAM));
232         
233         next->addr = strdup(str);
234         next->size = strlen(str)+1;
235         next->file = file;
236         next->line = line;
237         
238         next->next = RamTable;
239         RamTable = next;
240         
241         return (char *)next->addr;
242 #else
243         return strdup(str);
244 #endif
245 }
246
247 void vm_dump()
248 {
249 #ifdef WANT_DEBUG
250         int i = 0;
251         int mem = 0;
252         fprintf(stderr, "\nDumping allocated memory:\n");
253         
254         RAM *ptr = RamTable;
255         while (ptr) {
256                 fprintf(stderr, "%d: file: %s:%d: addr:%p size:%d\n", i, ptr->file, ptr->line, ptr->addr, ptr->size);
257                 mem += ptr->size;
258                 ptr = ptr->next;
259                 i++;
260         }
261         
262         fprintf(stderr, "\nTotal of %d left-over bytes from %d allocations\n", mem, i);
263 #endif  
264 }
265
266 void windebug_memwatch_init()
267 {
268         TotalRam = 0;
269 }
270
271 /* error message debugging junk */
272 /*
273 int Log_debug_output_to_file = 0;
274
275 void load_filter_info(void)
276 {
277 //      STUB_FUNCTION;
278 }
279
280 void outwnd_printf(char* id, char* format, ...)
281 {
282         char tmp[MAX_LINE_WIDTH*4];
283         va_list args;
284
285         va_start (args, format);
286         vsprintf (tmp, format, args);
287         va_end(args);
288         fprintf (stderr, "%s: %s\n", id, tmp);
289 }
290
291 void outwnd_printf2(char* format, ...)
292 {
293         char tmp[MAX_LINE_WIDTH*4];
294         va_list args;
295
296         va_start (args, format);
297         vsprintf (tmp, format, args);
298         va_end(args);
299         fprintf (stderr, "General: %s", tmp);
300 }
301
302 void outwnd_close()
303 {
304 //      STUB_FUNCTION;
305 }
306 */
307 void Warning( char * filename, int line, char * format, ... )
308 {
309         char tmp[MAX_LINE_WIDTH*4];
310         va_list args;
311
312         va_start (args, format);
313         vsprintf (tmp, format, args);
314         va_end(args);
315         fprintf (stderr, "Warning: (%s:%d): %s\n", filename, line, tmp);
316 }
317
318 void Error( char * filename, int line, char * format, ... )
319 {
320         char tmp[MAX_LINE_WIDTH*4];
321         va_list args;
322
323         va_start (args, format);
324         vsprintf (tmp, format, args);
325         va_end(args);
326         fprintf (stderr, "Error: (%s:%d): %s\n", filename, line, tmp);
327         exit (1);
328 }
329
330 void WinAssert(char * text,char *filename, int line)
331 {
332         fprintf (stderr, "Assertion: (%s:%d) %s\n", filename, line, text);
333 //      exit(1);
334 }