10Sstevel@tonic-gate /* 2*10598SGlenn.Barry@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 30Sstevel@tonic-gate * Use is subject to license terms. 40Sstevel@tonic-gate */ 50Sstevel@tonic-gate 60Sstevel@tonic-gate 70Sstevel@tonic-gate /* 80Sstevel@tonic-gate * k5-platform.h 90Sstevel@tonic-gate * 107934SMark.Phalan@Sun.COM * Copyright 2003, 2004, 2005 Massachusetts Institute of Technology. 110Sstevel@tonic-gate * All Rights Reserved. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * Export of this software from the United States of America may 140Sstevel@tonic-gate * require a specific license from the United States Government. 150Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating 160Sstevel@tonic-gate * export to obtain such a license before exporting. 170Sstevel@tonic-gate * 180Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 190Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 200Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 210Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 220Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 230Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining 240Sstevel@tonic-gate * to distribution of the software without specific, written prior 250Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label 260Sstevel@tonic-gate * your software as modified software and not distribute it in such a 270Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software. 280Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of 290Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 300Sstevel@tonic-gate * or implied warranty. 310Sstevel@tonic-gate * 320Sstevel@tonic-gate * 330Sstevel@tonic-gate * Some platform-dependent definitions to sync up the C support level. 340Sstevel@tonic-gate * Some to a C99-ish level, some related utility code. 350Sstevel@tonic-gate * 36781Sgtb * Currently: 37781Sgtb * + make "static inline" work 38781Sgtb * + 64-bit types and load/store code 39781Sgtb * + SIZE_MAX 40781Sgtb * + shared library init/fini hooks 417934SMark.Phalan@Sun.COM * + consistent getpwnam/getpwuid interfaces 420Sstevel@tonic-gate */ 430Sstevel@tonic-gate 440Sstevel@tonic-gate #ifndef K5_PLATFORM_H 450Sstevel@tonic-gate #define K5_PLATFORM_H 460Sstevel@tonic-gate 477934SMark.Phalan@Sun.COM /* Solaris Kerberos */ 48781Sgtb #ifndef _KERNEL 497934SMark.Phalan@Sun.COM #include <sys/types.h> 507934SMark.Phalan@Sun.COM 51781Sgtb #include "autoconf.h" 52781Sgtb 53781Sgtb /* Initialization and finalization function support for libraries. 54781Sgtb 55781Sgtb At top level, before the functions are defined or even declared: 56781Sgtb MAKE_INIT_FUNCTION(init_fn); 57781Sgtb MAKE_FINI_FUNCTION(fini_fn); 587934SMark.Phalan@Sun.COM Then: 59781Sgtb int init_fn(void) { ... } 60781Sgtb void fini_fn(void) { if (INITIALIZER_RAN(init_fn)) ... } 61781Sgtb In code, in the same file: 62781Sgtb err = CALL_INIT_FUNCTION(init_fn); 63781Sgtb 64781Sgtb To trigger or verify the initializer invocation from another file, 657934SMark.Phalan@Sun.COM a helper function must be created. 667934SMark.Phalan@Sun.COM 677934SMark.Phalan@Sun.COM This model handles both the load-time execution (Windows) and 687934SMark.Phalan@Sun.COM delayed execution (pthread_once) approaches, and should be able to 697934SMark.Phalan@Sun.COM guarantee in both cases that the init function is run once, in one 707934SMark.Phalan@Sun.COM thread, before other stuff in the library is done; furthermore, the 717934SMark.Phalan@Sun.COM finalization code should only run if the initialization code did. 727934SMark.Phalan@Sun.COM (Maybe I could've made the "if INITIALIZER_RAN" test implicit, via 737934SMark.Phalan@Sun.COM another function hidden in macros, but this is hairy enough 747934SMark.Phalan@Sun.COM already.) 75781Sgtb 76781Sgtb The init_fn and fini_fn names should be chosen such that any 77781Sgtb exported names staring with those names, and optionally followed by 78781Sgtb additional characters, fits in with any namespace constraints on 79781Sgtb the library in question. 80781Sgtb 81781Sgtb 827934SMark.Phalan@Sun.COM There's also PROGRAM_EXITING() currently always defined as zero. 837934SMark.Phalan@Sun.COM If there's some trivial way to find out if the fini function is 847934SMark.Phalan@Sun.COM being called because the program that the library is linked into is 857934SMark.Phalan@Sun.COM exiting, we can just skip all the work because the resources are 867934SMark.Phalan@Sun.COM about to be freed up anyways. Generally this is likely to be the 877934SMark.Phalan@Sun.COM same as distinguishing whether the library was loaded dynamically 887934SMark.Phalan@Sun.COM while the program was running, or loaded as part of program 897934SMark.Phalan@Sun.COM startup. On most platforms, I don't think we can distinguish these 907934SMark.Phalan@Sun.COM cases easily, and it's probably not worth expending any significant 917934SMark.Phalan@Sun.COM effort. (Note in particular that atexit() won't do, because if the 927934SMark.Phalan@Sun.COM library is explicitly loaded and unloaded, it would have to be able 937934SMark.Phalan@Sun.COM to deregister the atexit callback function. Also, the system limit 947934SMark.Phalan@Sun.COM on atexit callbacks may be small.) 957934SMark.Phalan@Sun.COM 967934SMark.Phalan@Sun.COM 97781Sgtb Implementation outline: 98781Sgtb 99781Sgtb Windows: MAKE_FINI_FUNCTION creates a symbol with a magic name that 100781Sgtb is sought at library build time, and code is added to invoke the 101781Sgtb function when the library is unloaded. MAKE_INIT_FUNCTION does 102781Sgtb likewise, but the function is invoked when the library is loaded, 103781Sgtb and an extra variable is declared to hold an error code and a "yes 104781Sgtb the initializer ran" flag. CALL_INIT_FUNCTION blows up if the flag 105781Sgtb isn't set, otherwise returns the error code. 106781Sgtb 107781Sgtb UNIX: MAKE_INIT_FUNCTION creates and initializes a variable with a 108781Sgtb name derived from the function name, containing a k5_once_t 109781Sgtb (pthread_once_t or int), an error code, and a pointer to the 110781Sgtb function. The function itself is declared static, but the 111781Sgtb associated variable has external linkage. CALL_INIT_FUNCTION 112781Sgtb ensures thath the function is called exactly once (pthread_once or 113781Sgtb just check the flag) and returns the stored error code (or the 114781Sgtb pthread_once error). 115781Sgtb 1167934SMark.Phalan@Sun.COM (That's the basic idea. With some debugging assert() calls and 1177934SMark.Phalan@Sun.COM such, it's a bit more complicated. And we also need to handle 1187934SMark.Phalan@Sun.COM doing the pthread test at run time on systems where that works, so 1197934SMark.Phalan@Sun.COM we use the k5_once_t stuff instead.) 1207934SMark.Phalan@Sun.COM 121781Sgtb UNIX, with compiler support: MAKE_FINI_FUNCTION declares the 122781Sgtb function as a destructor, and the run time linker support or 123781Sgtb whatever will cause it to be invoked when the library is unloaded, 124781Sgtb the program ends, etc. 125781Sgtb 126781Sgtb UNIX, with linker support: MAKE_FINI_FUNCTION creates a symbol with 127781Sgtb a magic name that is sought at library build time, and linker 128781Sgtb options are used to mark it as a finalization function for the 129781Sgtb library. The symbol must be exported. 130781Sgtb 131781Sgtb UNIX, no library finalization support: The finalization function 132781Sgtb never runs, and we leak memory. Tough. 133781Sgtb 1347934SMark.Phalan@Sun.COM DELAY_INITIALIZER will be defined by the configure script if we 1357934SMark.Phalan@Sun.COM want to use k5_once instead of load-time initialization. That'll 1367934SMark.Phalan@Sun.COM be the preferred method on most systems except Windows, where we 1377934SMark.Phalan@Sun.COM have to initialize some mutexes. 1387934SMark.Phalan@Sun.COM 1397934SMark.Phalan@Sun.COM 140781Sgtb 141781Sgtb 142781Sgtb For maximum flexibility in defining the macros, the function name 143781Sgtb parameter should be a simple name, not even a macro defined as 144781Sgtb another name. The function should have a unique name, and should 145781Sgtb conform to whatever namespace is used by the library in question. 1467934SMark.Phalan@Sun.COM (We do have export lists, but (1) they're not used for all 1477934SMark.Phalan@Sun.COM platforms, and (2) they're not used for static libraries.) 148781Sgtb 149781Sgtb If the macro expansion needs the function to have been declared, it 150781Sgtb must include a declaration. If it is not necessary for the symbol 151781Sgtb name to be exported from the object file, the macro should declare 152781Sgtb it as "static". Hence the signature must exactly match "void 153781Sgtb foo(void)". (ANSI C allows a static declaration followed by a 154781Sgtb non-static one; the result is internal linkage.) The macro 155781Sgtb expansion has to come before the function, because gcc apparently 156781Sgtb won't act on "__attribute__((constructor))" if it comes after the 157781Sgtb function definition. 158781Sgtb 159781Sgtb This is going to be compiler- and environment-specific, and may 160781Sgtb require some support at library build time, and/or "asm" 1617934SMark.Phalan@Sun.COM statements. But through macro expansion and auxiliary functions, 1627934SMark.Phalan@Sun.COM we should be able to handle most things except #pragma. 163781Sgtb 164781Sgtb It's okay for this code to require that the library be built 165781Sgtb with the same compiler and compiler options throughout, but 166781Sgtb we shouldn't require that the library and application use the 167781Sgtb same compiler. 168781Sgtb 169781Sgtb For static libraries, we don't really care about cleanup too much, 170781Sgtb since it's all memory handling and mutex allocation which will all 171781Sgtb be cleaned up when the program exits. Thus, it's okay if gcc-built 172781Sgtb static libraries don't play nicely with cc-built executables when 173781Sgtb it comes to static constructors, just as long as it doesn't cause 174781Sgtb linking to fail. 175781Sgtb 176781Sgtb For dynamic libraries on UNIX, we'll use pthread_once-type support 177781Sgtb to do delayed initialization, so if finalization can't be made to 178781Sgtb work, we'll only have memory leaks in a load/use/unload cycle. If 179781Sgtb anyone (like, say, the OS vendor) complains about this, they can 180781Sgtb tell us how to get a shared library finalization function invoked 1817934SMark.Phalan@Sun.COM automatically. 1827934SMark.Phalan@Sun.COM 1837934SMark.Phalan@Sun.COM Currently there's --disable-delayed-initialization for preventing 1847934SMark.Phalan@Sun.COM the initialization from being delayed on UNIX, but that's mainly 1857934SMark.Phalan@Sun.COM just for testing the linker options for initialization, and will 1867934SMark.Phalan@Sun.COM probably be removed at some point. */ 187781Sgtb 188781Sgtb /* Helper macros. */ 189781Sgtb 190781Sgtb # define JOIN__2_2(A,B) A ## _ ## _ ## B 191781Sgtb # define JOIN__2(A,B) JOIN__2_2(A,B) 192781Sgtb 193781Sgtb /* XXX Should test USE_LINKER_INIT_OPTION early, and if it's set, 194781Sgtb always provide a function by the expected name, even if we're 195781Sgtb delaying initialization. */ 196781Sgtb 197781Sgtb #if defined(DELAY_INITIALIZER) 198781Sgtb 199781Sgtb /* Run the initialization code during program execution, at the latest 200781Sgtb possible moment. This means multiple threads may be active. */ 201781Sgtb # include "k5-thread.h" 202781Sgtb typedef struct { k5_once_t once; int error, did_run; void (*fn)(void); } k5_init_t; 203781Sgtb # ifdef USE_LINKER_INIT_OPTION 204781Sgtb # define MAYBE_DUMMY_INIT(NAME) \ 205781Sgtb void JOIN__2(NAME, auxinit) () { } 206781Sgtb # else 207781Sgtb # define MAYBE_DUMMY_INIT(NAME) 208781Sgtb # endif 209781Sgtb # ifdef __GNUC__ 210781Sgtb /* Do it in macro form so we get the file/line of the invocation if 211781Sgtb the assertion fails. */ 212781Sgtb # define k5_call_init_function(I) \ 213781Sgtb (__extension__ ({ \ 214781Sgtb k5_init_t *k5int_i = (I); \ 215781Sgtb int k5int_err = k5_once(&k5int_i->once, k5int_i->fn); \ 216781Sgtb (k5int_err \ 217781Sgtb ? k5int_err \ 218781Sgtb : (assert(k5int_i->did_run != 0), k5int_i->error)); \ 219781Sgtb })) 2207934SMark.Phalan@Sun.COM # define MAYBE_DEFINE_CALLINIT_FUNCTION 2217934SMark.Phalan@Sun.COM # else 2227934SMark.Phalan@Sun.COM # define MAYBE_DEFINE_CALLINIT_FUNCTION \ 2237934SMark.Phalan@Sun.COM static int k5_call_init_function(k5_init_t *i) \ 2247934SMark.Phalan@Sun.COM { \ 2257934SMark.Phalan@Sun.COM int err; \ 2267934SMark.Phalan@Sun.COM err = k5_once(&i->once, i->fn); \ 2277934SMark.Phalan@Sun.COM if (err) \ 2287934SMark.Phalan@Sun.COM return err; \ 2297934SMark.Phalan@Sun.COM assert (i->did_run != 0); \ 2307934SMark.Phalan@Sun.COM return i->error; \ 2317934SMark.Phalan@Sun.COM } 2327934SMark.Phalan@Sun.COM # endif 2337934SMark.Phalan@Sun.COM # define MAKE_INIT_FUNCTION(NAME) \ 2347934SMark.Phalan@Sun.COM static int NAME(void); \ 2357934SMark.Phalan@Sun.COM MAYBE_DUMMY_INIT(NAME) \ 2367934SMark.Phalan@Sun.COM /* forward declaration for use in initializer */ \ 2377934SMark.Phalan@Sun.COM static void JOIN__2(NAME, aux) (void); \ 2387934SMark.Phalan@Sun.COM static k5_init_t JOIN__2(NAME, once) = \ 2397934SMark.Phalan@Sun.COM { K5_ONCE_INIT, 0, 0, JOIN__2(NAME, aux) }; \ 2407934SMark.Phalan@Sun.COM MAYBE_DEFINE_CALLINIT_FUNCTION \ 2417934SMark.Phalan@Sun.COM static void JOIN__2(NAME, aux) (void) \ 2427934SMark.Phalan@Sun.COM { \ 2437934SMark.Phalan@Sun.COM JOIN__2(NAME, once).did_run = 1; \ 2447934SMark.Phalan@Sun.COM JOIN__2(NAME, once).error = NAME(); \ 2457934SMark.Phalan@Sun.COM } \ 2467934SMark.Phalan@Sun.COM /* so ';' following macro use won't get error */ \ 2477934SMark.Phalan@Sun.COM static int NAME(void) 2487934SMark.Phalan@Sun.COM # define CALL_INIT_FUNCTION(NAME) \ 2497934SMark.Phalan@Sun.COM k5_call_init_function(& JOIN__2(NAME, once)) 250781Sgtb /* This should be called in finalization only, so we shouldn't have 251781Sgtb multiple active threads mucking around in our library at this 252781Sgtb point. So ignore the once_t object and just look at the flag. 253781Sgtb 2547934SMark.Phalan@Sun.COM XXX Could we have problems with memory coherence between processors 2557934SMark.Phalan@Sun.COM if we don't invoke mutex/once routines? Probably not, the 2567934SMark.Phalan@Sun.COM application code should already be coordinating things such that 2577934SMark.Phalan@Sun.COM the library code is not in use by this point, and memory 2587934SMark.Phalan@Sun.COM synchronization will be needed there. */ 259781Sgtb # define INITIALIZER_RAN(NAME) \ 260781Sgtb (JOIN__2(NAME, once).did_run && JOIN__2(NAME, once).error == 0) 261781Sgtb 262781Sgtb # define PROGRAM_EXITING() (0) 263781Sgtb 264781Sgtb #elif defined(__GNUC__) && !defined(_WIN32) && defined(CONSTRUCTOR_ATTR_WORKS) 265781Sgtb 266781Sgtb /* Run initializer at load time, via GCC/C++ hook magic. */ 267781Sgtb 268781Sgtb # ifdef USE_LINKER_INIT_OPTION 2697934SMark.Phalan@Sun.COM /* Both gcc and linker option?? Favor gcc. */ 270781Sgtb # define MAYBE_DUMMY_INIT(NAME) \ 271781Sgtb void JOIN__2(NAME, auxinit) () { } 272781Sgtb # else 273781Sgtb # define MAYBE_DUMMY_INIT(NAME) 274781Sgtb # endif 275781Sgtb 276781Sgtb typedef struct { int error; unsigned char did_run; } k5_init_t; 277781Sgtb # define MAKE_INIT_FUNCTION(NAME) \ 278781Sgtb MAYBE_DUMMY_INIT(NAME) \ 279781Sgtb static k5_init_t JOIN__2(NAME, ran) \ 280781Sgtb = { 0, 2 }; \ 281781Sgtb static void JOIN__2(NAME, aux)(void) \ 282781Sgtb __attribute__((constructor)); \ 283781Sgtb static int NAME(void); \ 284781Sgtb static void JOIN__2(NAME, aux)(void) \ 285781Sgtb { \ 286781Sgtb JOIN__2(NAME, ran).error = NAME(); \ 287781Sgtb JOIN__2(NAME, ran).did_run = 3; \ 288781Sgtb } \ 289781Sgtb static int NAME(void) 290781Sgtb # define CALL_INIT_FUNCTION(NAME) \ 291781Sgtb (JOIN__2(NAME, ran).did_run == 3 \ 292781Sgtb ? JOIN__2(NAME, ran).error \ 293781Sgtb : (abort(),0)) 294781Sgtb # define INITIALIZER_RAN(NAME) (JOIN__2(NAME,ran).did_run == 3 && JOIN__2(NAME, ran).error == 0) 295781Sgtb 2967934SMark.Phalan@Sun.COM # define PROGRAM_EXITING() (0) 2977934SMark.Phalan@Sun.COM 298781Sgtb #elif defined(USE_LINKER_INIT_OPTION) || defined(_WIN32) 299781Sgtb 300781Sgtb /* Run initializer at load time, via linker magic, or in the 301781Sgtb case of WIN32, win_glue.c hard-coded knowledge. */ 302781Sgtb typedef struct { int error; unsigned char did_run; } k5_init_t; 303781Sgtb # define MAKE_INIT_FUNCTION(NAME) \ 304781Sgtb static k5_init_t JOIN__2(NAME, ran) \ 305781Sgtb = { 0, 2 }; \ 306781Sgtb static int NAME(void); \ 307781Sgtb void JOIN__2(NAME, auxinit)() \ 308781Sgtb { \ 309781Sgtb JOIN__2(NAME, ran).error = NAME(); \ 310781Sgtb JOIN__2(NAME, ran).did_run = 3; \ 311781Sgtb } \ 312781Sgtb static int NAME(void) 313781Sgtb # define CALL_INIT_FUNCTION(NAME) \ 314781Sgtb (JOIN__2(NAME, ran).did_run == 3 \ 315781Sgtb ? JOIN__2(NAME, ran).error \ 316781Sgtb : (abort(),0)) 317781Sgtb # define INITIALIZER_RAN(NAME) \ 318781Sgtb (JOIN__2(NAME, ran).error == 0) 319781Sgtb 320781Sgtb # define PROGRAM_EXITING() (0) 321781Sgtb 322781Sgtb #else 323781Sgtb 324781Sgtb # error "Don't know how to do load-time initializers for this configuration." 325781Sgtb 326781Sgtb # define PROGRAM_EXITING() (0) 327781Sgtb 328781Sgtb #endif 329781Sgtb 330781Sgtb 331781Sgtb 332781Sgtb #if defined(USE_LINKER_FINI_OPTION) || defined(_WIN32) 333781Sgtb /* If we're told the linker option will be used, it doesn't really 334781Sgtb matter what compiler we're using. Do it the same way 335781Sgtb regardless. */ 336781Sgtb 3377934SMark.Phalan@Sun.COM # ifdef __hpux 3387934SMark.Phalan@Sun.COM 3397934SMark.Phalan@Sun.COM /* On HP-UX, we need this auxiliary function. At dynamic load or 3407934SMark.Phalan@Sun.COM unload time (but *not* program startup and termination for 3417934SMark.Phalan@Sun.COM link-time specified libraries), the linker-indicated function 3427934SMark.Phalan@Sun.COM is called with a handle on the library and a flag indicating 3437934SMark.Phalan@Sun.COM whether it's being loaded or unloaded. 3447934SMark.Phalan@Sun.COM 3457934SMark.Phalan@Sun.COM The "real" fini function doesn't need to be exported, so 3467934SMark.Phalan@Sun.COM declare it static. 3477934SMark.Phalan@Sun.COM 3487934SMark.Phalan@Sun.COM As usual, the final declaration is just for syntactic 3497934SMark.Phalan@Sun.COM convenience, so the top-level invocation of this macro can be 3507934SMark.Phalan@Sun.COM followed by a semicolon. */ 3517934SMark.Phalan@Sun.COM 3527934SMark.Phalan@Sun.COM # include <dl.h> 3537934SMark.Phalan@Sun.COM # define MAKE_FINI_FUNCTION(NAME) \ 3547934SMark.Phalan@Sun.COM static void NAME(void); \ 3557934SMark.Phalan@Sun.COM void JOIN__2(NAME, auxfini)(shl_t, int); /* silence gcc warnings */ \ 3567934SMark.Phalan@Sun.COM void JOIN__2(NAME, auxfini)(shl_t h, int l) { if (!l) NAME(); } \ 3577934SMark.Phalan@Sun.COM static void NAME(void) 3587934SMark.Phalan@Sun.COM 3597934SMark.Phalan@Sun.COM # else /* not hpux */ 3607934SMark.Phalan@Sun.COM 3617934SMark.Phalan@Sun.COM # define MAKE_FINI_FUNCTION(NAME) \ 362781Sgtb void NAME(void) 363781Sgtb 3647934SMark.Phalan@Sun.COM # endif 3657934SMark.Phalan@Sun.COM 366781Sgtb #elif defined(__GNUC__) && defined(DESTRUCTOR_ATTR_WORKS) 367781Sgtb /* If we're using gcc, if the C++ support works, the compiler should 368781Sgtb build executables and shared libraries that support the use of 369781Sgtb static constructors and destructors. The C compiler supports a 370781Sgtb function attribute that makes use of the same facility as C++. 371781Sgtb 372781Sgtb XXX How do we know if the C++ support actually works? */ 373781Sgtb # define MAKE_FINI_FUNCTION(NAME) \ 374781Sgtb static void NAME(void) __attribute__((destructor)) 375781Sgtb 376781Sgtb #elif !defined(SHARED) 377781Sgtb 378781Sgtb /* In this case, we just don't care about finalization. 379781Sgtb 380781Sgtb The code will still define the function, but we won't do anything 381781Sgtb with it. Annoying: This may generate unused-function warnings. */ 382781Sgtb 383781Sgtb # define MAKE_FINI_FUNCTION(NAME) \ 384781Sgtb static void NAME(void) 385781Sgtb 3867934SMark.Phalan@Sun.COM #else 387781Sgtb 388781Sgtb # error "Don't know how to do unload-time finalization for this configuration." 389781Sgtb 3907934SMark.Phalan@Sun.COM #endif 391781Sgtb 392781Sgtb #endif /* !_KERNEL */ 393781Sgtb 394781Sgtb 3950Sstevel@tonic-gate /* 64-bit support: krb5_ui_8 and krb5_int64. 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate This should move to krb5.h eventually, but without the namespace 3980Sstevel@tonic-gate pollution from the autoconf macros. */ 3990Sstevel@tonic-gate #if defined(HAVE_STDINT_H) || defined(HAVE_INTTYPES_H) 4000Sstevel@tonic-gate # ifdef HAVE_STDINT_H 4010Sstevel@tonic-gate # include <stdint.h> 4020Sstevel@tonic-gate # endif 4030Sstevel@tonic-gate # ifdef HAVE_INTTYPES_H 4040Sstevel@tonic-gate # include <inttypes.h> 4050Sstevel@tonic-gate # endif 4060Sstevel@tonic-gate # define INT64_TYPE int64_t 4070Sstevel@tonic-gate # define UINT64_TYPE uint64_t 4080Sstevel@tonic-gate #elif defined(_WIN32) 4090Sstevel@tonic-gate # define INT64_TYPE signed __int64 4100Sstevel@tonic-gate # define UINT64_TYPE unsigned __int64 4110Sstevel@tonic-gate #else /* not Windows, and neither stdint.h nor inttypes.h */ 4120Sstevel@tonic-gate # define INT64_TYPE signed long long 4130Sstevel@tonic-gate # define UINT64_TYPE unsigned long long 4140Sstevel@tonic-gate #endif 4150Sstevel@tonic-gate 416781Sgtb #ifndef _KERNEL 417781Sgtb #include <limits.h> 418781Sgtb #endif /* !_KERNEL */ 4190Sstevel@tonic-gate #ifndef SIZE_MAX 4200Sstevel@tonic-gate # define SIZE_MAX ((size_t)((size_t)0 - 1)) 4210Sstevel@tonic-gate #endif 4220Sstevel@tonic-gate 423781Sgtb 4240Sstevel@tonic-gate /* Read and write integer values as (unaligned) octet strings in 4250Sstevel@tonic-gate specific byte orders. 4260Sstevel@tonic-gate 4270Sstevel@tonic-gate Add per-platform optimizations later if needed. (E.g., maybe x86 4280Sstevel@tonic-gate unaligned word stores and gcc/asm instructions for byte swaps, 4290Sstevel@tonic-gate etc.) */ 4300Sstevel@tonic-gate 4317934SMark.Phalan@Sun.COM /* Solaris Kerberos: To avoid problems with lint the following 4327934SMark.Phalan@Sun.COM functions can be found in separate header files. */ 4337934SMark.Phalan@Sun.COM #if 0 4347934SMark.Phalan@Sun.COM static void 4350Sstevel@tonic-gate store_16_be (unsigned int val, unsigned char *p) 4360Sstevel@tonic-gate { 4370Sstevel@tonic-gate p[0] = (val >> 8) & 0xff; 4380Sstevel@tonic-gate p[1] = (val ) & 0xff; 4390Sstevel@tonic-gate } 4407934SMark.Phalan@Sun.COM static void 4410Sstevel@tonic-gate store_16_le (unsigned int val, unsigned char *p) 4420Sstevel@tonic-gate { 4430Sstevel@tonic-gate p[1] = (val >> 8) & 0xff; 4440Sstevel@tonic-gate p[0] = (val ) & 0xff; 4450Sstevel@tonic-gate } 4467934SMark.Phalan@Sun.COM static void 4470Sstevel@tonic-gate store_32_be (unsigned int val, unsigned char *p) 4480Sstevel@tonic-gate { 4490Sstevel@tonic-gate p[0] = (val >> 24) & 0xff; 4500Sstevel@tonic-gate p[1] = (val >> 16) & 0xff; 4510Sstevel@tonic-gate p[2] = (val >> 8) & 0xff; 4520Sstevel@tonic-gate p[3] = (val ) & 0xff; 4530Sstevel@tonic-gate } 4547934SMark.Phalan@Sun.COM static void 4550Sstevel@tonic-gate store_32_le (unsigned int val, unsigned char *p) 4560Sstevel@tonic-gate { 4570Sstevel@tonic-gate p[3] = (val >> 24) & 0xff; 4580Sstevel@tonic-gate p[2] = (val >> 16) & 0xff; 4590Sstevel@tonic-gate p[1] = (val >> 8) & 0xff; 4600Sstevel@tonic-gate p[0] = (val ) & 0xff; 4610Sstevel@tonic-gate } 4627934SMark.Phalan@Sun.COM static void 4630Sstevel@tonic-gate store_64_be (UINT64_TYPE val, unsigned char *p) 4640Sstevel@tonic-gate { 4650Sstevel@tonic-gate p[0] = (unsigned char)((val >> 56) & 0xff); 4660Sstevel@tonic-gate p[1] = (unsigned char)((val >> 48) & 0xff); 4670Sstevel@tonic-gate p[2] = (unsigned char)((val >> 40) & 0xff); 4680Sstevel@tonic-gate p[3] = (unsigned char)((val >> 32) & 0xff); 4690Sstevel@tonic-gate p[4] = (unsigned char)((val >> 24) & 0xff); 4700Sstevel@tonic-gate p[5] = (unsigned char)((val >> 16) & 0xff); 4710Sstevel@tonic-gate p[6] = (unsigned char)((val >> 8) & 0xff); 4720Sstevel@tonic-gate p[7] = (unsigned char)((val ) & 0xff); 4730Sstevel@tonic-gate } 4747934SMark.Phalan@Sun.COM static void 4750Sstevel@tonic-gate store_64_le (UINT64_TYPE val, unsigned char *p) 4760Sstevel@tonic-gate { 4770Sstevel@tonic-gate p[7] = (unsigned char)((val >> 56) & 0xff); 4780Sstevel@tonic-gate p[6] = (unsigned char)((val >> 48) & 0xff); 4790Sstevel@tonic-gate p[5] = (unsigned char)((val >> 40) & 0xff); 4800Sstevel@tonic-gate p[4] = (unsigned char)((val >> 32) & 0xff); 4810Sstevel@tonic-gate p[3] = (unsigned char)((val >> 24) & 0xff); 4820Sstevel@tonic-gate p[2] = (unsigned char)((val >> 16) & 0xff); 4830Sstevel@tonic-gate p[1] = (unsigned char)((val >> 8) & 0xff); 4840Sstevel@tonic-gate p[0] = (unsigned char)((val ) & 0xff); 4850Sstevel@tonic-gate } 4867934SMark.Phalan@Sun.COM static unsigned short 4870Sstevel@tonic-gate load_16_be (unsigned char *p) 4880Sstevel@tonic-gate { 4890Sstevel@tonic-gate return (p[1] | (p[0] << 8)); 4900Sstevel@tonic-gate } 4917934SMark.Phalan@Sun.COM static unsigned short 4920Sstevel@tonic-gate load_16_le (unsigned char *p) 4930Sstevel@tonic-gate { 4940Sstevel@tonic-gate return (p[0] | (p[1] << 8)); 4950Sstevel@tonic-gate } 496781Sgtb static unsigned int 4970Sstevel@tonic-gate load_32_be (unsigned char *p) 4980Sstevel@tonic-gate { 4990Sstevel@tonic-gate return (p[3] | (p[2] << 8) | (p[1] << 16) | (p[0] << 24)); 5000Sstevel@tonic-gate } 501781Sgtb static unsigned int 5020Sstevel@tonic-gate load_32_le (unsigned char *p) 5030Sstevel@tonic-gate { 5040Sstevel@tonic-gate return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24)); 5050Sstevel@tonic-gate } 5067934SMark.Phalan@Sun.COM static UINT64_TYPE 5070Sstevel@tonic-gate load_64_be (unsigned char *p) 5080Sstevel@tonic-gate { 5090Sstevel@tonic-gate return ((UINT64_TYPE)load_32_be(p) << 32) | load_32_be(p+4); 5100Sstevel@tonic-gate } 5117934SMark.Phalan@Sun.COM static UINT64_TYPE 5120Sstevel@tonic-gate load_64_le (unsigned char *p) 5130Sstevel@tonic-gate { 5140Sstevel@tonic-gate return ((UINT64_TYPE)load_32_le(p+4) << 32) | load_32_le(p); 5150Sstevel@tonic-gate } 5167934SMark.Phalan@Sun.COM #endif 5175053Sgtb 5185053Sgtb /* Make the interfaces to getpwnam and getpwuid consistent. 5195053Sgtb Model the wrappers on the POSIX thread-safe versions, but 5205053Sgtb use the unsafe system versions if the safe ones don't exist 5215053Sgtb or we can't figure out their interfaces. */ 5225053Sgtb /* SUNW15resync - just have Solaris relevant ones */ 5235053Sgtb 5245053Sgtb #define k5_getpwnam_r(NAME, REC, BUF, BUFSIZE, OUT) \ 5255053Sgtb (*(OUT) = getpwnam_r(NAME,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0) 5265053Sgtb 5275053Sgtb #define k5_getpwuid_r(UID, REC, BUF, BUFSIZE, OUT) \ 5285053Sgtb (*(OUT) = getpwuid_r(UID,REC,BUF,BUFSIZE), *(OUT) == NULL ? -1 : 0) 5295053Sgtb 530*10598SGlenn.Barry@Sun.COM /* Return true if the snprintf return value RESULT reflects a buffer 531*10598SGlenn.Barry@Sun.COM overflow for the buffer size SIZE. 532*10598SGlenn.Barry@Sun.COM 533*10598SGlenn.Barry@Sun.COM We cast the result to unsigned int for two reasons. First, old 534*10598SGlenn.Barry@Sun.COM implementations of snprintf (such as the one in Solaris 9 and 535*10598SGlenn.Barry@Sun.COM prior) return -1 on a buffer overflow. Casting the result to -1 536*10598SGlenn.Barry@Sun.COM will convert that value to UINT_MAX, which should compare larger 537*10598SGlenn.Barry@Sun.COM than any reasonable buffer size. Second, comparing signed and 538*10598SGlenn.Barry@Sun.COM unsigned integers will generate warnings with some compilers, and 539*10598SGlenn.Barry@Sun.COM can have unpredictable results, particularly when the relative 540*10598SGlenn.Barry@Sun.COM widths of the types is not known (size_t may be the same width as 541*10598SGlenn.Barry@Sun.COM int or larger). 542*10598SGlenn.Barry@Sun.COM */ 543*10598SGlenn.Barry@Sun.COM #define SNPRINTF_OVERFLOW(result, size) \ 544*10598SGlenn.Barry@Sun.COM ((unsigned int)(result) >= (size_t)(size)) 5455053Sgtb 5460Sstevel@tonic-gate #endif /* K5_PLATFORM_H */ 547