Cygwin: (mostly) drop NT4 and Samba < 3.0 support
[newlib-cygwin.git] / winsup / cygwin / local_includes / cygheap.h
blob9edd61c28abdda68a4e7139d752709d36682c8f2
1 /* cygheap.h: Cygwin heap manager.
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7 details. */
9 #include "clock.h"
10 #include "cygheap_malloc.h"
11 #include "pwdgrp.h"
13 #define incygheap(s) (cygheap && ((char *) (s) >= (char *) cygheap) && ((char *) (s) <= ((char *) cygheap_max)))
15 struct _cmalloc_entry
17 union
19 unsigned b;
20 char *ptr;
22 struct _cmalloc_entry *prev;
23 char data[0];
26 struct cygheap_root_mount_info
28 char posix_path[CYG_MAX_PATH];
29 unsigned posix_pathlen;
30 char native_path[CYG_MAX_PATH];
31 unsigned native_pathlen;
32 bool caseinsensitive;
35 /* CGF: FIXME This doesn't belong here */
37 class cygheap_root
39 /* Root directory information.
40 This is used after a chroot is called. */
41 struct cygheap_root_mount_info *m;
43 public:
44 bool posix_ok (const char *path)
46 if (!m)
47 return 1;
48 return path_prefix_p (m->posix_path, path, m->posix_pathlen,
49 m->caseinsensitive);
51 bool ischroot_native (const char *path)
53 if (!m)
54 return 1;
55 return strncasematch (m->native_path, path, m->native_pathlen)
56 && (path[m->native_pathlen] == '\\' || !path[m->native_pathlen]);
58 const char *unchroot (const char *path)
60 if (!m)
61 return path;
62 const char *p = path + m->posix_pathlen;
63 if (!*p)
64 p = "/";
65 return p;
67 bool exists () {return !!m;}
68 void set (const char *, const char *, bool);
69 size_t posix_length () const { return m->posix_pathlen; }
70 const char *posix_path () const { return m->posix_path; }
71 size_t native_length () const { return m->native_pathlen; }
72 const char *native_path () const { return m->native_path; }
75 enum homebodies
77 CH_HOMEDRIVE,
78 CH_HOMEPATH,
79 CH_HOME
82 class cygheap_user
84 /* Extendend user information.
85 The information is derived from the internal_getlogin call
86 when on a NT system. */
87 char *pname; /* user's name */
88 char *plogsrv; /* Logon server, may be FQDN */
89 char *pdomain; /* Logon domain of the user */
90 char *homedrive; /* User's home drive */
91 char *homepath; /* User's home path */
92 char *psystemroot; /* Value of SYSTEMROOT */
93 char *pwinname; /* User's name as far as Windows knows it */
94 char *puserprof; /* User profile */
95 cygsid effec_cygsid; /* buffer for user's SID */
96 cygsid saved_cygsid; /* Remains intact even after impersonation */
97 public:
98 uid_t saved_uid; /* Remains intact even after impersonation */
99 gid_t saved_gid; /* Ditto */
100 uid_t real_uid; /* Remains intact on seteuid, replaced by setuid */
101 gid_t real_gid; /* Ditto */
102 user_groups groups; /* Primary and supp SIDs */
104 HANDLE external_token; /* token from set_impersonation_token call */
105 HANDLE internal_token; /* password-less token fetched in seteuid */
106 HANDLE curr_primary_token; /* Just a copy of external or internal token */
107 HANDLE curr_imp_token; /* impersonation token derived from primary
108 token */
109 bool ext_token_is_restricted; /* external_token is restricted token */
110 bool curr_token_is_restricted; /* curr_primary_token is restricted token */
111 bool setuid_to_restricted; /* switch to restricted token by setuid () */
113 /* CGF 2002-06-27. I removed the initializaton from this constructor
114 since this class is always allocated statically. That means that everything
115 is zero anyway so there is no need to initialize it to zero. Since the
116 token initialization is always handled during process startup as well,
117 I've removed the constructor entirely. Please reinstate this if this
118 situation ever changes.
119 cygheap_user () : pname (NULL), plogsrv (NULL), pdomain (NULL),
120 homedrive (NULL), homepath (NULL),
121 token (INVALID_HANDLE_VALUE) {}
124 ~cygheap_user ();
126 void init ();
127 void set_name (const char *new_name);
128 const char *name () const { return pname; }
130 const char *env_logsrv (const char *, size_t);
131 const char *env_homepath (const char *, size_t);
132 const char *env_homedrive (const char *, size_t);
133 const char *env_userprofile (const char *, size_t);
134 const char *env_domain (const char *, size_t);
135 const char *env_name (const char *, size_t);
136 const char *env_systemroot (const char *, size_t);
138 const char *logsrv ()
140 const char *p = env_logsrv ("LOGONSERVER=", sizeof ("LOGONSERVER=") - 1);
141 return (p == almost_null) ? NULL : p;
143 const char *winname ()
145 const char *p = env_name ("USERNAME=", sizeof ("USERNAME=") - 1);
146 return (p == almost_null) ? NULL : p;
148 const char *domain ()
150 const char *p = env_domain ("USERDOMAIN=", sizeof ("USERDOMAIN=") - 1);
151 return (p == almost_null) ? NULL : p;
153 void set_sid (PSID new_sid) { effec_cygsid = new_sid;}
154 void set_saved_sid () { saved_cygsid = effec_cygsid; }
155 cygpsid &sid () { return effec_cygsid; }
156 cygpsid &saved_sid () { return saved_cygsid; }
157 const char *ontherange (homebodies what, struct passwd * = NULL);
158 #define NO_IMPERSONATION NULL
159 bool issetuid () const { return curr_imp_token != NO_IMPERSONATION; }
160 HANDLE primary_token () { return curr_primary_token; }
161 HANDLE imp_token () { return curr_imp_token; }
162 void deimpersonate ()
164 RevertToSelf ();
166 bool reimpersonate ()
168 if (issetuid ())
169 return ImpersonateLoggedOnUser (primary_token ());
170 return true;
172 bool has_impersonation_tokens ()
173 { return external_token != NO_IMPERSONATION
174 || internal_token != NO_IMPERSONATION
175 || curr_primary_token != NO_IMPERSONATION; }
176 void close_impersonation_tokens ()
178 if (curr_imp_token != NO_IMPERSONATION)
179 CloseHandle (curr_imp_token);
180 if (external_token != NO_IMPERSONATION)
181 CloseHandle (external_token);
182 if (internal_token != NO_IMPERSONATION)
183 CloseHandle (internal_token);
185 PWCHAR get_windows_id (PWCHAR buf)
187 return effec_cygsid.string (buf);
189 char *get_windows_id (char *buf)
191 return effec_cygsid.string (buf);
194 const char *test_uid (char *&, const char *, size_t);
197 /* cwd cache stuff. */
199 /* This class is used to store the CWD. The CWD storage in the
200 RTL_USER_PROCESS_PARAMETERS block is only an afterthought now. The actual
201 CWD storage is a FAST_CWD structure which is allocated on the process heap.
202 The new method only requires minimal locking and it's much more multi-thread
203 friendly. Presumably it minimizes contention when accessing the CWD.
204 The class fcwd_access_t is supposed to encapsulate the gory implementation
205 details depending on OS version from the calling functions.
206 The layout of all structures has been tested on 32 and 64 bit. */
207 class fcwd_access_t {
208 LONG ReferenceCount; /* Only release when this is 0. */
209 HANDLE DirectoryHandle;
210 ULONG OldDismountCount; /* Reflects the system DismountCount
211 at the time the CWD has been set. */
212 UNICODE_STRING Path; /* Path's Buffer member always refers
213 to the following Buffer array. */
214 LONG FSCharacteristics; /* Taken from FileFsDeviceInformation */
215 /* fcwd_access_t is dynamically allocated with a size of
216 sizeof(fcwd_access_t) + cwd.Length. Preallocating 2 chars
217 here allows to append a trailing backslash and NUL. */
218 WCHAR Buffer[2] __attribute ((aligned (8)));
220 public:
221 void CopyPath (UNICODE_STRING &target);
222 void Free (PVOID heap);
223 void FillIn (HANDLE dir, PUNICODE_STRING name, ULONG old_dismount_count);
224 static void SetDirHandleFromBufferPointer (PWCHAR buf_p, HANDLE dir);
225 static void SetVersionFromPointer (PBYTE buf_p, bool is_buffer);
228 class cwdstuff
230 private:
231 char *posix;
232 HANDLE dir;
233 DWORD drive_length;
234 int error; /* This contains an errno number which corresponds
235 to the problem with this path when trying to start
236 a native Win32 application. See cwdstuff::set for
237 how it gets set. See child_info_spawn::worker for how
238 it's evaluated. */
240 friend class fcwd_access_t;
241 /* fast_cwd_ptr is a pointer to the global RtlpCurDirRef pointer in
242 ntdll.dll pointing to the FAST_CWD structure which constitutes the CWD.
243 Unfortunately RtlpCurDirRef is not exported from ntdll.dll. */
244 fcwd_access_t **fast_cwd_ptr;
245 void override_win32_cwd (bool init, ULONG old_dismount_count);
247 public:
248 UNICODE_STRING win32;
249 static SRWLOCK NO_COPY cwd_lock;
251 static void acquire_read () { AcquireSRWLockShared (&cwd_lock); }
252 static void release_read () { ReleaseSRWLockShared (&cwd_lock); }
253 static void acquire_write () { AcquireSRWLockExclusive (&cwd_lock); }
254 static void release_write () { ReleaseSRWLockExclusive (&cwd_lock); }
255 const char *get_posix () const { return posix; };
256 void reset_posix (wchar_t *w_cwd);
257 char *get (char *buf, int need_posix = 1, int with_chroot = 0,
258 unsigned ulen = NT_MAX_PATH);
259 PWCHAR get (PWCHAR buf, unsigned buflen = NT_MAX_PATH)
261 acquire_read ();
262 buf[0] = L'\0';
263 wcsncat (buf, win32.Buffer, buflen - 1);
264 release_read ();
265 return buf;
267 HANDLE get_handle () { return dir; }
268 DWORD get_drive (char * dst)
270 acquire_read ();
271 DWORD ret = sys_wcstombs (dst, NT_MAX_PATH, win32.Buffer, drive_length);
272 release_read ();
273 return ret;
275 int get_error () const { return error; }
276 const char *get_error_desc () const;
277 void init ();
278 int set (path_conv *, const char *);
281 #ifdef DEBUGGING
282 struct cygheap_debug
284 handle_list starth;
285 handle_list freeh[500];
287 #endif
289 struct cygheap_locale
291 mbtowc_p mbtowc;
294 struct user_heap_info
296 void *base;
297 void *ptr;
298 void *top;
299 void *max;
300 SIZE_T chunk;
301 void *sbrk (ptrdiff_t);
302 void init ();
305 /* This info is maintained for /proc/<PID>/maps ONLY! */
306 struct shared_region_info
308 void *cygwin_shared_addr;
309 void *user_shared_addr;
310 void *myself_shared_addr;
311 void *console_shared_addr;
314 class cygheap_domain_info
316 PWCHAR pdom_name;
317 PWCHAR pdom_dns_name;
318 cygsid pdom_sid;
320 PWCHAR adom_name;
321 cygsid adom_sid;
323 PDS_DOMAIN_TRUSTSW tdom;
324 ULONG tdom_count;
326 PWCHAR rfc2307_domain_buf;
328 public:
329 bool init ();
331 inline PCWSTR primary_flat_name () const { return pdom_name; }
332 inline PCWSTR primary_dns_name () const { return pdom_dns_name; }
333 inline cygsid &primary_sid () { return pdom_sid; }
335 inline bool member_machine () const { return pdom_sid != NO_SID; }
337 inline PCWSTR account_flat_name () const { return adom_name; }
338 inline cygsid &account_sid () { return adom_sid; }
340 inline PDS_DOMAIN_TRUSTSW trusted_domain (ULONG idx) const
341 { return (idx < tdom_count) ? tdom + idx : NULL; }
342 PDS_DOMAIN_TRUSTSW add_domain (PCWSTR, PSID);
344 inline PWCHAR get_rfc2307_domain () const
345 { return rfc2307_domain_buf ?: NULL; }
348 #define NSS_SEPARATOR_STRING L"+"
349 #define NSS_SEPARATOR_CHAR (NSS_SEPARATOR_STRING[0])
351 class cygheap_pwdgrp
353 public:
354 enum nss_scheme_method {
355 NSS_SCHEME_FALLBACK = 0,
356 NSS_SCHEME_WINDOWS,
357 NSS_SCHEME_CYGWIN,
358 NSS_SCHEME_UNIX,
359 NSS_SCHEME_DESC,
360 NSS_SCHEME_PATH,
361 NSS_SCHEME_FREEATTR,
362 NSS_SCHEME_ENV
364 struct nss_scheme_t {
365 nss_scheme_method method;
366 PWCHAR attrib;
368 private:
369 bool nss_inited;
370 uint32_t pwd_src;
371 uint32_t grp_src;
372 bool caching;
374 #define NSS_SCHEME_MAX 4
375 nss_scheme_t home_scheme[NSS_SCHEME_MAX];
376 nss_scheme_t shell_scheme[NSS_SCHEME_MAX];
377 nss_scheme_t gecos_scheme[NSS_SCHEME_MAX];
379 uint32_t enums;
380 PWCHAR enum_tdoms;
382 void nss_init_line (const char *line);
383 void _nss_init ();
385 public:
386 struct {
387 pwdgrp cygserver;
388 pwdgrp file;
389 pwdgrp win;
390 } pwd_cache;
391 struct {
392 pwdgrp cygserver;
393 pwdgrp file;
394 pwdgrp win;
395 } grp_cache;
397 void init ();
399 /* Implemented in ldap.cc */
400 PWCHAR *ldap_user_attr;
401 void init_ldap_user_attr ();
403 inline void nss_init () { if (!nss_inited) _nss_init (); }
404 inline bool nss_pwd_files () const { return !!(pwd_src & NSS_SRC_FILES); }
405 inline bool nss_pwd_db () const { return !!(pwd_src & NSS_SRC_DB); }
406 inline int nss_pwd_src () const { return pwd_src; } /* CW_GETNSS_PWD_SRC */
407 inline bool nss_grp_files () const { return !!(grp_src & NSS_SRC_FILES); }
408 inline bool nss_grp_db () const { return !!(grp_src & NSS_SRC_DB); }
409 inline int nss_grp_src () const { return grp_src; } /* CW_GETNSS_GRP_SRC */
410 inline bool nss_cygserver_caching () const { return caching; }
411 inline void nss_disable_cygserver_caching () { caching = false; }
413 char *get_home (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom, PCWSTR dnsdomain,
414 PCWSTR name, bool fq);
415 char *get_home (struct _USER_INFO_3 *ui, cygpsid &sid, PCWSTR dom,
416 PCWSTR name, bool fq);
418 char *get_shell (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom, PCWSTR dnsdomain,
419 PCWSTR name, bool fq);
420 char *get_shell (struct _USER_INFO_3 *ui, cygpsid &sid, PCWSTR dom,
421 PCWSTR name, bool fq);
423 char *get_gecos (cyg_ldap *pldap, cygpsid &sid, PCWSTR dom, PCWSTR dnsdomain,
424 PCWSTR name, bool fq);
425 char *get_gecos (struct _USER_INFO_3 *ui, cygpsid &sid, PCWSTR dom,
426 PCWSTR name, bool fq);
428 inline int nss_db_enums () const { return enums; }
429 inline PCWSTR nss_db_enum_tdoms () const { return enum_tdoms; }
432 class cygheap_ugid_cache
434 struct idmap {
435 uint32_t nfs_id;
436 uint32_t cyg_id;
438 class idmaps {
439 uint32_t _cnt;
440 uint32_t _max;
441 idmap *_map;
442 public:
443 uint32_t get (uint32_t id) const
445 for (uint32_t i = 0; i < _cnt; ++i)
446 if (_map[i].nfs_id == id)
447 return _map[i].cyg_id;
448 return (uint32_t) -1;
450 uint32_t reverse_get (uint32_t id) const
452 for (uint32_t i = 0; i < _cnt; ++i)
453 if (_map[i].cyg_id == id)
454 return _map[i].nfs_id;
455 return (uint32_t) -1;
457 void add (uint32_t nfs_id, uint32_t cyg_id)
459 if (_cnt >= _max)
460 _map = (idmap *) crealloc (_map, (_max += 10) * sizeof (*_map));
461 _map[_cnt].nfs_id = nfs_id;
462 _map[_cnt].cyg_id = cyg_id;
463 ++_cnt;
466 idmaps uids;
467 idmaps gids;
469 public:
470 uid_t get_uid (uid_t uid) const { return uids.get (uid); }
471 gid_t get_gid (gid_t gid) const { return gids.get (gid); }
472 uid_t reverse_get_uid (uid_t uid) const { return uids.reverse_get (uid); }
473 gid_t reverse_get_gid (gid_t gid) const { return gids.reverse_get (gid); }
474 void add_uid (uid_t nfs_uid, uid_t cyg_uid) { uids.add (nfs_uid, cyg_uid); }
475 void add_gid (gid_t nfs_gid, gid_t cyg_gid) { gids.add (nfs_gid, cyg_gid); }
478 struct hook_chain
480 void **loc;
481 const void *func;
482 struct hook_chain *next;
485 struct mini_cygheap
487 cygheap_locale locale;
490 #define NBUCKETS 32
492 struct threadlist_t
494 struct _cygtls *thread;
495 HANDLE mutex; /* Used to avoid accessing tls area of
496 deleted thread. See comment in
497 cygheap::remove_tls for a description. */
500 struct init_cygheap: public mini_cygheap
502 _cmalloc_entry *chain;
503 char *buckets[NBUCKETS];
504 UNICODE_STRING installation_root;
505 WCHAR installation_root_buf[PATH_MAX];
506 UNICODE_STRING installation_dir;
507 WCHAR installation_dir_buf[PATH_MAX];
508 UNICODE_STRING installation_key;
509 WCHAR installation_key_buf[18];
510 cygheap_root root;
511 cygheap_domain_info dom;
512 cygheap_pwdgrp pg;
513 cygheap_ugid_cache ugid_cache;
514 cygheap_user user;
515 user_heap_info user_heap;
516 shared_region_info shared_regions;
517 mode_t umask;
518 LONG rlim_as_id;
519 unsigned long rlim_core;
520 HANDLE console_h;
521 cwdstuff cwd;
522 dtable fdtab;
523 #ifdef DEBUGGING
524 cygheap_debug debug;
525 #endif
526 struct sigaction *sigs;
528 fhandler_termios *ctty; /* Current tty */
529 threadlist_t *threadlist;
530 uint32_t sthreads;
531 pid_t pid; /* my pid */
532 struct { /* Equivalent to using LIST_HEAD. */
533 struct inode_t *lh_first;
534 } inode_list; /* Global inode pointer for adv. locking. */
535 hook_chain hooks;
536 void close_ctty ();
537 void init_installation_root ();
538 void init_tls_list ();;
539 void add_tls (_cygtls *);
540 HANDLE remove_tls (_cygtls *);
541 threadlist_t *find_tls (_cygtls *);
542 threadlist_t *find_tls (int, bool&);
543 sigset_t compute_sigblkmask ();
544 void unlock_tls (threadlist_t *t) { if (t) ReleaseMutex (t->mutex); }
548 #define _CYGHEAPSIZE_SLOP (128 * 1024)
549 #define CYGHEAPSIZE (sizeof (init_cygheap) + (20000 * sizeof (fhandler_union)) + _CYGHEAPSIZE_SLOP)
550 #define CYGHEAPSIZE_MIN (sizeof (init_cygheap) + (10000 * sizeof (fhandler_union)))
552 extern init_cygheap *cygheap;
553 extern void *cygheap_max;
555 class cygheap_fdmanip
557 protected:
558 int fd;
559 bool locked;
560 public:
561 cygheap_fdmanip (): fd (-1), locked (false) {}
562 virtual ~cygheap_fdmanip ()
564 if (locked)
565 cygheap->fdtab.unlock ();
567 virtual void release () { cygheap->fdtab.release (fd); }
568 operator int &() {return fd;}
569 operator fhandler_base* &() {return cygheap->fdtab[fd];}
570 operator fhandler_socket* () const {return reinterpret_cast<fhandler_socket *> (cygheap->fdtab[fd]);}
571 operator fhandler_pipe* () const {return reinterpret_cast<fhandler_pipe *> (cygheap->fdtab[fd]);}
572 void operator = (fhandler_base *fh) {cygheap->fdtab[fd] = fh;}
573 fhandler_base *operator -> () const {return cygheap->fdtab[fd];}
574 bool isopen () const
576 if (cygheap->fdtab[fd])
577 return true;
578 set_errno (EBADF);
579 return false;
583 class cygheap_fdnew : public cygheap_fdmanip
585 public:
586 cygheap_fdnew (int seed_fd = -1, bool lockit = true)
588 if (lockit)
589 cygheap->fdtab.lock ();
590 if (seed_fd < 0)
591 fd = cygheap->fdtab.find_unused_handle ();
592 else
593 fd = cygheap->fdtab.find_unused_handle (seed_fd + 1);
594 if (fd >= 0)
595 locked = lockit;
596 else
598 /* errno set by find_unused_handle */
599 if (lockit)
600 cygheap->fdtab.unlock ();
601 locked = false;
604 ~cygheap_fdnew ()
606 if (cygheap->fdtab[fd])
607 cygheap->fdtab[fd]->inc_refcnt ();
609 void operator = (fhandler_base *fh) {cygheap->fdtab[fd] = fh;}
612 class cygheap_fdget : public cygheap_fdmanip
614 fhandler_base *fh;
615 public:
616 cygheap_fdget (int fd, bool lockit = false, bool do_set_errno = true)
618 if (lockit)
619 cygheap->fdtab.lock ();
620 if (fd >= 0 && fd < (int) cygheap->fdtab.size && cygheap->fdtab[fd] != NULL)
622 this->fd = fd;
623 locked = lockit;
624 fh = cygheap->fdtab[fd];
625 fh->inc_refcnt ();
627 else
629 this->fd = -1;
630 if (do_set_errno)
631 set_errno (EBADF);
632 if (lockit)
633 cygheap->fdtab.unlock ();
634 locked = false;
635 fh = NULL;
638 ~cygheap_fdget ()
640 if (fh && fh->dec_refcnt () <= 0)
642 debug_only_printf ("deleting fh %p", fh);
643 delete fh;
646 void release () { cygheap->fdtab.release (fd); }
649 class cygheap_fdenum : public cygheap_fdmanip
651 public:
652 cygheap_fdenum (bool lockit = false)
654 locked = lockit;
655 if (lockit)
656 cygheap->fdtab.lock ();
657 fd = -1;
659 int next ()
661 while (++fd < (int) cygheap->fdtab.size)
662 if (cygheap->fdtab[fd] != NULL)
663 return fd;
664 return -1;
666 void rewind ()
668 fd = -1;
672 void cygheap_fixup_in_child (bool);
673 void cygheap_init ();
674 void setup_cygheap ();