1 #ifndef _GNU_SOURCE
2 #define _GNU_SOURCE
3 #endif
4 
5 #include <sys/types.h>
6 #include <errno.h>
7 #include <stdio.h>
8 #include <dirent.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
11 #include <sys/mman.h>
12 #include <sys/time.h>
13 #include <ctype.h>
14 
15 #include "../linux/glob.h"
16 
17 #include "../qcommon/qcommon.h"
18 
19 #ifndef __linux__
20 #include <machine/param.h>
21 #endif
22 
23 //===============================================================================
24 
25 byte *membase;
26 int maxhunksize;
27 int curhunksize;
28 
29 #ifdef __FreeBSD__
30 #define MMAP_ANON MAP_ANON
31 #else
32 #define MMAP_ANON MAP_ANONYMOUS
33 #endif
34 
Hunk_Begin(int maxsize,int precommit)35 void *Hunk_Begin (int maxsize, int precommit)
36 {
37 	// reserve a huge chunk of memory, but don't commit any yet
38 	maxhunksize = maxsize + sizeof(int);
39 	curhunksize = 0;
40 	membase = mmap(0, maxhunksize, PROT_READ|PROT_WRITE,
41 		MAP_PRIVATE|MMAP_ANON, -1, 0);
42 	if (membase == NULL || membase == (byte *)-1)
43 		Sys_Error("unable to virtual allocate %d bytes", maxsize);
44 
45 	*((int *)membase) = curhunksize;
46 
47 	return membase + sizeof(int);
48 }
49 
Hunk_Alloc(int size)50 void *Hunk_Alloc (int size)
51 {
52 	byte *buf;
53 
54 	// round to cacheline
55 	size = (size+31)&~31;
56 	if (curhunksize + size > maxhunksize)
57 		Sys_Error("Hunk_Alloc overflow");
58 	buf = membase + sizeof(int) + curhunksize;
59 	curhunksize += size;
60 	return buf;
61 }
62 
Hunk_End(void)63 int Hunk_End (void)
64 {
65 	byte *n;
66 
67 #ifndef __linux__
68 	size_t old_size = maxhunksize;
69 	size_t new_size = curhunksize + sizeof(int);
70 	void * unmap_base;
71 	size_t unmap_len;
72 
73 	new_size = round_page(new_size);
74 	old_size = round_page(old_size);
75 	if (new_size > old_size)
76 		n = 0; /* error */
77 	else if (new_size < old_size) {
78 		unmap_base = (caddr_t)(membase + new_size);
79 		unmap_len = old_size - new_size;
80 		n = munmap(unmap_base, unmap_len) + membase;
81 	}
82 #else
83 	n = mremap(membase, maxhunksize, curhunksize + sizeof(int), 0);
84 #endif
85 	if (n != membase)
86 		Sys_Error("Hunk_End:  Could not remap virtual block (%d)", errno);
87 	*((int *)membase) = curhunksize + sizeof(int);
88 
89 	return curhunksize;
90 }
91 
Hunk_Free(void * base)92 void Hunk_Free (void *base)
93 {
94 	byte *m;
95 
96 	if (base) {
97 		m = ((byte *)base) - sizeof(int);
98 		if (munmap(m, *((int *)m)))
99 			Sys_Error("Hunk_Free: munmap failed (%d)", errno);
100 	}
101 }
102 
103 //===============================================================================
104 
105 
106 /*
107 ================
108 Sys_Milliseconds
109 ================
110 */
111 unsigned int curtime;
Sys_Milliseconds(void)112 unsigned int Sys_Milliseconds (void)
113 {
114 	struct timeval tp;
115 	struct timezone tzp;
116 	static unsigned int		secbase;
117 
118 	gettimeofday(&tp, &tzp);
119 
120 	if (!secbase)
121 	{
122 		secbase = tp.tv_sec;
123 		return tp.tv_usec/1000;
124 	}
125 
126 	curtime = (tp.tv_sec - secbase)*1000 + tp.tv_usec/1000;
127 
128 	return curtime;
129 }
130 
Sys_DebugBreak(void)131 void Sys_DebugBreak (void)
132 {
133 #ifdef __i386__
134         __asm ("int $3");
135 #endif
136 }
137 
Sys_Mkdir(char * path)138 void Sys_Mkdir (char *path)
139 {
140     mkdir (path, 0755);
141 }
142 
strlwr(char * s)143 void strlwr (char *s)
144 {
145 	while (*s) {
146 		*s = tolower(*s);
147 		s++;
148 	}
149 }
150 
151 //============================================
152 
153 static	char	findbase[MAX_OSPATH];
154 static	char	findpath[MAX_OSPATH];
155 static	char	findpattern[MAX_OSPATH];
156 static	DIR		*fdir;
157 
CompareAttributes(char * path,char * name,unsigned musthave,unsigned canthave)158 static qboolean CompareAttributes(char *path, char *name,
159 	unsigned musthave, unsigned canthave )
160 {
161 	struct stat st;
162 	char fn[MAX_OSPATH];
163 
164 // . and .. never match
165 	if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0)
166 		return false;
167 
168 	sprintf(fn, "%s/%s", path, name);
169 	if (stat(fn, &st) == -1)
170 		return false; // shouldn't happen
171 
172 	if ( ( st.st_mode & S_IFDIR ) && ( canthave & SFF_SUBDIR ) )
173 		return false;
174 
175 	if ( ( musthave & SFF_SUBDIR ) && !( st.st_mode & S_IFDIR ) )
176 		return false;
177 
178 	return true;
179 }
180 
Sys_FindFirst(char * path,unsigned musthave,unsigned canhave)181 char *Sys_FindFirst (char *path, unsigned musthave, unsigned canhave)
182 {
183 	struct dirent *d;
184 	char *p;
185 
186 	if (fdir)
187 		Sys_Error ("Sys_BeginFind without close");
188 
189 //	COM_FilePath (path, findbase);
190 	strcpy(findbase, path);
191 
192 	if ((p = strrchr(findbase, '/')) != NULL) {
193 		*p = 0;
194 		strcpy(findpattern, p + 1);
195 	} else
196 		strcpy(findpattern, "*");
197 
198 	if (strcmp(findpattern, "*.*") == 0)
199 		strcpy(findpattern, "*");
200 
201 	if ((fdir = opendir(findbase)) == NULL)
202 		return NULL;
203 	while ((d = readdir(fdir)) != NULL) {
204 		if (!*findpattern || glob_match(findpattern, d->d_name)) {
205 //			if (*findpattern)
206 //				printf("%s matched %s\n", findpattern, d->d_name);
207 			if (CompareAttributes(findbase, d->d_name, musthave, canhave)) {
208 				sprintf (findpath, "%s/%s", findbase, d->d_name);
209 				return findpath;
210 			}
211 		}
212 	}
213 	return NULL;
214 }
215 
Sys_FindNext(unsigned musthave,unsigned canhave)216 char *Sys_FindNext (unsigned musthave, unsigned canhave)
217 {
218 	struct dirent *d;
219 
220 	if (fdir == NULL)
221 		return NULL;
222 	while ((d = readdir(fdir)) != NULL) {
223 		if (!*findpattern || glob_match(findpattern, d->d_name)) {
224 //			if (*findpattern)
225 //				printf("%s matched %s\n", findpattern, d->d_name);
226 			if (CompareAttributes(findbase, d->d_name, musthave, canhave)) {
227 				sprintf (findpath, "%s/%s", findbase, d->d_name);
228 				return findpath;
229 			}
230 		}
231 	}
232 	return NULL;
233 }
234 
Sys_FindClose(void)235 void Sys_FindClose (void)
236 {
237 	if (fdir != NULL)
238 		closedir(fdir);
239 	fdir = NULL;
240 }
241 
242 
243 //============================================
244 
245