]>
Commit | Line | Data |
---|---|---|
b0e82b74 CF |
1 | /* cygheap.h: Cygwin heap manager. |
2 | ||
85dde362 | 3 | Copyright 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. |
b0e82b74 CF |
4 | |
5 | This file is part of Cygwin. | |
6 | ||
7 | This software is a copyrighted work licensed under the terms of the | |
8 | Cygwin license. Please consult the file "CYGWIN_LICENSE" for | |
9 | details. */ | |
10 | ||
11 | #undef cfree | |
12 | ||
13 | enum cygheap_types | |
14 | { | |
15 | HEAP_FHANDLER, | |
16 | HEAP_STR, | |
17 | HEAP_ARGV, | |
e5648465 | 18 | HEAP_BUF, |
7ceb1cac | 19 | HEAP_MOUNT, |
c0a9bffd | 20 | HEAP_SIGS, |
8e10c431 | 21 | HEAP_ARCHETYPES, |
2d1d1eb1 | 22 | HEAP_TLS, |
e5648465 CF |
23 | HEAP_1_START, |
24 | HEAP_1_STR, | |
25 | HEAP_1_ARGV, | |
26 | HEAP_1_BUF, | |
8d82847a | 27 | HEAP_1_EXEC, |
5c6497b4 CF |
28 | HEAP_1_MAX = 100, |
29 | HEAP_MMAP = 200 | |
b0e82b74 CF |
30 | }; |
31 | ||
9fc09d00 | 32 | #define incygheap(s) (cygheap && ((char *) (s) >= (char *) cygheap) && ((char *) (s) <= ((char *) cygheap_max))) |
b0e82b74 | 33 | |
a4785603 CF |
34 | struct _cmalloc_entry |
35 | { | |
36 | union | |
37 | { | |
38 | DWORD b; | |
39 | char *ptr; | |
40 | }; | |
41 | struct _cmalloc_entry *prev; | |
42 | char data[0]; | |
43 | }; | |
44 | ||
7ceb1cac CF |
45 | struct cygheap_root_mount_info |
46 | { | |
95d02d5b | 47 | char posix_path[CYG_MAX_PATH]; |
7ceb1cac | 48 | unsigned posix_pathlen; |
95d02d5b | 49 | char native_path[CYG_MAX_PATH]; |
7ceb1cac CF |
50 | unsigned native_pathlen; |
51 | }; | |
52 | ||
ac5561f2 CF |
53 | /* CGF: FIXME This doesn't belong here */ |
54 | ||
1f0f8e12 CV |
55 | class cygheap_root |
56 | { | |
57 | /* Root directory information. | |
58 | This is used after a chroot is called. */ | |
7ceb1cac CF |
59 | struct cygheap_root_mount_info *m; |
60 | ||
1f0f8e12 | 61 | public: |
7ceb1cac CF |
62 | bool posix_ok (const char *path) |
63 | { | |
7ceb1cac CF |
64 | if (!m) |
65 | return 1; | |
66 | return path_prefix_p (m->posix_path, path, m->posix_pathlen); | |
67 | } | |
68 | bool ischroot_native (const char *path) | |
69 | { | |
70 | if (!m) | |
71 | return 1; | |
72 | return strncasematch (m->native_path, path, m->native_pathlen) | |
1ff9f4b9 | 73 | && (path[m->native_pathlen] == '\\' || !path[m->native_pathlen]); |
7ceb1cac CF |
74 | } |
75 | const char *unchroot (const char *path) | |
76 | { | |
77 | if (!m) | |
78 | return path; | |
79 | const char *p = path + m->posix_pathlen; | |
80 | if (!*p) | |
81 | p = "/"; | |
82 | return p; | |
83 | } | |
84 | bool exists () {return !!m;} | |
71af2ed3 | 85 | void set (const char *, const char *); |
7ceb1cac CF |
86 | size_t posix_length () const { return m->posix_pathlen; } |
87 | const char *posix_path () const { return m->posix_path; } | |
88 | size_t native_length () const { return m->native_pathlen; } | |
89 | const char *native_path () const { return m->native_path; } | |
1f0f8e12 CV |
90 | }; |
91 | ||
da086d02 CF |
92 | enum homebodies |
93 | { | |
94 | CH_HOMEDRIVE, | |
95 | CH_HOMEPATH, | |
96 | CH_HOME | |
97 | }; | |
98 | ||
a7cde2b9 CF |
99 | class cygheap_user |
100 | { | |
1f0f8e12 CV |
101 | /* Extendend user information. |
102 | The information is derived from the internal_getlogin call | |
103 | when on a NT system. */ | |
66c161ba CV |
104 | char *pname; /* user's name */ |
105 | char *plogsrv; /* Logon server, may be FQDN */ | |
106 | char *pdomain; /* Logon domain of the user */ | |
da086d02 CF |
107 | char *homedrive; /* User's home drive */ |
108 | char *homepath; /* User's home path */ | |
60cb120f | 109 | char *psystemroot; /* Value of SYSTEMROOT */ |
094d5193 | 110 | char *pwinname; /* User's name as far as Windows knows it */ |
179cae11 | 111 | char *puserprof; /* User profile */ |
6806a8b5 PH |
112 | cygsid effec_cygsid; /* buffer for user's SID */ |
113 | cygsid saved_cygsid; /* Remains intact even after impersonation */ | |
1f0f8e12 | 114 | public: |
1498189c CV |
115 | __uid32_t saved_uid; /* Remains intact even after impersonation */ |
116 | __gid32_t saved_gid; /* Ditto */ | |
a8d7ae61 | 117 | __uid32_t real_uid; /* Remains intact on seteuid, replaced by setuid */ |
57196405 | 118 | __gid32_t real_gid; /* Ditto */ |
5519d543 | 119 | user_groups groups; /* Primary and supp SIDs */ |
1f0f8e12 | 120 | |
66c161ba CV |
121 | /* token is needed if set(e)uid should be called. It can be set by a call |
122 | to `set_impersonation_token()'. */ | |
70249d56 CV |
123 | HANDLE external_token; |
124 | HANDLE internal_token; | |
ea3ba114 | 125 | HANDLE current_token; |
66c161ba | 126 | |
179cae11 CF |
127 | /* CGF 2002-06-27. I removed the initializaton from this constructor |
128 | since this class is always allocated statically. That means that everything | |
129 | is zero anyway so there is no need to initialize it to zero. Since the | |
130 | token initialization is always handled during process startup as well, | |
2e008fb9 | 131 | I've removed the constructor entirely. Please reinstate this if this |
179cae11 | 132 | situation ever changes. |
f7fa593d | 133 | cygheap_user () : pname (NULL), plogsrv (NULL), pdomain (NULL), |
1498189c | 134 | homedrive (NULL), homepath (NULL), |
179cae11 CF |
135 | token (INVALID_HANDLE_VALUE) {} |
136 | */ | |
137 | ||
1f0f8e12 CV |
138 | ~cygheap_user (); |
139 | ||
0efafbfb | 140 | void init (); |
1f0f8e12 CV |
141 | void set_name (const char *new_name); |
142 | const char *name () const { return pname; } | |
143 | ||
094d5193 CF |
144 | const char *env_logsrv (const char *, size_t); |
145 | const char *env_homepath (const char *, size_t); | |
146 | const char *env_homedrive (const char *, size_t); | |
147 | const char *env_userprofile (const char *, size_t); | |
148 | const char *env_domain (const char *, size_t); | |
149 | const char *env_name (const char *, size_t); | |
60cb120f | 150 | const char *env_systemroot (const char *, size_t); |
1f0f8e12 | 151 | |
094d5193 CF |
152 | const char *logsrv () |
153 | { | |
efc1575e CF |
154 | const char *p = env_logsrv ("LOGONSERVER=", sizeof ("LOGONSERVER=") - 1); |
155 | return (p == almost_null) ? NULL : p; | |
094d5193 CF |
156 | } |
157 | const char *winname () | |
158 | { | |
efc1575e CF |
159 | const char *p = env_name ("USERNAME=", sizeof ("USERNAME=") - 1); |
160 | return (p == almost_null) ? NULL : p; | |
094d5193 CF |
161 | } |
162 | const char *domain () | |
163 | { | |
efc1575e CF |
164 | const char *p = env_domain ("USERDOMAIN=", sizeof ("USERDOMAIN=") - 1); |
165 | return (p == almost_null) ? NULL : p; | |
094d5193 | 166 | } |
6806a8b5 PH |
167 | BOOL set_sid (PSID new_sid) {return (BOOL) (effec_cygsid = new_sid);} |
168 | BOOL set_saved_sid () { return (BOOL) (saved_cygsid = effec_cygsid); } | |
169 | PSID sid () { return effec_cygsid; } | |
170 | PSID saved_sid () { return saved_cygsid; } | |
da086d02 | 171 | const char *ontherange (homebodies what, struct passwd * = NULL); |
53197923 PH |
172 | #define NO_IMPERSONATION NULL |
173 | bool issetuid () const { return current_token != NO_IMPERSONATION; } | |
ea3ba114 | 174 | HANDLE token () { return current_token; } |
70249d56 CV |
175 | void deimpersonate () |
176 | { | |
ea3ba114 | 177 | if (issetuid ()) |
70249d56 CV |
178 | RevertToSelf (); |
179 | } | |
180 | void reimpersonate () | |
181 | { | |
ea3ba114 | 182 | if (issetuid () |
70249d56 CV |
183 | && !ImpersonateLoggedOnUser (token ())) |
184 | system_printf ("ImpersonateLoggedOnUser: %E"); | |
185 | } | |
ea3ba114 | 186 | bool has_impersonation_tokens () |
53197923 PH |
187 | { return external_token != NO_IMPERSONATION |
188 | || internal_token != NO_IMPERSONATION | |
189 | || current_token != NO_IMPERSONATION; } | |
70249d56 CV |
190 | void close_impersonation_tokens () |
191 | { | |
53197923 | 192 | if (current_token != NO_IMPERSONATION) |
ea3ba114 CV |
193 | { |
194 | if( current_token != external_token && current_token != internal_token) | |
195 | CloseHandle (current_token); | |
53197923 | 196 | current_token = NO_IMPERSONATION; |
ea3ba114 | 197 | } |
53197923 | 198 | if (external_token != NO_IMPERSONATION) |
70249d56 CV |
199 | { |
200 | CloseHandle (external_token); | |
53197923 | 201 | external_token = NO_IMPERSONATION; |
70249d56 | 202 | } |
53197923 | 203 | if (internal_token != NO_IMPERSONATION) |
70249d56 CV |
204 | { |
205 | CloseHandle (internal_token); | |
53197923 | 206 | internal_token = NO_IMPERSONATION; |
70249d56 | 207 | } |
e40670ee | 208 | } |
094d5193 CF |
209 | const char *cygheap_user::test_uid (char *&, const char *, size_t) |
210 | __attribute__ ((regparm (3))); | |
1f0f8e12 | 211 | }; |
a4785603 | 212 | |
431ba7dd CF |
213 | /* cwd cache stuff. */ |
214 | ||
215 | class muto; | |
216 | ||
217 | struct cwdstuff | |
218 | { | |
219 | char *posix; | |
220 | char *win32; | |
221 | DWORD hash; | |
a4563209 | 222 | DWORD drive_length; |
083abe54 | 223 | muto *cwd_lock; |
71af2ed3 | 224 | char *get (char *, int = 1, int = 0, unsigned = CYG_MAX_PATH); |
431ba7dd | 225 | DWORD get_hash (); |
a4563209 PH |
226 | DWORD get_drive (char * dst) |
227 | { | |
228 | get_initial (); | |
229 | memcpy (dst, win32, drive_length); | |
230 | return drive_length; | |
231 | } | |
431ba7dd | 232 | void init (); |
71af2ed3 | 233 | void fixup_after_exec (char *, char *, DWORD); |
431ba7dd | 234 | bool get_initial (); |
71af2ed3 | 235 | int set (const char *, const char *, bool); |
431ba7dd CF |
236 | }; |
237 | ||
0301bfd0 CF |
238 | #ifdef DEBUGGING |
239 | struct cygheap_debug | |
240 | { | |
241 | handle_list starth; | |
242 | handle_list *endh; | |
243 | handle_list freeh[500]; | |
244 | }; | |
245 | #endif | |
246 | ||
1cc651ec CF |
247 | struct user_heap_info |
248 | { | |
249 | void *base; | |
250 | void *ptr; | |
251 | void *top; | |
897c6b52 | 252 | void *max; |
1cc651ec CF |
253 | unsigned chunk; |
254 | }; | |
255 | ||
a4785603 CF |
256 | struct init_cygheap |
257 | { | |
258 | _cmalloc_entry *chain; | |
4ce15a49 | 259 | char *buckets[32]; |
1f0f8e12 CV |
260 | cygheap_root root; |
261 | cygheap_user user; | |
1cc651ec | 262 | user_heap_info user_heap; |
a4785603 | 263 | mode_t umask; |
2a6fc028 CF |
264 | HANDLE shared_h; |
265 | HANDLE console_h; | |
191ea07a | 266 | HANDLE mt_h; |
a9f20457 | 267 | char *cygwin_regname; |
431ba7dd | 268 | cwdstuff cwd; |
0381fec6 | 269 | dtable fdtab; |
6c2b7846 | 270 | const char *shared_prefix; |
0301bfd0 CF |
271 | #ifdef DEBUGGING |
272 | cygheap_debug debug; | |
273 | #endif | |
c0a9bffd | 274 | struct sigaction *sigs; |
2e008fb9 | 275 | |
8e10c431 | 276 | fhandler_tty_slave *ctty; /* Current tty */ |
f7239090 | 277 | #ifdef NEWVFORK |
e80cbe3e | 278 | fhandler_tty_slave *ctty_on_hold; |
f7239090 | 279 | #endif |
e431827c | 280 | struct _cygtls **threadlist; |
2d1d1eb1 | 281 | size_t sthreads; |
8ed5c9b6 | 282 | int open_fhs; |
d584454c | 283 | pid_t pid; /* my pid */ |
2d1d1eb1 | 284 | void close_ctty (); |
a4785603 CF |
285 | }; |
286 | ||
0cb38eb5 | 287 | #define _CYGHEAPSIZE_SLOP (128 * 1024) |
d8f87fba CF |
288 | #define CYGHEAPSIZE (sizeof (init_cygheap) + (20000 * sizeof (fhandler_union)) + _CYGHEAPSIZE_SLOP) |
289 | #define CYGHEAPSIZE_MIN (sizeof (init_cygheap) + (10000 * sizeof (fhandler_union))) | |
0381fec6 | 290 | |
a4785603 CF |
291 | extern init_cygheap *cygheap; |
292 | extern void *cygheap_max; | |
293 | ||
df63bd49 CF |
294 | class cygheap_fdmanip |
295 | { | |
296 | protected: | |
297 | int fd; | |
298 | fhandler_base **fh; | |
299 | bool locked; | |
300 | public: | |
6ea0c04e | 301 | cygheap_fdmanip (): fh (NULL) {} |
df63bd49 CF |
302 | virtual ~cygheap_fdmanip () |
303 | { | |
304 | if (locked) | |
2d1d1eb1 | 305 | cygheap->fdtab.unlock (); |
df63bd49 CF |
306 | } |
307 | void release () | |
308 | { | |
309 | cygheap->fdtab.release (fd); | |
310 | } | |
311 | operator int &() {return fd;} | |
312 | operator fhandler_base* &() {return *fh;} | |
7ac61736 | 313 | operator fhandler_socket* () const {return reinterpret_cast<fhandler_socket *> (*fh);} |
df63bd49 CF |
314 | void operator = (fhandler_base *fh) {*this->fh = fh;} |
315 | fhandler_base *operator -> () const {return *fh;} | |
53f00290 CF |
316 | bool isopen () const |
317 | { | |
318 | if (*fh) | |
319 | return true; | |
320 | set_errno (EBADF); | |
321 | return false; | |
322 | } | |
df63bd49 CF |
323 | }; |
324 | ||
325 | class cygheap_fdnew : public cygheap_fdmanip | |
326 | { | |
327 | public: | |
328 | cygheap_fdnew (int seed_fd = -1, bool lockit = true) | |
329 | { | |
330 | if (lockit) | |
2d1d1eb1 | 331 | cygheap->fdtab.lock (); |
df63bd49 CF |
332 | if (seed_fd < 0) |
333 | fd = cygheap->fdtab.find_unused_handle (); | |
334 | else | |
335 | fd = cygheap->fdtab.find_unused_handle (seed_fd + 1); | |
336 | if (fd >= 0) | |
337 | { | |
338 | locked = lockit; | |
339 | fh = cygheap->fdtab + fd; | |
340 | } | |
341 | else | |
342 | { | |
343 | set_errno (EMFILE); | |
344 | if (lockit) | |
2d1d1eb1 | 345 | cygheap->fdtab.unlock (); |
df63bd49 CF |
346 | locked = false; |
347 | } | |
348 | } | |
7903ee69 | 349 | void operator = (fhandler_base *fh) {*this->fh = fh;} |
df63bd49 CF |
350 | }; |
351 | ||
352 | class cygheap_fdget : public cygheap_fdmanip | |
353 | { | |
354 | public: | |
0f4db8cb | 355 | cygheap_fdget (int fd, bool lockit = false, bool do_set_errno = true) |
df63bd49 CF |
356 | { |
357 | if (lockit) | |
2d1d1eb1 | 358 | cygheap->fdtab.lock (); |
df63bd49 CF |
359 | if (fd >= 0 && fd < (int) cygheap->fdtab.size |
360 | && *(fh = cygheap->fdtab + fd) != NULL) | |
361 | { | |
362 | this->fd = fd; | |
363 | locked = lockit; | |
364 | } | |
365 | else | |
366 | { | |
367 | this->fd = -1; | |
0f4db8cb | 368 | if (do_set_errno) |
2ac3bab6 | 369 | set_errno (EBADF); |
df63bd49 | 370 | if (lockit) |
2d1d1eb1 | 371 | cygheap->fdtab.unlock (); |
df63bd49 CF |
372 | locked = false; |
373 | } | |
374 | } | |
375 | }; | |
376 | ||
5457dfcb | 377 | class child_info; |
e2e07827 CF |
378 | void *__stdcall cygheap_setup_for_child (child_info *ci, bool dup_later) __attribute__ ((regparm(2))); |
379 | void __stdcall cygheap_setup_for_child_cleanup (void *, child_info *, bool) __attribute__ ((regparm(3))); | |
6ea3e429 | 380 | void __stdcall cygheap_fixup_in_child (bool); |
b0e82b74 | 381 | extern "C" { |
166b2571 | 382 | void __stdcall cfree (void *) __attribute__ ((regparm(1))); |
166b2571 CF |
383 | void *__stdcall cmalloc (cygheap_types, DWORD) __attribute__ ((regparm(2))); |
384 | void *__stdcall crealloc (void *, DWORD) __attribute__ ((regparm(2))); | |
385 | void *__stdcall ccalloc (cygheap_types, DWORD, DWORD) __attribute__ ((regparm(3))); | |
386 | char *__stdcall cstrdup (const char *) __attribute__ ((regparm(1))); | |
387 | char *__stdcall cstrdup1 (const char *) __attribute__ ((regparm(1))); | |
179cae11 | 388 | void __stdcall cfree_and_set (char *&, char * = NULL) __attribute__ ((regparm(2))); |
9fc09d00 | 389 | void __stdcall cygheap_init (); |
6d8bd861 | 390 | extern DWORD _cygheap_start; |
1ed8d187 | 391 | } |