root/source3/lib/util.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_global_myname
  2. global_myname
  3. set_global_myworkgroup
  4. lp_workgroup
  5. set_global_scope
  6. global_scope
  7. free_netbios_names_array
  8. allocate_my_netbios_names_array
  9. set_my_netbios_names
  10. gfree_names
  11. gfree_all
  12. my_netbios_names
  13. set_netbios_aliases
  14. init_names
  15. user_auth_info_init
  16. get_cmdline_auth_info_username
  17. set_cmdline_auth_info_username
  18. get_cmdline_auth_info_password
  19. set_cmdline_auth_info_password
  20. set_cmdline_auth_info_signing_state
  21. get_cmdline_auth_info_signing_state
  22. set_cmdline_auth_info_use_kerberos
  23. get_cmdline_auth_info_use_kerberos
  24. set_cmdline_auth_info_fallback_after_kerberos
  25. get_cmdline_auth_info_fallback_after_kerberos
  26. set_cmdline_auth_info_use_krb5_ticket
  27. set_cmdline_auth_info_smb_encrypt
  28. set_cmdline_auth_info_use_machine_account
  29. get_cmdline_auth_info_got_pass
  30. get_cmdline_auth_info_smb_encrypt
  31. get_cmdline_auth_info_use_machine_account
  32. get_cmdline_auth_info_copy
  33. set_cmdline_auth_info_machine_account_creds
  34. set_cmdline_auth_info_getpass
  35. add_gid_to_array_unique
  36. file_exist_stat
  37. socket_exist
  38. directory_exist_stat
  39. get_file_size_stat
  40. get_file_size
  41. attrib_string
  42. show_msg
  43. smb_set_enclen
  44. smb_setlen
  45. set_message_bcc
  46. message_push_blob
  47. dos_clean_name
  48. unix_clean_name
  49. clean_name
  50. write_data_at_offset
  51. smb_msleep
  52. reinit_after_fork
  53. yesno
  54. malloc_
  55. calloc_
  56. realloc_
  57. memalign_array
  58. calloc_array
  59. Realloc
  60. add_to_large_array
  61. get_mydnsdomname
  62. interpret_protocol
  63. strip_mount_options
  64. automount_lookup
  65. automount_lookup
  66. process_exists
  67. uidtoname
  68. gidtoname
  69. nametouid
  70. nametogid
  71. smb_panic
  72. log_stack_trace
  73. readdirname
  74. is_in_path
  75. set_namearray
  76. free_namearray
  77. fcntl_getlock
  78. is_myname
  79. is_myworkgroup
  80. ra_lanman_string
  81. get_remote_arch_str
  82. set_remote_arch
  83. get_remote_arch
  84. tab_depth
  85. str_checksum
  86. zero_free
  87. set_maxfiles
  88. smb_mkstemp
  89. smb_xmalloc_array
  90. smb_xvasprintf
  91. myhostname
  92. xx_path
  93. lock_path
  94. pid_path
  95. lib_path
  96. modules_path
  97. data_path
  98. state_path
  99. cache_path
  100. shlib_ext
  101. parent_dirname
  102. ms_has_wild
  103. ms_has_wild_w
  104. mask_match
  105. mask_match_search
  106. mask_match_list
  107. unix_do_match
  108. unix_wild_match
  109. name_to_fqdn
  110. talloc_append_blob
  111. map_share_mode_to_deny_mode
  112. procid_to_pid
  113. set_my_vnn
  114. get_my_vnn
  115. pid_to_procid
  116. procid_self
  117. server_id_self
  118. procid_equal
  119. cluster_id_equal
  120. procid_is_me
  121. interpret_pid
  122. procid_str
  123. procid_str_static
  124. procid_valid
  125. procid_is_local
  126. this_is_smp
  127. trans_oob
  128. is_offset_safe
  129. get_safe_ptr
  130. get_safe_str_ptr
  131. get_safe_SVAL
  132. get_safe_IVAL
  133. split_domain_user
  134. _talloc_zero_zeronull
  135. _talloc_memdup_zeronull
  136. _talloc_array_zeronull
  137. _talloc_zero_array_zeronull
  138. talloc_zeronull
  139. split_ntfs_stream_name
  140. is_valid_policy_hnd
  141. policy_hnd_equal
  142. strip_hostname

   1 /* 
   2    Unix SMB/CIFS implementation.
   3    Samba utility functions
   4    Copyright (C) Andrew Tridgell 1992-1998
   5    Copyright (C) Jeremy Allison 2001-2007
   6    Copyright (C) Simo Sorce 2001
   7    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
   8    Copyright (C) James Peach 2006
   9 
  10    This program is free software; you can redistribute it and/or modify
  11    it under the terms of the GNU General Public License as published by
  12    the Free Software Foundation; either version 3 of the License, or
  13    (at your option) any later version.
  14    
  15    This program is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18    GNU General Public License for more details.
  19    
  20    You should have received a copy of the GNU General Public License
  21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  22 */
  23 
  24 #include "includes.h"
  25 
  26 extern char *global_clobber_region_function;
  27 extern unsigned int global_clobber_region_line;
  28 
  29 /* Max allowable allococation - 256mb - 0x10000000 */
  30 #define MAX_ALLOC_SIZE (1024*1024*256)
  31 
  32 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
  33 #ifdef WITH_NISPLUS_HOME
  34 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
  35 /*
  36  * The following lines are needed due to buggy include files
  37  * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
  38  * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
  39  * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
  40  * an enum in /usr/include/rpcsvc/nis.h.
  41  */
  42 
  43 #if defined(GROUP)
  44 #undef GROUP
  45 #endif
  46 
  47 #if defined(GROUP_OBJ)
  48 #undef GROUP_OBJ
  49 #endif
  50 
  51 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
  52 
  53 #include <rpcsvc/nis.h>
  54 
  55 #endif /* WITH_NISPLUS_HOME */
  56 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
  57 
  58 enum protocol_types Protocol = PROTOCOL_COREPLUS;
  59 
  60 static enum remote_arch_types ra_type = RA_UNKNOWN;
  61 
  62 /***********************************************************************
  63  Definitions for all names.
  64 ***********************************************************************/
  65 
  66 static char *smb_myname;
  67 static char *smb_myworkgroup;
  68 static char *smb_scope;
  69 static int smb_num_netbios_names;
  70 static char **smb_my_netbios_names;
  71 
  72 /***********************************************************************
  73  Allocate and set myname. Ensure upper case.
  74 ***********************************************************************/
  75 
  76 bool set_global_myname(const char *myname)
     /* [<][>][^][v][top][bottom][index][help] */
  77 {
  78         SAFE_FREE(smb_myname);
  79         smb_myname = SMB_STRDUP(myname);
  80         if (!smb_myname)
  81                 return False;
  82         strupper_m(smb_myname);
  83         return True;
  84 }
  85 
  86 const char *global_myname(void)
     /* [<][>][^][v][top][bottom][index][help] */
  87 {
  88         return smb_myname;
  89 }
  90 
  91 /***********************************************************************
  92  Allocate and set myworkgroup. Ensure upper case.
  93 ***********************************************************************/
  94 
  95 bool set_global_myworkgroup(const char *myworkgroup)
     /* [<][>][^][v][top][bottom][index][help] */
  96 {
  97         SAFE_FREE(smb_myworkgroup);
  98         smb_myworkgroup = SMB_STRDUP(myworkgroup);
  99         if (!smb_myworkgroup)
 100                 return False;
 101         strupper_m(smb_myworkgroup);
 102         return True;
 103 }
 104 
 105 const char *lp_workgroup(void)
     /* [<][>][^][v][top][bottom][index][help] */
 106 {
 107         return smb_myworkgroup;
 108 }
 109 
 110 /***********************************************************************
 111  Allocate and set scope. Ensure upper case.
 112 ***********************************************************************/
 113 
 114 bool set_global_scope(const char *scope)
     /* [<][>][^][v][top][bottom][index][help] */
 115 {
 116         SAFE_FREE(smb_scope);
 117         smb_scope = SMB_STRDUP(scope);
 118         if (!smb_scope)
 119                 return False;
 120         strupper_m(smb_scope);
 121         return True;
 122 }
 123 
 124 /*********************************************************************
 125  Ensure scope is never null string.
 126 *********************************************************************/
 127 
 128 const char *global_scope(void)
     /* [<][>][^][v][top][bottom][index][help] */
 129 {
 130         if (!smb_scope)
 131                 set_global_scope("");
 132         return smb_scope;
 133 }
 134 
 135 static void free_netbios_names_array(void)
     /* [<][>][^][v][top][bottom][index][help] */
 136 {
 137         int i;
 138 
 139         for (i = 0; i < smb_num_netbios_names; i++)
 140                 SAFE_FREE(smb_my_netbios_names[i]);
 141 
 142         SAFE_FREE(smb_my_netbios_names);
 143         smb_num_netbios_names = 0;
 144 }
 145 
 146 static bool allocate_my_netbios_names_array(size_t number)
     /* [<][>][^][v][top][bottom][index][help] */
 147 {
 148         free_netbios_names_array();
 149 
 150         smb_num_netbios_names = number + 1;
 151         smb_my_netbios_names = SMB_MALLOC_ARRAY( char *, smb_num_netbios_names );
 152 
 153         if (!smb_my_netbios_names)
 154                 return False;
 155 
 156         memset(smb_my_netbios_names, '\0', sizeof(char *) * smb_num_netbios_names);
 157         return True;
 158 }
 159 
 160 static bool set_my_netbios_names(const char *name, int i)
     /* [<][>][^][v][top][bottom][index][help] */
 161 {
 162         SAFE_FREE(smb_my_netbios_names[i]);
 163 
 164         smb_my_netbios_names[i] = SMB_STRDUP(name);
 165         if (!smb_my_netbios_names[i])
 166                 return False;
 167         strupper_m(smb_my_netbios_names[i]);
 168         return True;
 169 }
 170 
 171 /***********************************************************************
 172  Free memory allocated to global objects
 173 ***********************************************************************/
 174 
 175 void gfree_names(void)
     /* [<][>][^][v][top][bottom][index][help] */
 176 {
 177         SAFE_FREE( smb_myname );
 178         SAFE_FREE( smb_myworkgroup );
 179         SAFE_FREE( smb_scope );
 180         free_netbios_names_array();
 181         free_local_machine_name();
 182 }
 183 
 184 void gfree_all( void )
     /* [<][>][^][v][top][bottom][index][help] */
 185 {
 186         gfree_names();
 187         gfree_loadparm();
 188         gfree_case_tables();
 189         gfree_charcnv();
 190         gfree_interfaces();
 191         gfree_debugsyms();
 192 }
 193 
 194 const char *my_netbios_names(int i)
     /* [<][>][^][v][top][bottom][index][help] */
 195 {
 196         return smb_my_netbios_names[i];
 197 }
 198 
 199 bool set_netbios_aliases(const char **str_array)
     /* [<][>][^][v][top][bottom][index][help] */
 200 {
 201         size_t namecount;
 202 
 203         /* Work out the max number of netbios aliases that we have */
 204         for( namecount=0; str_array && (str_array[namecount] != NULL); namecount++ )
 205                 ;
 206 
 207         if ( global_myname() && *global_myname())
 208                 namecount++;
 209 
 210         /* Allocate space for the netbios aliases */
 211         if (!allocate_my_netbios_names_array(namecount))
 212                 return False;
 213 
 214         /* Use the global_myname string first */
 215         namecount=0;
 216         if ( global_myname() && *global_myname()) {
 217                 set_my_netbios_names( global_myname(), namecount );
 218                 namecount++;
 219         }
 220 
 221         if (str_array) {
 222                 size_t i;
 223                 for ( i = 0; str_array[i] != NULL; i++) {
 224                         size_t n;
 225                         bool duplicate = False;
 226 
 227                         /* Look for duplicates */
 228                         for( n=0; n<namecount; n++ ) {
 229                                 if( strequal( str_array[i], my_netbios_names(n) ) ) {
 230                                         duplicate = True;
 231                                         break;
 232                                 }
 233                         }
 234                         if (!duplicate) {
 235                                 if (!set_my_netbios_names(str_array[i], namecount))
 236                                         return False;
 237                                 namecount++;
 238                         }
 239                 }
 240         }
 241         return True;
 242 }
 243 
 244 /****************************************************************************
 245   Common name initialization code.
 246 ****************************************************************************/
 247 
 248 bool init_names(void)
     /* [<][>][^][v][top][bottom][index][help] */
 249 {
 250         int n;
 251 
 252         if (global_myname() == NULL || *global_myname() == '\0') {
 253                 if (!set_global_myname(myhostname())) {
 254                         DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
 255                         return False;
 256                 }
 257         }
 258 
 259         if (!set_netbios_aliases(lp_netbios_aliases())) {
 260                 DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
 261                 return False;
 262         }
 263 
 264         set_local_machine_name(global_myname(),false);
 265 
 266         DEBUG( 5, ("Netbios name list:-\n") );
 267         for( n=0; my_netbios_names(n); n++ ) {
 268                 DEBUGADD( 5, ("my_netbios_names[%d]=\"%s\"\n",
 269                                         n, my_netbios_names(n) ) );
 270         }
 271 
 272         return( True );
 273 }
 274 
 275 /**************************************************************************n
 276   Code to cope with username/password auth options from the commandline.
 277   Used mainly in client tools.
 278 ****************************************************************************/
 279 
 280 struct user_auth_info *user_auth_info_init(TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 281 {
 282         struct user_auth_info *result;
 283 
 284         result = TALLOC_ZERO_P(mem_ctx, struct user_auth_info);
 285         if (result == NULL) {
 286                 return NULL;
 287         }
 288 
 289         result->signing_state = Undefined;
 290         return result;
 291 }
 292 
 293 const char *get_cmdline_auth_info_username(const struct user_auth_info *auth_info)
     /* [<][>][^][v][top][bottom][index][help] */
 294 {
 295         if (!auth_info->username) {
 296                 return "";
 297         }
 298         return auth_info->username;
 299 }
 300 
 301 void set_cmdline_auth_info_username(struct user_auth_info *auth_info,
     /* [<][>][^][v][top][bottom][index][help] */
 302                                     const char *username)
 303 {
 304         TALLOC_FREE(auth_info->username);
 305         auth_info->username = talloc_strdup(auth_info, username);
 306         if (!auth_info->username) {
 307                 exit(ENOMEM);
 308         }
 309 }
 310 
 311 const char *get_cmdline_auth_info_password(const struct user_auth_info *auth_info)
     /* [<][>][^][v][top][bottom][index][help] */
 312 {
 313         if (!auth_info->password) {
 314                 return "";
 315         }
 316         return auth_info->password;
 317 }
 318 
 319 void set_cmdline_auth_info_password(struct user_auth_info *auth_info,
     /* [<][>][^][v][top][bottom][index][help] */
 320                                     const char *password)
 321 {
 322         TALLOC_FREE(auth_info->password);
 323         if (password == NULL) {
 324                 password = "";
 325         }
 326         auth_info->password = talloc_strdup(auth_info, password);
 327         if (!auth_info->password) {
 328                 exit(ENOMEM);
 329         }
 330         auth_info->got_pass = true;
 331 }
 332 
 333 bool set_cmdline_auth_info_signing_state(struct user_auth_info *auth_info,
     /* [<][>][^][v][top][bottom][index][help] */
 334                                          const char *arg)
 335 {
 336         auth_info->signing_state = -1;
 337         if (strequal(arg, "off") || strequal(arg, "no") ||
 338                         strequal(arg, "false")) {
 339                 auth_info->signing_state = false;
 340         } else if (strequal(arg, "on") || strequal(arg, "yes") ||
 341                         strequal(arg, "true") || strequal(arg, "auto")) {
 342                 auth_info->signing_state = true;
 343         } else if (strequal(arg, "force") || strequal(arg, "required") ||
 344                         strequal(arg, "forced")) {
 345                 auth_info->signing_state = Required;
 346         } else {
 347                 return false;
 348         }
 349         return true;
 350 }
 351 
 352 int get_cmdline_auth_info_signing_state(const struct user_auth_info *auth_info)
     /* [<][>][^][v][top][bottom][index][help] */
 353 {
 354         return auth_info->signing_state;
 355 }
 356 
 357 void set_cmdline_auth_info_use_kerberos(struct user_auth_info *auth_info,
     /* [<][>][^][v][top][bottom][index][help] */
 358                                         bool b)
 359 {
 360         auth_info->use_kerberos = b;
 361 }
 362 
 363 bool get_cmdline_auth_info_use_kerberos(const struct user_auth_info *auth_info)
     /* [<][>][^][v][top][bottom][index][help] */
 364 {
 365         return auth_info->use_kerberos;
 366 }
 367 
 368 void set_cmdline_auth_info_fallback_after_kerberos(struct user_auth_info *auth_info,
     /* [<][>][^][v][top][bottom][index][help] */
 369                                         bool b)
 370 {
 371         auth_info->fallback_after_kerberos = b;
 372 }
 373 
 374 bool get_cmdline_auth_info_fallback_after_kerberos(const struct user_auth_info *auth_info)
     /* [<][>][^][v][top][bottom][index][help] */
 375 {
 376         return auth_info->fallback_after_kerberos;
 377 }
 378 
 379 /* This should only be used by lib/popt_common.c JRA */
 380 void set_cmdline_auth_info_use_krb5_ticket(struct user_auth_info *auth_info)
     /* [<][>][^][v][top][bottom][index][help] */
 381 {
 382         auth_info->use_kerberos = true;
 383         auth_info->got_pass = true;
 384 }
 385 
 386 /* This should only be used by lib/popt_common.c JRA */
 387 void set_cmdline_auth_info_smb_encrypt(struct user_auth_info *auth_info)
     /* [<][>][^][v][top][bottom][index][help] */
 388 {
 389         auth_info->smb_encrypt = true;
 390 }
 391 
 392 void set_cmdline_auth_info_use_machine_account(struct user_auth_info *auth_info)
     /* [<][>][^][v][top][bottom][index][help] */
 393 {
 394         auth_info->use_machine_account = true;
 395 }
 396 
 397 bool get_cmdline_auth_info_got_pass(const struct user_auth_info *auth_info)
     /* [<][>][^][v][top][bottom][index][help] */
 398 {
 399         return auth_info->got_pass;
 400 }
 401 
 402 bool get_cmdline_auth_info_smb_encrypt(const struct user_auth_info *auth_info)
     /* [<][>][^][v][top][bottom][index][help] */
 403 {
 404         return auth_info->smb_encrypt;
 405 }
 406 
 407 bool get_cmdline_auth_info_use_machine_account(const struct user_auth_info *auth_info)
     /* [<][>][^][v][top][bottom][index][help] */
 408 {
 409         return auth_info->use_machine_account;
 410 }
 411 
 412 struct user_auth_info *get_cmdline_auth_info_copy(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 413                                                   const struct user_auth_info *src)
 414 {
 415         struct user_auth_info *result;
 416 
 417         result = user_auth_info_init(mem_ctx);
 418         if (result == NULL) {
 419                 return NULL;
 420         }
 421 
 422         *result = *src;
 423 
 424         result->username = talloc_strdup(
 425                 result, get_cmdline_auth_info_username(src));
 426         result->password = talloc_strdup(
 427                 result, get_cmdline_auth_info_password(src));
 428         if ((result->username == NULL) || (result->password == NULL)) {
 429                 TALLOC_FREE(result);
 430                 return NULL;
 431         }
 432 
 433         return result;
 434 }
 435 
 436 bool set_cmdline_auth_info_machine_account_creds(struct user_auth_info *auth_info)
     /* [<][>][^][v][top][bottom][index][help] */
 437 {
 438         char *pass = NULL;
 439         char *account = NULL;
 440 
 441         if (!get_cmdline_auth_info_use_machine_account(auth_info)) {
 442                 return false;
 443         }
 444 
 445         if (!secrets_init()) {
 446                 d_printf("ERROR: Unable to open secrets database\n");
 447                 return false;
 448         }
 449 
 450         if (asprintf(&account, "%s$@%s", global_myname(), lp_realm()) < 0) {
 451                 return false;
 452         }
 453 
 454         pass = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
 455         if (!pass) {
 456                 d_printf("ERROR: Unable to fetch machine password for "
 457                         "%s in domain %s\n",
 458                         account, lp_workgroup());
 459                 SAFE_FREE(account);
 460                 return false;
 461         }
 462 
 463         set_cmdline_auth_info_username(auth_info, account);
 464         set_cmdline_auth_info_password(auth_info, pass);
 465 
 466         SAFE_FREE(account);
 467         SAFE_FREE(pass);
 468 
 469         return true;
 470 }
 471 
 472 /****************************************************************************
 473  Ensure we have a password if one not given.
 474 ****************************************************************************/
 475 
 476 void set_cmdline_auth_info_getpass(struct user_auth_info *auth_info)
     /* [<][>][^][v][top][bottom][index][help] */
 477 {
 478         char *label = NULL;
 479         char *pass;
 480         TALLOC_CTX *frame;
 481 
 482         if (get_cmdline_auth_info_got_pass(auth_info) ||
 483                         get_cmdline_auth_info_use_kerberos(auth_info)) {
 484                 /* Already got one... */
 485                 return;
 486         }
 487 
 488         frame = talloc_stackframe();
 489         label = talloc_asprintf(frame, "Enter %s's password: ",
 490                         get_cmdline_auth_info_username(auth_info));
 491         pass = getpass(label);
 492         if (pass) {
 493                 set_cmdline_auth_info_password(auth_info, pass);
 494         }
 495         TALLOC_FREE(frame);
 496 }
 497 
 498 /****************************************************************************
 499  Add a gid to an array of gids if it's not already there.
 500 ****************************************************************************/
 501 
 502 bool add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
     /* [<][>][^][v][top][bottom][index][help] */
 503                              gid_t **gids, size_t *num_gids)
 504 {
 505         int i;
 506 
 507         if ((*num_gids != 0) && (*gids == NULL)) {
 508                 /*
 509                  * A former call to this routine has failed to allocate memory
 510                  */
 511                 return False;
 512         }
 513 
 514         for (i=0; i<*num_gids; i++) {
 515                 if ((*gids)[i] == gid) {
 516                         return True;
 517                 }
 518         }
 519 
 520         *gids = TALLOC_REALLOC_ARRAY(mem_ctx, *gids, gid_t, *num_gids+1);
 521         if (*gids == NULL) {
 522                 *num_gids = 0;
 523                 return False;
 524         }
 525 
 526         (*gids)[*num_gids] = gid;
 527         *num_gids += 1;
 528         return True;
 529 }
 530 
 531 /*******************************************************************
 532  Check if a file exists - call vfs_file_exist for samba files.
 533 ********************************************************************/
 534 
 535 bool file_exist_stat(const char *fname,SMB_STRUCT_STAT *sbuf)
     /* [<][>][^][v][top][bottom][index][help] */
 536 {
 537         SMB_STRUCT_STAT st;
 538         if (!sbuf)
 539                 sbuf = &st;
 540   
 541         if (sys_stat(fname,sbuf) != 0) 
 542                 return(False);
 543 
 544         return((S_ISREG(sbuf->st_mode)) || (S_ISFIFO(sbuf->st_mode)));
 545 }
 546 
 547 /*******************************************************************
 548  Check if a unix domain socket exists - call vfs_file_exist for samba files.
 549 ********************************************************************/
 550 
 551 bool socket_exist(const char *fname)
     /* [<][>][^][v][top][bottom][index][help] */
 552 {
 553         SMB_STRUCT_STAT st;
 554         if (sys_stat(fname,&st) != 0) 
 555                 return(False);
 556 
 557         return S_ISSOCK(st.st_mode);
 558 }
 559 
 560 /*******************************************************************
 561  Check if a directory exists.
 562 ********************************************************************/
 563 
 564 bool directory_exist_stat(char *dname,SMB_STRUCT_STAT *st)
     /* [<][>][^][v][top][bottom][index][help] */
 565 {
 566         SMB_STRUCT_STAT st2;
 567         bool ret;
 568 
 569         if (!st)
 570                 st = &st2;
 571 
 572         if (sys_stat(dname,st) != 0) 
 573                 return(False);
 574 
 575         ret = S_ISDIR(st->st_mode);
 576         if(!ret)
 577                 errno = ENOTDIR;
 578         return ret;
 579 }
 580 
 581 /*******************************************************************
 582  Returns the size in bytes of the named given the stat struct.
 583 ********************************************************************/
 584 
 585 uint64_t get_file_size_stat(const SMB_STRUCT_STAT *sbuf)
     /* [<][>][^][v][top][bottom][index][help] */
 586 {
 587         return sbuf->st_size;
 588 }
 589 
 590 /*******************************************************************
 591  Returns the size in bytes of the named file.
 592 ********************************************************************/
 593 
 594 SMB_OFF_T get_file_size(char *file_name)
     /* [<][>][^][v][top][bottom][index][help] */
 595 {
 596         SMB_STRUCT_STAT buf;
 597         buf.st_size = 0;
 598         if(sys_stat(file_name,&buf) != 0)
 599                 return (SMB_OFF_T)-1;
 600         return get_file_size_stat(&buf);
 601 }
 602 
 603 /*******************************************************************
 604  Return a string representing an attribute for a file.
 605 ********************************************************************/
 606 
 607 char *attrib_string(uint16 mode)
     /* [<][>][^][v][top][bottom][index][help] */
 608 {
 609         fstring attrstr;
 610 
 611         attrstr[0] = 0;
 612 
 613         if (mode & aVOLID) fstrcat(attrstr,"V");
 614         if (mode & aDIR) fstrcat(attrstr,"D");
 615         if (mode & aARCH) fstrcat(attrstr,"A");
 616         if (mode & aHIDDEN) fstrcat(attrstr,"H");
 617         if (mode & aSYSTEM) fstrcat(attrstr,"S");
 618         if (mode & aRONLY) fstrcat(attrstr,"R");          
 619 
 620         return talloc_strdup(talloc_tos(), attrstr);
 621 }
 622 
 623 /*******************************************************************
 624  Show a smb message structure.
 625 ********************************************************************/
 626 
 627 void show_msg(char *buf)
     /* [<][>][^][v][top][bottom][index][help] */
 628 {
 629         int i;
 630         int bcc=0;
 631 
 632         if (!DEBUGLVL(5))
 633                 return;
 634         
 635         DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
 636                         smb_len(buf),
 637                         (int)CVAL(buf,smb_com),
 638                         (int)CVAL(buf,smb_rcls),
 639                         (int)CVAL(buf,smb_reh),
 640                         (int)SVAL(buf,smb_err),
 641                         (int)CVAL(buf,smb_flg),
 642                         (int)SVAL(buf,smb_flg2)));
 643         DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
 644                         (int)SVAL(buf,smb_tid),
 645                         (int)SVAL(buf,smb_pid),
 646                         (int)SVAL(buf,smb_uid),
 647                         (int)SVAL(buf,smb_mid)));
 648         DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct)));
 649 
 650         for (i=0;i<(int)CVAL(buf,smb_wct);i++)
 651                 DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
 652                         SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
 653         
 654         bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
 655 
 656         DEBUGADD(5,("smb_bcc=%d\n",bcc));
 657 
 658         if (DEBUGLEVEL < 10)
 659                 return;
 660 
 661         if (DEBUGLEVEL < 50)
 662                 bcc = MIN(bcc, 512);
 663 
 664         dump_data(10, (uint8 *)smb_buf(buf), bcc);      
 665 }
 666 
 667 /*******************************************************************
 668  Set the length and marker of an encrypted smb packet.
 669 ********************************************************************/
 670 
 671 void smb_set_enclen(char *buf,int len,uint16 enc_ctx_num)
     /* [<][>][^][v][top][bottom][index][help] */
 672 {
 673         _smb_setlen(buf,len);
 674 
 675         SCVAL(buf,4,0xFF);
 676         SCVAL(buf,5,'E');
 677         SSVAL(buf,6,enc_ctx_num);
 678 }
 679 
 680 /*******************************************************************
 681  Set the length and marker of an smb packet.
 682 ********************************************************************/
 683 
 684 void smb_setlen(char *buf,int len)
     /* [<][>][^][v][top][bottom][index][help] */
 685 {
 686         _smb_setlen(buf,len);
 687 
 688         SCVAL(buf,4,0xFF);
 689         SCVAL(buf,5,'S');
 690         SCVAL(buf,6,'M');
 691         SCVAL(buf,7,'B');
 692 }
 693 
 694 /*******************************************************************
 695  Setup only the byte count for a smb message.
 696 ********************************************************************/
 697 
 698 int set_message_bcc(char *buf,int num_bytes)
     /* [<][>][^][v][top][bottom][index][help] */
 699 {
 700         int num_words = CVAL(buf,smb_wct);
 701         SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
 702         _smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
 703         return (smb_size + num_words*2 + num_bytes);
 704 }
 705 
 706 /*******************************************************************
 707  Add a data blob to the end of a smb_buf, adjusting bcc and smb_len.
 708  Return the bytes added
 709 ********************************************************************/
 710 
 711 ssize_t message_push_blob(uint8 **outbuf, DATA_BLOB blob)
     /* [<][>][^][v][top][bottom][index][help] */
 712 {
 713         size_t newlen = smb_len(*outbuf) + 4 + blob.length;
 714         uint8 *tmp;
 715 
 716         if (!(tmp = TALLOC_REALLOC_ARRAY(NULL, *outbuf, uint8, newlen))) {
 717                 DEBUG(0, ("talloc failed\n"));
 718                 return -1;
 719         }
 720         *outbuf = tmp;
 721 
 722         memcpy(tmp + smb_len(tmp) + 4, blob.data, blob.length);
 723         set_message_bcc((char *)tmp, smb_buflen(tmp) + blob.length);
 724         return blob.length;
 725 }
 726 
 727 /*******************************************************************
 728  Reduce a file name, removing .. elements.
 729 ********************************************************************/
 730 
 731 static char *dos_clean_name(TALLOC_CTX *ctx, const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
 732 {
 733         char *p = NULL;
 734         char *str = NULL;
 735 
 736         DEBUG(3,("dos_clean_name [%s]\n",s));
 737 
 738         /* remove any double slashes */
 739         str = talloc_all_string_sub(ctx, s, "\\\\", "\\");
 740         if (!str) {
 741                 return NULL;
 742         }
 743 
 744         /* Remove leading .\\ characters */
 745         if(strncmp(str, ".\\", 2) == 0) {
 746                 trim_string(str, ".\\", NULL);
 747                 if(*str == 0) {
 748                         str = talloc_strdup(ctx, ".\\");
 749                         if (!str) {
 750                                 return NULL;
 751                         }
 752                 }
 753         }
 754 
 755         while ((p = strstr_m(str,"\\..\\")) != NULL) {
 756                 char *s1;
 757 
 758                 *p = 0;
 759                 s1 = p+3;
 760 
 761                 if ((p=strrchr_m(str,'\\')) != NULL) {
 762                         *p = 0;
 763                 } else {
 764                         *str = 0;
 765                 }
 766                 str = talloc_asprintf(ctx,
 767                                 "%s%s",
 768                                 str,
 769                                 s1);
 770                 if (!str) {
 771                         return NULL;
 772                 }
 773         }
 774 
 775         trim_string(str,NULL,"\\..");
 776         return talloc_all_string_sub(ctx, str, "\\.\\", "\\");
 777 }
 778 
 779 /*******************************************************************
 780  Reduce a file name, removing .. elements.
 781 ********************************************************************/
 782 
 783 char *unix_clean_name(TALLOC_CTX *ctx, const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
 784 {
 785         char *p = NULL;
 786         char *str = NULL;
 787 
 788         DEBUG(3,("unix_clean_name [%s]\n",s));
 789 
 790         /* remove any double slashes */
 791         str = talloc_all_string_sub(ctx, s, "//","/");
 792         if (!str) {
 793                 return NULL;
 794         }
 795 
 796         /* Remove leading ./ characters */
 797         if(strncmp(str, "./", 2) == 0) {
 798                 trim_string(str, "./", NULL);
 799                 if(*str == 0) {
 800                         str = talloc_strdup(ctx, "./");
 801                         if (!str) {
 802                                 return NULL;
 803                         }
 804                 }
 805         }
 806 
 807         while ((p = strstr_m(str,"/../")) != NULL) {
 808                 char *s1;
 809 
 810                 *p = 0;
 811                 s1 = p+3;
 812 
 813                 if ((p=strrchr_m(str,'/')) != NULL) {
 814                         *p = 0;
 815                 } else {
 816                         *str = 0;
 817                 }
 818                 str = talloc_asprintf(ctx,
 819                                 "%s%s",
 820                                 str,
 821                                 s1);
 822                 if (!str) {
 823                         return NULL;
 824                 }
 825         }
 826 
 827         trim_string(str,NULL,"/..");
 828         return talloc_all_string_sub(ctx, str, "/./", "/");
 829 }
 830 
 831 char *clean_name(TALLOC_CTX *ctx, const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
 832 {
 833         char *str = dos_clean_name(ctx, s);
 834         if (!str) {
 835                 return NULL;
 836         }
 837         return unix_clean_name(ctx, str);
 838 }
 839 
 840 /*******************************************************************
 841  Write data into an fd at a given offset. Ignore seek errors.
 842 ********************************************************************/
 843 
 844 ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos)
     /* [<][>][^][v][top][bottom][index][help] */
 845 {
 846         size_t total=0;
 847         ssize_t ret;
 848 
 849         if (pos == (SMB_OFF_T)-1) {
 850                 return write_data(fd, buffer, N);
 851         }
 852 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
 853         while (total < N) {
 854                 ret = sys_pwrite(fd,buffer + total,N - total, pos);
 855                 if (ret == -1 && errno == ESPIPE) {
 856                         return write_data(fd, buffer + total,N - total);
 857                 }
 858                 if (ret == -1) {
 859                         DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
 860                         return -1;
 861                 }
 862                 if (ret == 0) {
 863                         return total;
 864                 }
 865                 total += ret;
 866                 pos += ret;
 867         }
 868         return (ssize_t)total;
 869 #else
 870         /* Use lseek and write_data. */
 871         if (sys_lseek(fd, pos, SEEK_SET) == -1) {
 872                 if (errno != ESPIPE) {
 873                         return -1;
 874                 }
 875         }
 876         return write_data(fd, buffer, N);
 877 #endif
 878 }
 879 
 880 /*******************************************************************
 881  Sleep for a specified number of milliseconds.
 882 ********************************************************************/
 883 
 884 void smb_msleep(unsigned int t)
     /* [<][>][^][v][top][bottom][index][help] */
 885 {
 886 #if defined(HAVE_NANOSLEEP)
 887         struct timespec tval;
 888         int ret;
 889 
 890         tval.tv_sec = t/1000;
 891         tval.tv_nsec = 1000000*(t%1000);
 892 
 893         do {
 894                 errno = 0;
 895                 ret = nanosleep(&tval, &tval);
 896         } while (ret < 0 && errno == EINTR && (tval.tv_sec > 0 || tval.tv_nsec > 0));
 897 #else
 898         unsigned int tdiff=0;
 899         struct timeval tval,t1,t2;  
 900         fd_set fds;
 901 
 902         GetTimeOfDay(&t1);
 903         t2 = t1;
 904   
 905         while (tdiff < t) {
 906                 tval.tv_sec = (t-tdiff)/1000;
 907                 tval.tv_usec = 1000*((t-tdiff)%1000);
 908 
 909                 /* Never wait for more than 1 sec. */
 910                 if (tval.tv_sec > 1) {
 911                         tval.tv_sec = 1; 
 912                         tval.tv_usec = 0;
 913                 }
 914 
 915                 FD_ZERO(&fds);
 916                 errno = 0;
 917                 sys_select_intr(0,&fds,NULL,NULL,&tval);
 918 
 919                 GetTimeOfDay(&t2);
 920                 if (t2.tv_sec < t1.tv_sec) {
 921                         /* Someone adjusted time... */
 922                         t1 = t2;
 923                 }
 924 
 925                 tdiff = TvalDiff(&t1,&t2);
 926         }
 927 #endif
 928 }
 929 
 930 NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 931                        struct event_context *ev_ctx,
 932                        bool parent_longlived)
 933 {
 934         NTSTATUS status = NT_STATUS_OK;
 935 
 936         /* Reset the state of the random
 937          * number generation system, so
 938          * children do not get the same random
 939          * numbers as each other */
 940         set_need_random_reseed();
 941 
 942         /* tdb needs special fork handling */
 943         if (tdb_reopen_all(parent_longlived ? 1 : 0) == -1) {
 944                 DEBUG(0,("tdb_reopen_all failed.\n"));
 945                 status = NT_STATUS_OPEN_FAILED;
 946                 goto done;
 947         }
 948 
 949         if (ev_ctx) {
 950                 event_context_reinit(ev_ctx);
 951         }
 952 
 953         if (msg_ctx) {
 954                 /*
 955                  * For clustering, we need to re-init our ctdbd connection after the
 956                  * fork
 957                  */
 958                 status = messaging_reinit(msg_ctx);
 959                 if (!NT_STATUS_IS_OK(status)) {
 960                         DEBUG(0,("messaging_reinit() failed: %s\n",
 961                                  nt_errstr(status)));
 962                 }
 963         }
 964  done:
 965         return status;
 966 }
 967 
 968 /****************************************************************************
 969  Put up a yes/no prompt.
 970 ****************************************************************************/
 971 
 972 bool yesno(const char *p)
     /* [<][>][^][v][top][bottom][index][help] */
 973 {
 974         char ans[20];
 975         printf("%s",p);
 976 
 977         if (!fgets(ans,sizeof(ans)-1,stdin))
 978                 return(False);
 979 
 980         if (*ans == 'y' || *ans == 'Y')
 981                 return(True);
 982 
 983         return(False);
 984 }
 985 
 986 #if defined(PARANOID_MALLOC_CHECKER)
 987 
 988 /****************************************************************************
 989  Internal malloc wrapper. Externally visible.
 990 ****************************************************************************/
 991 
 992 void *malloc_(size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
 993 {
 994         if (size == 0) {
 995                 return NULL;
 996         }
 997 #undef malloc
 998         return malloc(size);
 999 #define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
1000 }
1001 
1002 /****************************************************************************
1003  Internal calloc wrapper. Not externally visible.
1004 ****************************************************************************/
1005 
1006 static void *calloc_(size_t count, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
1007 {
1008         if (size == 0 || count == 0) {
1009                 return NULL;
1010         }
1011 #undef calloc
1012         return calloc(count, size);
1013 #define calloc(n,s) __ERROR_DONT_USE_CALLOC_DIRECTLY
1014 }
1015 
1016 /****************************************************************************
1017  Internal realloc wrapper. Not externally visible.
1018 ****************************************************************************/
1019 
1020 static void *realloc_(void *ptr, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
1021 {
1022 #undef realloc
1023         return realloc(ptr, size);
1024 #define realloc(p,s) __ERROR_DONT_USE_RELLOC_DIRECTLY
1025 }
1026 
1027 #endif /* PARANOID_MALLOC_CHECKER */
1028 
1029 /****************************************************************************
1030  Type-safe memalign
1031 ****************************************************************************/
1032 
1033 void *memalign_array(size_t el_size, size_t align, unsigned int count)
     /* [<][>][^][v][top][bottom][index][help] */
1034 {
1035         if (count >= MAX_ALLOC_SIZE/el_size) {
1036                 return NULL;
1037         }
1038 
1039         return sys_memalign(align, el_size*count);
1040 }
1041 
1042 /****************************************************************************
1043  Type-safe calloc.
1044 ****************************************************************************/
1045 
1046 void *calloc_array(size_t size, size_t nmemb)
     /* [<][>][^][v][top][bottom][index][help] */
1047 {
1048         if (nmemb >= MAX_ALLOC_SIZE/size) {
1049                 return NULL;
1050         }
1051         if (size == 0 || nmemb == 0) {
1052                 return NULL;
1053         }
1054 #if defined(PARANOID_MALLOC_CHECKER)
1055         return calloc_(nmemb, size);
1056 #else
1057         return calloc(nmemb, size);
1058 #endif
1059 }
1060 
1061 /****************************************************************************
1062  Expand a pointer to be a particular size.
1063  Note that this version of Realloc has an extra parameter that decides
1064  whether to free the passed in storage on allocation failure or if the
1065  new size is zero.
1066 
1067  This is designed for use in the typical idiom of :
1068 
1069  p = SMB_REALLOC(p, size)
1070  if (!p) {
1071     return error;
1072  }
1073 
1074  and not to have to keep track of the old 'p' contents to free later, nor
1075  to worry if the size parameter was zero. In the case where NULL is returned
1076  we guarentee that p has been freed.
1077 
1078  If free later semantics are desired, then pass 'free_old_on_error' as False which
1079  guarentees that the old contents are not freed on error, even if size == 0. To use
1080  this idiom use :
1081 
1082  tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
1083  if (!tmp) {
1084     SAFE_FREE(p);
1085     return error;
1086  } else {
1087     p = tmp;
1088  }
1089 
1090  Changes were instigated by Coverity error checking. JRA.
1091 ****************************************************************************/
1092 
1093 void *Realloc(void *p, size_t size, bool free_old_on_error)
     /* [<][>][^][v][top][bottom][index][help] */
1094 {
1095         void *ret=NULL;
1096 
1097         if (size == 0) {
1098                 if (free_old_on_error) {
1099                         SAFE_FREE(p);
1100                 }
1101                 DEBUG(2,("Realloc asked for 0 bytes\n"));
1102                 return NULL;
1103         }
1104 
1105 #if defined(PARANOID_MALLOC_CHECKER)
1106         if (!p) {
1107                 ret = (void *)malloc_(size);
1108         } else {
1109                 ret = (void *)realloc_(p,size);
1110         }
1111 #else
1112         if (!p) {
1113                 ret = (void *)malloc(size);
1114         } else {
1115                 ret = (void *)realloc(p,size);
1116         }
1117 #endif
1118 
1119         if (!ret) {
1120                 if (free_old_on_error && p) {
1121                         SAFE_FREE(p);
1122                 }
1123                 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
1124         }
1125 
1126         return(ret);
1127 }
1128 
1129 /****************************************************************************
1130  (Hopefully) efficient array append.
1131 ****************************************************************************/
1132 
1133 void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
     /* [<][>][^][v][top][bottom][index][help] */
1134                         void *element, void *_array, uint32 *num_elements,
1135                         ssize_t *array_size)
1136 {
1137         void **array = (void **)_array;
1138 
1139         if (*array_size < 0) {
1140                 return;
1141         }
1142 
1143         if (*array == NULL) {
1144                 if (*array_size == 0) {
1145                         *array_size = 128;
1146                 }
1147 
1148                 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
1149                         goto error;
1150                 }
1151 
1152                 *array = TALLOC(mem_ctx, element_size * (*array_size));
1153                 if (*array == NULL) {
1154                         goto error;
1155                 }
1156         }
1157 
1158         if (*num_elements == *array_size) {
1159                 *array_size *= 2;
1160 
1161                 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
1162                         goto error;
1163                 }
1164 
1165                 *array = TALLOC_REALLOC(mem_ctx, *array,
1166                                         element_size * (*array_size));
1167 
1168                 if (*array == NULL) {
1169                         goto error;
1170                 }
1171         }
1172 
1173         memcpy((char *)(*array) + element_size*(*num_elements),
1174                element, element_size);
1175         *num_elements += 1;
1176 
1177         return;
1178 
1179  error:
1180         *num_elements = 0;
1181         *array_size = -1;
1182 }
1183 
1184 /****************************************************************************
1185  Get my own domain name, or "" if we have none.
1186 ****************************************************************************/
1187 
1188 char *get_mydnsdomname(TALLOC_CTX *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
1189 {
1190         const char *domname;
1191         char *p;
1192 
1193         domname = get_mydnsfullname();
1194         if (!domname) {
1195                 return NULL;
1196         }
1197 
1198         p = strchr_m(domname, '.');
1199         if (p) {
1200                 p++;
1201                 return talloc_strdup(ctx, p);
1202         } else {
1203                 return talloc_strdup(ctx, "");
1204         }
1205 }
1206 
1207 /****************************************************************************
1208  Interpret a protocol description string, with a default.
1209 ****************************************************************************/
1210 
1211 int interpret_protocol(const char *str,int def)
     /* [<][>][^][v][top][bottom][index][help] */
1212 {
1213         if (strequal(str,"NT1"))
1214                 return(PROTOCOL_NT1);
1215         if (strequal(str,"LANMAN2"))
1216                 return(PROTOCOL_LANMAN2);
1217         if (strequal(str,"LANMAN1"))
1218                 return(PROTOCOL_LANMAN1);
1219         if (strequal(str,"CORE"))
1220                 return(PROTOCOL_CORE);
1221         if (strequal(str,"COREPLUS"))
1222                 return(PROTOCOL_COREPLUS);
1223         if (strequal(str,"CORE+"))
1224                 return(PROTOCOL_COREPLUS);
1225   
1226         DEBUG(0,("Unrecognised protocol level %s\n",str));
1227   
1228         return(def);
1229 }
1230 
1231 
1232 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1233 /******************************************************************
1234  Remove any mount options such as -rsize=2048,wsize=2048 etc.
1235  Based on a fix from <Thomas.Hepper@icem.de>.
1236  Returns a malloc'ed string.
1237 *******************************************************************/
1238 
1239 static char *strip_mount_options(TALLOC_CTX *ctx, const char *str)
     /* [<][>][^][v][top][bottom][index][help] */
1240 {
1241         if (*str == '-') {
1242                 const char *p = str;
1243                 while(*p && !isspace(*p))
1244                         p++;
1245                 while(*p && isspace(*p))
1246                         p++;
1247                 if(*p) {
1248                         return talloc_strdup(ctx, p);
1249                 }
1250         }
1251         return NULL;
1252 }
1253 
1254 /*******************************************************************
1255  Patch from jkf@soton.ac.uk
1256  Split Luke's automount_server into YP lookup and string splitter
1257  so can easily implement automount_path().
1258  Returns a malloc'ed string.
1259 *******************************************************************/
1260 
1261 #ifdef WITH_NISPLUS_HOME
1262 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
     /* [<][>][^][v][top][bottom][index][help] */
1263 {
1264         char *value = NULL;
1265 
1266         char *nis_map = (char *)lp_nis_home_map_name();
1267 
1268         char buffer[NIS_MAXATTRVAL + 1];
1269         nis_result *result;
1270         nis_object *object;
1271         entry_obj  *entry;
1272 
1273         snprintf(buffer, sizeof(buffer), "[key=%s],%s", user_name, nis_map);
1274         DEBUG(5, ("NIS+ querystring: %s\n", buffer));
1275 
1276         if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
1277                 if (result->status != NIS_SUCCESS) {
1278                         DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
1279                 } else {
1280                         object = result->objects.objects_val;
1281                         if (object->zo_data.zo_type == ENTRY_OBJ) {
1282                                 entry = &object->zo_data.objdata_u.en_data;
1283                                 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
1284                                 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
1285 
1286                                 value = talloc_strdup(ctx,
1287                                                 entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
1288                                 if (!value) {
1289                                         nis_freeresult(result);
1290                                         return NULL;
1291                                 }
1292                                 value = talloc_string_sub(ctx,
1293                                                 value,
1294                                                 "&",
1295                                                 user_name);
1296                         }
1297                 }
1298         }
1299         nis_freeresult(result);
1300 
1301         if (value) {
1302                 value = strip_mount_options(ctx, value);
1303                 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n",
1304                                         user_name, value));
1305         }
1306         return value;
1307 }
1308 #else /* WITH_NISPLUS_HOME */
1309 
1310 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
     /* [<][>][^][v][top][bottom][index][help] */
1311 {
1312         char *value = NULL;
1313 
1314         int nis_error;        /* returned by yp all functions */
1315         char *nis_result;     /* yp_match inits this */
1316         int nis_result_len;  /* and set this */
1317         char *nis_domain;     /* yp_get_default_domain inits this */
1318         char *nis_map = (char *)lp_nis_home_map_name();
1319 
1320         if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
1321                 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
1322                 return NULL;
1323         }
1324 
1325         DEBUG(5, ("NIS Domain: %s\n", nis_domain));
1326 
1327         if ((nis_error = yp_match(nis_domain, nis_map, user_name,
1328                                         strlen(user_name), &nis_result,
1329                                         &nis_result_len)) == 0) {
1330                 value = talloc_strdup(ctx, nis_result);
1331                 if (!value) {
1332                         return NULL;
1333                 }
1334                 value = strip_mount_options(ctx, value);
1335         } else if(nis_error == YPERR_KEY) {
1336                 DEBUG(3, ("YP Key not found:  while looking up \"%s\" in map \"%s\"\n", 
1337                                 user_name, nis_map));
1338                 DEBUG(3, ("using defaults for server and home directory\n"));
1339         } else {
1340                 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n", 
1341                                 yperr_string(nis_error), user_name, nis_map));
1342         }
1343 
1344         if (value) {
1345                 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, value));
1346         }
1347         return value;
1348 }
1349 #endif /* WITH_NISPLUS_HOME */
1350 #endif
1351 
1352 /****************************************************************************
1353  Check if a process exists. Does this work on all unixes?
1354 ****************************************************************************/
1355 
1356 bool process_exists(const struct server_id pid)
     /* [<][>][^][v][top][bottom][index][help] */
1357 {
1358         if (procid_is_me(&pid)) {
1359                 return True;
1360         }
1361 
1362         if (procid_is_local(&pid)) {
1363                 return (kill(pid.pid,0) == 0 || errno != ESRCH);
1364         }
1365 
1366 #ifdef CLUSTER_SUPPORT
1367         return ctdbd_process_exists(messaging_ctdbd_connection(), pid.vnn,
1368                                     pid.pid);
1369 #else
1370         return False;
1371 #endif
1372 }
1373 
1374 /*******************************************************************
1375  Convert a uid into a user name.
1376 ********************************************************************/
1377 
1378 const char *uidtoname(uid_t uid)
     /* [<][>][^][v][top][bottom][index][help] */
1379 {
1380         TALLOC_CTX *ctx = talloc_tos();
1381         char *name = NULL;
1382         struct passwd *pass = NULL;
1383 
1384         pass = getpwuid_alloc(ctx,uid);
1385         if (pass) {
1386                 name = talloc_strdup(ctx,pass->pw_name);
1387                 TALLOC_FREE(pass);
1388         } else {
1389                 name = talloc_asprintf(ctx,
1390                                 "%ld",
1391                                 (long int)uid);
1392         }
1393         return name;
1394 }
1395 
1396 /*******************************************************************
1397  Convert a gid into a group name.
1398 ********************************************************************/
1399 
1400 char *gidtoname(gid_t gid)
     /* [<][>][^][v][top][bottom][index][help] */
1401 {
1402         struct group *grp;
1403 
1404         grp = getgrgid(gid);
1405         if (grp) {
1406                 return talloc_strdup(talloc_tos(), grp->gr_name);
1407         }
1408         else {
1409                 return talloc_asprintf(talloc_tos(),
1410                                         "%d",
1411                                         (int)gid);
1412         }
1413 }
1414 
1415 /*******************************************************************
1416  Convert a user name into a uid.
1417 ********************************************************************/
1418 
1419 uid_t nametouid(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
1420 {
1421         struct passwd *pass;
1422         char *p;
1423         uid_t u;
1424 
1425         pass = getpwnam_alloc(talloc_autofree_context(), name);
1426         if (pass) {
1427                 u = pass->pw_uid;
1428                 TALLOC_FREE(pass);
1429                 return u;
1430         }
1431 
1432         u = (uid_t)strtol(name, &p, 0);
1433         if ((p != name) && (*p == '\0'))
1434                 return u;
1435 
1436         return (uid_t)-1;
1437 }
1438 
1439 /*******************************************************************
1440  Convert a name to a gid_t if possible. Return -1 if not a group. 
1441 ********************************************************************/
1442 
1443 gid_t nametogid(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
1444 {
1445         struct group *grp;
1446         char *p;
1447         gid_t g;
1448 
1449         g = (gid_t)strtol(name, &p, 0);
1450         if ((p != name) && (*p == '\0'))
1451                 return g;
1452 
1453         grp = sys_getgrnam(name);
1454         if (grp)
1455                 return(grp->gr_gid);
1456         return (gid_t)-1;
1457 }
1458 
1459 /*******************************************************************
1460  Something really nasty happened - panic !
1461 ********************************************************************/
1462 
1463 void smb_panic(const char *const why)
     /* [<][>][^][v][top][bottom][index][help] */
1464 {
1465         char *cmd;
1466         int result;
1467 
1468 #ifdef DEVELOPER
1469         {
1470 
1471                 if (global_clobber_region_function) {
1472                         DEBUG(0,("smb_panic: clobber_region() last called from [%s(%u)]\n",
1473                                          global_clobber_region_function,
1474                                          global_clobber_region_line));
1475                 } 
1476         }
1477 #endif
1478 
1479         DEBUG(0,("PANIC (pid %llu): %s\n",
1480                     (unsigned long long)sys_getpid(), why));
1481         log_stack_trace();
1482 
1483         cmd = lp_panic_action();
1484         if (cmd && *cmd) {
1485                 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
1486                 result = system(cmd);
1487 
1488                 if (result == -1)
1489                         DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
1490                                           strerror(errno)));
1491                 else
1492                         DEBUG(0, ("smb_panic(): action returned status %d\n",
1493                                           WEXITSTATUS(result)));
1494         }
1495 
1496         dump_core();
1497 }
1498 
1499 /*******************************************************************
1500  Print a backtrace of the stack to the debug log. This function
1501  DELIBERATELY LEAKS MEMORY. The expectation is that you should
1502  exit shortly after calling it.
1503 ********************************************************************/
1504 
1505 #ifdef HAVE_LIBUNWIND_H
1506 #include <libunwind.h>
1507 #endif
1508 
1509 #ifdef HAVE_EXECINFO_H
1510 #include <execinfo.h>
1511 #endif
1512 
1513 #ifdef HAVE_LIBEXC_H
1514 #include <libexc.h>
1515 #endif
1516 
1517 void log_stack_trace(void)
     /* [<][>][^][v][top][bottom][index][help] */
1518 {
1519 #ifdef HAVE_LIBUNWIND
1520         /* Try to use libunwind before any other technique since on ia64
1521          * libunwind correctly walks the stack in more circumstances than
1522          * backtrace.
1523          */ 
1524         unw_cursor_t cursor;
1525         unw_context_t uc;
1526         unsigned i = 0;
1527 
1528         char procname[256];
1529         unw_word_t ip, sp, off;
1530 
1531         procname[sizeof(procname) - 1] = '\0';
1532 
1533         if (unw_getcontext(&uc) != 0) {
1534                 goto libunwind_failed;
1535         }
1536 
1537         if (unw_init_local(&cursor, &uc) != 0) {
1538                 goto libunwind_failed;
1539         }
1540 
1541         DEBUG(0, ("BACKTRACE:\n"));
1542 
1543         do {
1544             ip = sp = 0;
1545             unw_get_reg(&cursor, UNW_REG_IP, &ip);
1546             unw_get_reg(&cursor, UNW_REG_SP, &sp);
1547 
1548             switch (unw_get_proc_name(&cursor,
1549                         procname, sizeof(procname) - 1, &off) ) {
1550             case 0:
1551                     /* Name found. */
1552             case -UNW_ENOMEM:
1553                     /* Name truncated. */
1554                     DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
1555                             i, procname, (long long)off,
1556                             (long long)ip, (long long) sp));
1557                     break;
1558             default:
1559             /* case -UNW_ENOINFO: */
1560             /* case -UNW_EUNSPEC: */
1561                     /* No symbol name found. */
1562                     DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
1563                             i, "<unknown symbol>",
1564                             (long long)ip, (long long) sp));
1565             }
1566             ++i;
1567         } while (unw_step(&cursor) > 0);
1568 
1569         return;
1570 
1571 libunwind_failed:
1572         DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
1573 
1574 #elif HAVE_BACKTRACE_SYMBOLS
1575         void *backtrace_stack[BACKTRACE_STACK_SIZE];
1576         size_t backtrace_size;
1577         char **backtrace_strings;
1578 
1579         /* get the backtrace (stack frames) */
1580         backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
1581         backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
1582 
1583         DEBUG(0, ("BACKTRACE: %lu stack frames:\n", 
1584                   (unsigned long)backtrace_size));
1585         
1586         if (backtrace_strings) {
1587                 int i;
1588 
1589                 for (i = 0; i < backtrace_size; i++)
1590                         DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
1591 
1592                 /* Leak the backtrace_strings, rather than risk what free() might do */
1593         }
1594 
1595 #elif HAVE_LIBEXC
1596 
1597         /* The IRIX libexc library provides an API for unwinding the stack. See
1598          * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
1599          * since we are about to abort anyway, it hardly matters.
1600          */
1601 
1602 #define NAMESIZE 32 /* Arbitrary */
1603 
1604         __uint64_t      addrs[BACKTRACE_STACK_SIZE];
1605         char *          names[BACKTRACE_STACK_SIZE];
1606         char            namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
1607 
1608         int             i;
1609         int             levels;
1610 
1611         ZERO_ARRAY(addrs);
1612         ZERO_ARRAY(names);
1613         ZERO_ARRAY(namebuf);
1614 
1615         /* We need to be root so we can open our /proc entry to walk
1616          * our stack. It also helps when we want to dump core.
1617          */
1618         become_root();
1619 
1620         for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
1621                 names[i] = namebuf + (i * NAMESIZE);
1622         }
1623 
1624         levels = trace_back_stack(0, addrs, names,
1625                         BACKTRACE_STACK_SIZE, NAMESIZE - 1);
1626 
1627         DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
1628         for (i = 0; i < levels; i++) {
1629                 DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
1630         }
1631 #undef NAMESIZE
1632 
1633 #else
1634         DEBUG(0, ("unable to produce a stack trace on this platform\n"));
1635 #endif
1636 }
1637 
1638 /*******************************************************************
1639   A readdir wrapper which just returns the file name.
1640  ********************************************************************/
1641 
1642 const char *readdirname(SMB_STRUCT_DIR *p)
     /* [<][>][^][v][top][bottom][index][help] */
1643 {
1644         SMB_STRUCT_DIRENT *ptr;
1645         char *dname;
1646 
1647         if (!p)
1648                 return(NULL);
1649   
1650         ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
1651         if (!ptr)
1652                 return(NULL);
1653 
1654         dname = ptr->d_name;
1655 
1656 #ifdef NEXT2
1657         if (telldir(p) < 0)
1658                 return(NULL);
1659 #endif
1660 
1661 #ifdef HAVE_BROKEN_READDIR_NAME
1662         /* using /usr/ucb/cc is BAD */
1663         dname = dname - 2;
1664 #endif
1665 
1666         return talloc_strdup(talloc_tos(), dname);
1667 }
1668 
1669 /*******************************************************************
1670  Utility function used to decide if the last component 
1671  of a path matches a (possibly wildcarded) entry in a namelist.
1672 ********************************************************************/
1673 
1674 bool is_in_path(const char *name, name_compare_entry *namelist, bool case_sensitive)
     /* [<][>][^][v][top][bottom][index][help] */
1675 {
1676         const char *last_component;
1677 
1678         /* if we have no list it's obviously not in the path */
1679         if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
1680                 return False;
1681         }
1682 
1683         DEBUG(8, ("is_in_path: %s\n", name));
1684 
1685         /* Get the last component of the unix name. */
1686         last_component = strrchr_m(name, '/');
1687         if (!last_component) {
1688                 last_component = name;
1689         } else {
1690                 last_component++; /* Go past '/' */
1691         }
1692 
1693         for(; namelist->name != NULL; namelist++) {
1694                 if(namelist->is_wild) {
1695                         if (mask_match(last_component, namelist->name, case_sensitive)) {
1696                                 DEBUG(8,("is_in_path: mask match succeeded\n"));
1697                                 return True;
1698                         }
1699                 } else {
1700                         if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
1701                                                 (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0))) {
1702                                 DEBUG(8,("is_in_path: match succeeded\n"));
1703                                 return True;
1704                         }
1705                 }
1706         }
1707         DEBUG(8,("is_in_path: match not found\n"));
1708         return False;
1709 }
1710 
1711 /*******************************************************************
1712  Strip a '/' separated list into an array of 
1713  name_compare_enties structures suitable for 
1714  passing to is_in_path(). We do this for
1715  speed so we can pre-parse all the names in the list 
1716  and don't do it for each call to is_in_path().
1717  namelist is modified here and is assumed to be 
1718  a copy owned by the caller.
1719  We also check if the entry contains a wildcard to
1720  remove a potentially expensive call to mask_match
1721  if possible.
1722 ********************************************************************/
1723  
1724 void set_namearray(name_compare_entry **ppname_array, const char *namelist)
     /* [<][>][^][v][top][bottom][index][help] */
1725 {
1726         char *name_end;
1727         const char *nameptr = namelist;
1728         int num_entries = 0;
1729         int i;
1730 
1731         (*ppname_array) = NULL;
1732 
1733         if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) 
1734                 return;
1735 
1736         /* We need to make two passes over the string. The
1737                 first to count the number of elements, the second
1738                 to split it.
1739         */
1740 
1741         while(*nameptr) {
1742                 if ( *nameptr == '/' ) {
1743                         /* cope with multiple (useless) /s) */
1744                         nameptr++;
1745                         continue;
1746                 }
1747                 /* find the next / */
1748                 name_end = strchr_m(nameptr, '/');
1749 
1750                 /* oops - the last check for a / didn't find one. */
1751                 if (name_end == NULL)
1752                         break;
1753 
1754                 /* next segment please */
1755                 nameptr = name_end + 1;
1756                 num_entries++;
1757         }
1758 
1759         if(num_entries == 0)
1760                 return;
1761 
1762         if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
1763                 DEBUG(0,("set_namearray: malloc fail\n"));
1764                 return;
1765         }
1766 
1767         /* Now copy out the names */
1768         nameptr = namelist;
1769         i = 0;
1770         while(*nameptr) {
1771                 if ( *nameptr == '/' ) {
1772                         /* cope with multiple (useless) /s) */
1773                         nameptr++;
1774                         continue;
1775                 }
1776                 /* find the next / */
1777                 if ((name_end = strchr_m(nameptr, '/')) != NULL)
1778                         *name_end = 0;
1779 
1780                 /* oops - the last check for a / didn't find one. */
1781                 if(name_end == NULL) 
1782                         break;
1783 
1784                 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1785                 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1786                         DEBUG(0,("set_namearray: malloc fail (1)\n"));
1787                         return;
1788                 }
1789 
1790                 /* next segment please */
1791                 nameptr = name_end + 1;
1792                 i++;
1793         }
1794   
1795         (*ppname_array)[i].name = NULL;
1796 
1797         return;
1798 }
1799 
1800 /****************************************************************************
1801  Routine to free a namearray.
1802 ****************************************************************************/
1803 
1804 void free_namearray(name_compare_entry *name_array)
     /* [<][>][^][v][top][bottom][index][help] */
1805 {
1806         int i;
1807 
1808         if(name_array == NULL)
1809                 return;
1810 
1811         for(i=0; name_array[i].name!=NULL; i++)
1812                 SAFE_FREE(name_array[i].name);
1813         SAFE_FREE(name_array);
1814 }
1815 
1816 #undef DBGC_CLASS
1817 #define DBGC_CLASS DBGC_LOCKING
1818 
1819 /****************************************************************************
1820  Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
1821  is dealt with in posix.c
1822  Returns True if we have information regarding this lock region (and returns
1823  F_UNLCK in *ptype if the region is unlocked). False if the call failed.
1824 ****************************************************************************/
1825 
1826 bool fcntl_getlock(int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
     /* [<][>][^][v][top][bottom][index][help] */
1827 {
1828         SMB_STRUCT_FLOCK lock;
1829         int ret;
1830 
1831         DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
1832                     fd,(double)*poffset,(double)*pcount,*ptype));
1833 
1834         lock.l_type = *ptype;
1835         lock.l_whence = SEEK_SET;
1836         lock.l_start = *poffset;
1837         lock.l_len = *pcount;
1838         lock.l_pid = 0;
1839 
1840         ret = sys_fcntl_ptr(fd,SMB_F_GETLK,&lock);
1841 
1842         if (ret == -1) {
1843                 int sav = errno;
1844                 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
1845                         (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
1846                 errno = sav;
1847                 return False;
1848         }
1849 
1850         *ptype = lock.l_type;
1851         *poffset = lock.l_start;
1852         *pcount = lock.l_len;
1853         *ppid = lock.l_pid;
1854         
1855         DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
1856                         fd, (int)lock.l_type, (unsigned int)lock.l_pid));
1857         return True;
1858 }
1859 
1860 #undef DBGC_CLASS
1861 #define DBGC_CLASS DBGC_ALL
1862 
1863 /*******************************************************************
1864  Is the name specified one of my netbios names.
1865  Returns true if it is equal, false otherwise.
1866 ********************************************************************/
1867 
1868 bool is_myname(const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
1869 {
1870         int n;
1871         bool ret = False;
1872 
1873         for (n=0; my_netbios_names(n); n++) {
1874                 if (strequal(my_netbios_names(n), s)) {
1875                         ret=True;
1876                         break;
1877                 }
1878         }
1879         DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
1880         return(ret);
1881 }
1882 
1883 /*******************************************************************
1884  Is the name specified our workgroup/domain.
1885  Returns true if it is equal, false otherwise.
1886 ********************************************************************/
1887 
1888 bool is_myworkgroup(const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
1889 {
1890         bool ret = False;
1891 
1892         if (strequal(s, lp_workgroup())) {
1893                 ret=True;
1894         }
1895 
1896         DEBUG(8, ("is_myworkgroup(\"%s\") returns %d\n", s, ret));
1897         return(ret);
1898 }
1899 
1900 /*******************************************************************
1901  we distinguish between 2K and XP by the "Native Lan Manager" string
1902    WinXP => "Windows 2002 5.1"
1903    WinXP 64bit => "Windows XP 5.2"
1904    Win2k => "Windows 2000 5.0"
1905    NT4   => "Windows NT 4.0"
1906    Win9x => "Windows 4.0"
1907  Windows 2003 doesn't set the native lan manager string but
1908  they do set the domain to "Windows 2003 5.2" (probably a bug).
1909 ********************************************************************/
1910 
1911 void ra_lanman_string( const char *native_lanman )
     /* [<][>][^][v][top][bottom][index][help] */
1912 {
1913         if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
1914                 set_remote_arch( RA_WINXP );
1915         else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
1916                 set_remote_arch( RA_WINXP64 );
1917         else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
1918                 set_remote_arch( RA_WIN2K3 );
1919 }
1920 
1921 static const char *remote_arch_str;
1922 
1923 const char *get_remote_arch_str(void)
     /* [<][>][^][v][top][bottom][index][help] */
1924 {
1925         if (!remote_arch_str) {
1926                 return "UNKNOWN";
1927         }
1928         return remote_arch_str;
1929 }
1930 
1931 /*******************************************************************
1932  Set the horrid remote_arch string based on an enum.
1933 ********************************************************************/
1934 
1935 void set_remote_arch(enum remote_arch_types type)
     /* [<][>][^][v][top][bottom][index][help] */
1936 {
1937         ra_type = type;
1938         switch( type ) {
1939         case RA_WFWG:
1940                 remote_arch_str = "WfWg";
1941                 break;
1942         case RA_OS2:
1943                 remote_arch_str = "OS2";
1944                 break;
1945         case RA_WIN95:
1946                 remote_arch_str = "Win95";
1947                 break;
1948         case RA_WINNT:
1949                 remote_arch_str = "WinNT";
1950                 break;
1951         case RA_WIN2K:
1952                 remote_arch_str = "Win2K";
1953                 break;
1954         case RA_WINXP:
1955                 remote_arch_str = "WinXP";
1956                 break;
1957         case RA_WINXP64:
1958                 remote_arch_str = "WinXP64";
1959                 break;
1960         case RA_WIN2K3:
1961                 remote_arch_str = "Win2K3";
1962                 break;
1963         case RA_VISTA:
1964                 remote_arch_str = "Vista";
1965                 break;
1966         case RA_SAMBA:
1967                 remote_arch_str = "Samba";
1968                 break;
1969         case RA_CIFSFS:
1970                 remote_arch_str = "CIFSFS";
1971                 break;
1972         default:
1973                 ra_type = RA_UNKNOWN;
1974                 remote_arch_str = "UNKNOWN";
1975                 break;
1976         }
1977 
1978         DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1979                                 remote_arch_str));
1980 }
1981 
1982 /*******************************************************************
1983  Get the remote_arch type.
1984 ********************************************************************/
1985 
1986 enum remote_arch_types get_remote_arch(void)
     /* [<][>][^][v][top][bottom][index][help] */
1987 {
1988         return ra_type;
1989 }
1990 
1991 const char *tab_depth(int level, int depth)
     /* [<][>][^][v][top][bottom][index][help] */
1992 {
1993         if( CHECK_DEBUGLVL(level) ) {
1994                 dbgtext("%*s", depth*4, "");
1995         }
1996         return "";
1997 }
1998 
1999 /*****************************************************************************
2000  Provide a checksum on a string
2001 
2002  Input:  s - the null-terminated character string for which the checksum
2003              will be calculated.
2004 
2005   Output: The checksum value calculated for s.
2006 *****************************************************************************/
2007 
2008 int str_checksum(const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
2009 {
2010         int res = 0;
2011         int c;
2012         int i=0;
2013 
2014         while(*s) {
2015                 c = *s;
2016                 res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
2017                 s++;
2018                 i++;
2019         }
2020         return(res);
2021 }
2022 
2023 /*****************************************************************
2024  Zero a memory area then free it. Used to catch bugs faster.
2025 *****************************************************************/  
2026 
2027 void zero_free(void *p, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
2028 {
2029         memset(p, 0, size);
2030         SAFE_FREE(p);
2031 }
2032 
2033 /*****************************************************************
2034  Set our open file limit to a requested max and return the limit.
2035 *****************************************************************/  
2036 
2037 int set_maxfiles(int requested_max)
     /* [<][>][^][v][top][bottom][index][help] */
2038 {
2039 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
2040         struct rlimit rlp;
2041         int saved_current_limit;
2042 
2043         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2044                 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
2045                         strerror(errno) ));
2046                 /* just guess... */
2047                 return requested_max;
2048         }
2049 
2050         /* 
2051          * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
2052          * account for the extra fd we need 
2053          * as well as the log files and standard
2054          * handles etc. Save the limit we want to set in case
2055          * we are running on an OS that doesn't support this limit (AIX)
2056          * which always returns RLIM_INFINITY for rlp.rlim_max.
2057          */
2058 
2059         /* Try raising the hard (max) limit to the requested amount. */
2060 
2061 #if defined(RLIM_INFINITY)
2062         if (rlp.rlim_max != RLIM_INFINITY) {
2063                 int orig_max = rlp.rlim_max;
2064 
2065                 if ( rlp.rlim_max < requested_max )
2066                         rlp.rlim_max = requested_max;
2067 
2068                 /* This failing is not an error - many systems (Linux) don't
2069                         support our default request of 10,000 open files. JRA. */
2070 
2071                 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
2072                         DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n", 
2073                                 (int)rlp.rlim_max, strerror(errno) ));
2074 
2075                         /* Set failed - restore original value from get. */
2076                         rlp.rlim_max = orig_max;
2077                 }
2078         }
2079 #endif
2080 
2081         /* Now try setting the soft (current) limit. */
2082 
2083         saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
2084 
2085         if(setrlimit(RLIMIT_NOFILE, &rlp)) {
2086                 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n", 
2087                         (int)rlp.rlim_cur, strerror(errno) ));
2088                 /* just guess... */
2089                 return saved_current_limit;
2090         }
2091 
2092         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2093                 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
2094                         strerror(errno) ));
2095                 /* just guess... */
2096                 return saved_current_limit;
2097     }
2098 
2099 #if defined(RLIM_INFINITY)
2100         if(rlp.rlim_cur == RLIM_INFINITY)
2101                 return saved_current_limit;
2102 #endif
2103 
2104         if((int)rlp.rlim_cur > saved_current_limit)
2105                 return saved_current_limit;
2106 
2107         return rlp.rlim_cur;
2108 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
2109         /*
2110          * No way to know - just guess...
2111          */
2112         return requested_max;
2113 #endif
2114 }
2115 
2116 /*****************************************************************
2117  Possibly replace mkstemp if it is broken.
2118 *****************************************************************/  
2119 
2120 int smb_mkstemp(char *name_template)
     /* [<][>][^][v][top][bottom][index][help] */
2121 {
2122 #if HAVE_SECURE_MKSTEMP
2123         return mkstemp(name_template);
2124 #else
2125         /* have a reasonable go at emulating it. Hope that
2126            the system mktemp() isn't completly hopeless */
2127         char *p = mktemp(name_template);
2128         if (!p)
2129                 return -1;
2130         return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
2131 #endif
2132 }
2133 
2134 /*****************************************************************
2135  malloc that aborts with smb_panic on fail or zero size.
2136  *****************************************************************/  
2137 
2138 void *smb_xmalloc_array(size_t size, unsigned int count)
     /* [<][>][^][v][top][bottom][index][help] */
2139 {
2140         void *p;
2141         if (size == 0) {
2142                 smb_panic("smb_xmalloc_array: called with zero size");
2143         }
2144         if (count >= MAX_ALLOC_SIZE/size) {
2145                 smb_panic("smb_xmalloc_array: alloc size too large");
2146         }
2147         if ((p = SMB_MALLOC(size*count)) == NULL) {
2148                 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
2149                         (unsigned long)size, (unsigned long)count));
2150                 smb_panic("smb_xmalloc_array: malloc failed");
2151         }
2152         return p;
2153 }
2154 
2155 /*
2156   vasprintf that aborts on malloc fail
2157 */
2158 
2159  int smb_xvasprintf(char **ptr, const char *format, va_list ap)
     /* [<][>][^][v][top][bottom][index][help] */
2160 {
2161         int n;
2162         va_list ap2;
2163 
2164         va_copy(ap2, ap);
2165 
2166         n = vasprintf(ptr, format, ap2);
2167         if (n == -1 || ! *ptr) {
2168                 smb_panic("smb_xvasprintf: out of memory");
2169         }
2170         va_end(ap2);
2171         return n;
2172 }
2173 
2174 /*****************************************************************
2175  Get local hostname and cache result.
2176 *****************************************************************/
2177 
2178 char *myhostname(void)
     /* [<][>][^][v][top][bottom][index][help] */
2179 {
2180         static char *ret;
2181         if (ret == NULL) {
2182                 /* This is cached forever so
2183                  * use talloc_autofree_context() ctx. */
2184                 ret = get_myname(talloc_autofree_context());
2185         }
2186         return ret;
2187 }
2188 
2189 /**
2190  * @brief Returns an absolute path to a file concatenating the provided
2191  * @a rootpath and @a basename
2192  *
2193  * @param name Filename, relative to @a rootpath
2194  *
2195  * @retval Pointer to a string containing the full path.
2196  **/
2197 
2198 static char *xx_path(const char *name, const char *rootpath)
     /* [<][>][^][v][top][bottom][index][help] */
2199 {
2200         char *fname = NULL;
2201 
2202         fname = talloc_strdup(talloc_tos(), rootpath);
2203         if (!fname) {
2204                 return NULL;
2205         }
2206         trim_string(fname,"","/");
2207 
2208         if (!directory_exist(fname)) {
2209                 if (!mkdir(fname,0755))
2210                         DEBUG(1, ("Unable to create directory %s for file %s. "
2211                               "Error was %s\n", fname, name, strerror(errno)));
2212         }
2213 
2214         return talloc_asprintf(talloc_tos(),
2215                                 "%s/%s",
2216                                 fname,
2217                                 name);
2218 }
2219 
2220 /**
2221  * @brief Returns an absolute path to a file in the Samba lock directory.
2222  *
2223  * @param name File to find, relative to LOCKDIR.
2224  *
2225  * @retval Pointer to a talloc'ed string containing the full path.
2226  **/
2227 
2228 char *lock_path(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
2229 {
2230         return xx_path(name, lp_lockdir());
2231 }
2232 
2233 /**
2234  * @brief Returns an absolute path to a file in the Samba pid directory.
2235  *
2236  * @param name File to find, relative to PIDDIR.
2237  *
2238  * @retval Pointer to a talloc'ed string containing the full path.
2239  **/
2240 
2241 char *pid_path(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
2242 {
2243         return xx_path(name, lp_piddir());
2244 }
2245 
2246 /**
2247  * @brief Returns an absolute path to a file in the Samba lib directory.
2248  *
2249  * @param name File to find, relative to LIBDIR.
2250  *
2251  * @retval Pointer to a string containing the full path.
2252  **/
2253 
2254 char *lib_path(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
2255 {
2256         return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_LIBDIR(), name);
2257 }
2258 
2259 /**
2260  * @brief Returns an absolute path to a file in the Samba modules directory.
2261  *
2262  * @param name File to find, relative to MODULESDIR.
2263  *
2264  * @retval Pointer to a string containing the full path.
2265  **/
2266 
2267 char *modules_path(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
2268 {
2269         return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_MODULESDIR(), name);
2270 }
2271 
2272 /**
2273  * @brief Returns an absolute path to a file in the Samba data directory.
2274  *
2275  * @param name File to find, relative to CODEPAGEDIR.
2276  *
2277  * @retval Pointer to a talloc'ed string containing the full path.
2278  **/
2279 
2280 char *data_path(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
2281 {
2282         return talloc_asprintf(talloc_tos(), "%s/%s", get_dyn_CODEPAGEDIR(), name);
2283 }
2284 
2285 /**
2286  * @brief Returns an absolute path to a file in the Samba state directory.
2287  *
2288  * @param name File to find, relative to STATEDIR.
2289  *
2290  * @retval Pointer to a talloc'ed string containing the full path.
2291  **/
2292 
2293 char *state_path(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
2294 {
2295         return xx_path(name, lp_statedir());
2296 }
2297 
2298 /**
2299  * @brief Returns an absolute path to a file in the Samba cache directory.
2300  *
2301  * @param name File to find, relative to CACHEDIR.
2302  *
2303  * @retval Pointer to a talloc'ed string containing the full path.
2304  **/
2305 
2306 char *cache_path(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
2307 {
2308         return xx_path(name, lp_cachedir());
2309 }
2310 
2311 /**
2312  * @brief Returns the platform specific shared library extension.
2313  *
2314  * @retval Pointer to a const char * containing the extension.
2315  **/
2316 
2317 const char *shlib_ext(void)
     /* [<][>][^][v][top][bottom][index][help] */
2318 {
2319         return get_dyn_SHLIBEXT();
2320 }
2321 
2322 /*******************************************************************
2323  Given a filename - get its directory name
2324 ********************************************************************/
2325 
2326 bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
     /* [<][>][^][v][top][bottom][index][help] */
2327                     const char **name)
2328 {
2329         char *p;
2330         ptrdiff_t len;
2331  
2332         p = strrchr_m(dir, '/'); /* Find final '/', if any */
2333 
2334         if (p == NULL) {
2335                 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
2336                         return False;
2337                 }
2338                 if (name) {
2339                         *name = dir;
2340                 }
2341                 return True;
2342         }
2343 
2344         len = p-dir;
2345 
2346         if (!(*parent = (char *)TALLOC_MEMDUP(mem_ctx, dir, len+1))) {
2347                 return False;
2348         }
2349         (*parent)[len] = '\0';
2350 
2351         if (name) {
2352                 *name = p+1;
2353         }
2354         return True;
2355 }
2356 
2357 /*******************************************************************
2358  Determine if a pattern contains any Microsoft wildcard characters.
2359 *******************************************************************/
2360 
2361 bool ms_has_wild(const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
2362 {
2363         char c;
2364 
2365         if (lp_posix_pathnames()) {
2366                 /* With posix pathnames no characters are wild. */
2367                 return False;
2368         }
2369 
2370         while ((c = *s++)) {
2371                 switch (c) {
2372                 case '*':
2373                 case '?':
2374                 case '<':
2375                 case '>':
2376                 case '"':
2377                         return True;
2378                 }
2379         }
2380         return False;
2381 }
2382 
2383 bool ms_has_wild_w(const smb_ucs2_t *s)
     /* [<][>][^][v][top][bottom][index][help] */
2384 {
2385         smb_ucs2_t c;
2386         if (!s) return False;
2387         while ((c = *s++)) {
2388                 switch (c) {
2389                 case UCS2_CHAR('*'):
2390                 case UCS2_CHAR('?'):
2391                 case UCS2_CHAR('<'):
2392                 case UCS2_CHAR('>'):
2393                 case UCS2_CHAR('"'):
2394                         return True;
2395                 }
2396         }
2397         return False;
2398 }
2399 
2400 /*******************************************************************
2401  A wrapper that handles case sensitivity and the special handling
2402  of the ".." name.
2403 *******************************************************************/
2404 
2405 bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
     /* [<][>][^][v][top][bottom][index][help] */
2406 {
2407         if (strcmp(string,"..") == 0)
2408                 string = ".";
2409         if (strcmp(pattern,".") == 0)
2410                 return False;
2411         
2412         return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
2413 }
2414 
2415 /*******************************************************************
2416  A wrapper that handles case sensitivity and the special handling
2417  of the ".." name. Varient that is only called by old search code which requires
2418  pattern translation.
2419 *******************************************************************/
2420 
2421 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
     /* [<][>][^][v][top][bottom][index][help] */
2422 {
2423         if (strcmp(string,"..") == 0)
2424                 string = ".";
2425         if (strcmp(pattern,".") == 0)
2426                 return False;
2427         
2428         return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
2429 }
2430 
2431 /*******************************************************************
2432  A wrapper that handles a list of patters and calls mask_match()
2433  on each.  Returns True if any of the patterns match.
2434 *******************************************************************/
2435 
2436 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
     /* [<][>][^][v][top][bottom][index][help] */
2437 {
2438        while (listLen-- > 0) {
2439                if (mask_match(string, *list++, is_case_sensitive))
2440                        return True;
2441        }
2442        return False;
2443 }
2444 
2445 /*********************************************************
2446  Recursive routine that is called by unix_wild_match.
2447 *********************************************************/
2448 
2449 static bool unix_do_match(const char *regexp, const char *str)
     /* [<][>][^][v][top][bottom][index][help] */
2450 {
2451         const char *p;
2452 
2453         for( p = regexp; *p && *str; ) {
2454 
2455                 switch(*p) {
2456                         case '?':
2457                                 str++;
2458                                 p++;
2459                                 break;
2460 
2461                         case '*':
2462 
2463                                 /*
2464                                  * Look for a character matching 
2465                                  * the one after the '*'.
2466                                  */
2467                                 p++;
2468                                 if(!*p)
2469                                         return true; /* Automatic match */
2470                                 while(*str) {
2471 
2472                                         while(*str && (*p != *str))
2473                                                 str++;
2474 
2475                                         /*
2476                                          * Patch from weidel@multichart.de. In the case of the regexp
2477                                          * '*XX*' we want to ensure there are at least 2 'X' characters
2478                                          * in the string after the '*' for a match to be made.
2479                                          */
2480 
2481                                         {
2482                                                 int matchcount=0;
2483 
2484                                                 /*
2485                                                  * Eat all the characters that match, but count how many there were.
2486                                                  */
2487 
2488                                                 while(*str && (*p == *str)) {
2489                                                         str++;
2490                                                         matchcount++;
2491                                                 }
2492 
2493                                                 /*
2494                                                  * Now check that if the regexp had n identical characters that
2495                                                  * matchcount had at least that many matches.
2496                                                  */
2497 
2498                                                 while ( *(p+1) && (*(p+1) == *p)) {
2499                                                         p++;
2500                                                         matchcount--;
2501                                                 }
2502 
2503                                                 if ( matchcount <= 0 )
2504                                                         return false;
2505                                         }
2506 
2507                                         str--; /* We've eaten the match char after the '*' */
2508 
2509                                         if(unix_do_match(p, str))
2510                                                 return true;
2511 
2512                                         if(!*str)
2513                                                 return false;
2514                                         else
2515                                                 str++;
2516                                 }
2517                                 return false;
2518 
2519                         default:
2520                                 if(*str != *p)
2521                                         return false;
2522                                 str++;
2523                                 p++;
2524                                 break;
2525                 }
2526         }
2527 
2528         if(!*p && !*str)
2529                 return true;
2530 
2531         if (!*p && str[0] == '.' && str[1] == 0)
2532                 return true;
2533 
2534         if (!*str && *p == '?') {
2535                 while (*p == '?')
2536                         p++;
2537                 return(!*p);
2538         }
2539 
2540         if(!*str && (*p == '*' && p[1] == '\0'))
2541                 return true;
2542 
2543         return false;
2544 }
2545 
2546 /*******************************************************************
2547  Simple case insensitive interface to a UNIX wildcard matcher.
2548  Returns True if match, False if not.
2549 *******************************************************************/
2550 
2551 bool unix_wild_match(const char *pattern, const char *string)
     /* [<][>][^][v][top][bottom][index][help] */
2552 {
2553         TALLOC_CTX *ctx = talloc_stackframe();
2554         char *p2;
2555         char *s2;
2556         char *p;
2557         bool ret = false;
2558 
2559         p2 = talloc_strdup(ctx,pattern);
2560         s2 = talloc_strdup(ctx,string);
2561         if (!p2 || !s2) {
2562                 TALLOC_FREE(ctx);
2563                 return false;
2564         }
2565         strlower_m(p2);
2566         strlower_m(s2);
2567 
2568         /* Remove any *? and ** from the pattern as they are meaningless */
2569         for(p = p2; *p; p++) {
2570                 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
2571                         memmove(&p[1], &p[2], strlen(&p[2])+1);
2572                 }
2573         }
2574 
2575         if (strequal(p2,"*")) {
2576                 TALLOC_FREE(ctx);
2577                 return true;
2578         }
2579 
2580         ret = unix_do_match(p2, s2);
2581         TALLOC_FREE(ctx);
2582         return ret;
2583 }
2584 
2585 /**********************************************************************
2586  Converts a name to a fully qualified domain name.
2587  Returns true if lookup succeeded, false if not (then fqdn is set to name)
2588  Note we deliberately use gethostbyname here, not getaddrinfo as we want
2589  to examine the h_aliases and I don't know how to do that with getaddrinfo.
2590 ***********************************************************************/
2591 
2592 bool name_to_fqdn(fstring fqdn, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
2593 {
2594         char *full = NULL;
2595         struct hostent *hp = gethostbyname(name);
2596 
2597         if (!hp || !hp->h_name || !*hp->h_name) {
2598                 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
2599                 fstrcpy(fqdn, name);
2600                 return false;
2601         }
2602 
2603         /* Find out if the fqdn is returned as an alias
2604          * to cope with /etc/hosts files where the first
2605          * name is not the fqdn but the short name */
2606         if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
2607                 int i;
2608                 for (i = 0; hp->h_aliases[i]; i++) {
2609                         if (strchr_m(hp->h_aliases[i], '.')) {
2610                                 full = hp->h_aliases[i];
2611                                 break;
2612                         }
2613                 }
2614         }
2615         if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) {
2616                 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
2617                 DEBUGADD(1, ("    Specifing the machine hostname for address 127.0.0.1 may lead\n"));
2618                 DEBUGADD(1, ("    to Kerberos authentication problems as localhost.localdomain\n"));
2619                 DEBUGADD(1, ("    may end up being used instead of the real machine FQDN.\n"));
2620                 full = hp->h_name;
2621         }
2622         if (!full) {
2623                 full = hp->h_name;
2624         }
2625 
2626         DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
2627         fstrcpy(fqdn, full);
2628         return true;
2629 }
2630 
2631 /**********************************************************************
2632  Append a DATA_BLOB to a talloc'ed object
2633 ***********************************************************************/
2634 
2635 void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob)
     /* [<][>][^][v][top][bottom][index][help] */
2636 {
2637         size_t old_size = 0;
2638         char *result;
2639 
2640         if (blob.length == 0) {
2641                 return buf;
2642         }
2643 
2644         if (buf != NULL) {
2645                 old_size = talloc_get_size(buf);
2646         }
2647 
2648         result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length);
2649         if (result == NULL) {
2650                 return NULL;
2651         }
2652 
2653         memcpy(result + old_size, blob.data, blob.length);
2654         return result;
2655 }
2656 
2657 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
     /* [<][>][^][v][top][bottom][index][help] */
2658 {
2659         switch (share_access & ~FILE_SHARE_DELETE) {
2660                 case FILE_SHARE_NONE:
2661                         return DENY_ALL;
2662                 case FILE_SHARE_READ:
2663                         return DENY_WRITE;
2664                 case FILE_SHARE_WRITE:
2665                         return DENY_READ;
2666                 case FILE_SHARE_READ|FILE_SHARE_WRITE:
2667                         return DENY_NONE;
2668         }
2669         if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
2670                 return DENY_DOS;
2671         } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
2672                 return DENY_FCB;
2673         }
2674 
2675         return (uint32)-1;
2676 }
2677 
2678 pid_t procid_to_pid(const struct server_id *proc)
     /* [<][>][^][v][top][bottom][index][help] */
2679 {
2680         return proc->pid;
2681 }
2682 
2683 static uint32 my_vnn = NONCLUSTER_VNN;
2684 
2685 void set_my_vnn(uint32 vnn)
     /* [<][>][^][v][top][bottom][index][help] */
2686 {
2687         DEBUG(10, ("vnn pid %d = %u\n", (int)sys_getpid(), (unsigned int)vnn));
2688         my_vnn = vnn;
2689 }
2690 
2691 uint32 get_my_vnn(void)
     /* [<][>][^][v][top][bottom][index][help] */
2692 {
2693         return my_vnn;
2694 }
2695 
2696 struct server_id pid_to_procid(pid_t pid)
     /* [<][>][^][v][top][bottom][index][help] */
2697 {
2698         struct server_id result;
2699         result.pid = pid;
2700 #ifdef CLUSTER_SUPPORT
2701         result.vnn = my_vnn;
2702 #endif
2703         return result;
2704 }
2705 
2706 struct server_id procid_self(void)
     /* [<][>][^][v][top][bottom][index][help] */
2707 {
2708         return pid_to_procid(sys_getpid());
2709 }
2710 
2711 struct server_id server_id_self(void)
     /* [<][>][^][v][top][bottom][index][help] */
2712 {
2713         return procid_self();
2714 }
2715 
2716 bool procid_equal(const struct server_id *p1, const struct server_id *p2)
     /* [<][>][^][v][top][bottom][index][help] */
2717 {
2718         if (p1->pid != p2->pid)
2719                 return False;
2720 #ifdef CLUSTER_SUPPORT
2721         if (p1->vnn != p2->vnn)
2722                 return False;
2723 #endif
2724         return True;
2725 }
2726 
2727 bool cluster_id_equal(const struct server_id *id1,
     /* [<][>][^][v][top][bottom][index][help] */
2728                       const struct server_id *id2)
2729 {
2730         return procid_equal(id1, id2);
2731 }
2732 
2733 bool procid_is_me(const struct server_id *pid)
     /* [<][>][^][v][top][bottom][index][help] */
2734 {
2735         if (pid->pid != sys_getpid())
2736                 return False;
2737 #ifdef CLUSTER_SUPPORT
2738         if (pid->vnn != my_vnn)
2739                 return False;
2740 #endif
2741         return True;
2742 }
2743 
2744 struct server_id interpret_pid(const char *pid_string)
     /* [<][>][^][v][top][bottom][index][help] */
2745 {
2746         struct server_id result;
2747         int pid;
2748 #ifdef CLUSTER_SUPPORT
2749         unsigned int vnn;
2750         if (sscanf(pid_string, "%u:%d", &vnn, &pid) == 2) {
2751                 result.vnn = vnn;
2752                 result.pid = pid;
2753         }
2754         else if (sscanf(pid_string, "%d", &pid) == 1) {
2755                 result.vnn = get_my_vnn();
2756                 result.pid = pid;
2757         }
2758         else {
2759                 result.vnn = NONCLUSTER_VNN;
2760                 result.pid = -1;
2761         }
2762 #else
2763         if (sscanf(pid_string, "%d", &pid) != 1) {
2764                 result.pid = -1;
2765         } else {
2766                 result.pid = pid;
2767         }
2768 #endif
2769         /* Assigning to result.pid may have overflowed
2770            Map negative pid to -1: i.e. error */
2771         if (result.pid < 0) {
2772                 result.pid = -1;
2773         }
2774         return result;
2775 }
2776 
2777 char *procid_str(TALLOC_CTX *mem_ctx, const struct server_id *pid)
     /* [<][>][^][v][top][bottom][index][help] */
2778 {
2779 #ifdef CLUSTER_SUPPORT
2780         if (pid->vnn == NONCLUSTER_VNN) {
2781                 return talloc_asprintf(mem_ctx,
2782                                 "%d",
2783                                 (int)pid->pid);
2784         }
2785         else {
2786                 return talloc_asprintf(mem_ctx,
2787                                         "%u:%d",
2788                                         (unsigned)pid->vnn,
2789                                         (int)pid->pid);
2790         }
2791 #else
2792         return talloc_asprintf(mem_ctx,
2793                         "%d",
2794                         (int)pid->pid);
2795 #endif
2796 }
2797 
2798 char *procid_str_static(const struct server_id *pid)
     /* [<][>][^][v][top][bottom][index][help] */
2799 {
2800         return procid_str(talloc_tos(), pid);
2801 }
2802 
2803 bool procid_valid(const struct server_id *pid)
     /* [<][>][^][v][top][bottom][index][help] */
2804 {
2805         return (pid->pid != -1);
2806 }
2807 
2808 bool procid_is_local(const struct server_id *pid)
     /* [<][>][^][v][top][bottom][index][help] */
2809 {
2810 #ifdef CLUSTER_SUPPORT
2811         return pid->vnn == my_vnn;
2812 #else
2813         return True;
2814 #endif
2815 }
2816 
2817 int this_is_smp(void)
     /* [<][>][^][v][top][bottom][index][help] */
2818 {
2819 #if defined(HAVE_SYSCONF)
2820 
2821 #if defined(SYSCONF_SC_NPROC_ONLN)
2822         return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0;
2823 #elif defined(SYSCONF_SC_NPROCESSORS_ONLN)
2824         return (sysconf(_SC_NPROCESSORS_ONLN) > 1) ? 1 : 0;
2825 #else
2826         return 0;
2827 #endif
2828 
2829 #else
2830         return 0;
2831 #endif
2832 }
2833 
2834 /****************************************************************
2835  Check if offset/length fit into bufsize. Should probably be
2836  merged with is_offset_safe, but this would require a rewrite
2837  of lanman.c. Later :-)
2838 ****************************************************************/
2839 
2840 bool trans_oob(uint32_t bufsize, uint32_t offset, uint32_t length)
     /* [<][>][^][v][top][bottom][index][help] */
2841 {
2842         if ((offset + length < offset) || (offset + length < length)) {
2843                 /* wrap */
2844                 return true;
2845         }
2846         if ((offset > bufsize) || (offset + length > bufsize)) {
2847                 /* overflow */
2848                 return true;
2849         }
2850         return false;
2851 }
2852 
2853 /****************************************************************
2854  Check if an offset into a buffer is safe.
2855  If this returns True it's safe to indirect into the byte at
2856  pointer ptr+off.
2857 ****************************************************************/
2858 
2859 bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
     /* [<][>][^][v][top][bottom][index][help] */
2860 {
2861         const char *end_base = buf_base + buf_len;
2862         char *end_ptr = ptr + off;
2863 
2864         if (!buf_base || !ptr) {
2865                 return False;
2866         }
2867 
2868         if (end_base < buf_base || end_ptr < ptr) {
2869                 return False; /* wrap. */
2870         }
2871 
2872         if (end_ptr < end_base) {
2873                 return True;
2874         }
2875         return False;
2876 }
2877 
2878 /****************************************************************
2879  Return a safe pointer into a buffer, or NULL.
2880 ****************************************************************/
2881 
2882 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
     /* [<][>][^][v][top][bottom][index][help] */
2883 {
2884         return is_offset_safe(buf_base, buf_len, ptr, off) ?
2885                         ptr + off : NULL;
2886 }
2887 
2888 /****************************************************************
2889  Return a safe pointer into a string within a buffer, or NULL.
2890 ****************************************************************/
2891 
2892 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
     /* [<][>][^][v][top][bottom][index][help] */
2893 {
2894         if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
2895                 return NULL;
2896         }
2897         /* Check if a valid string exists at this offset. */
2898         if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
2899                 return NULL;
2900         }
2901         return ptr + off;
2902 }
2903 
2904 /****************************************************************
2905  Return an SVAL at a pointer, or failval if beyond the end.
2906 ****************************************************************/
2907 
2908 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
     /* [<][>][^][v][top][bottom][index][help] */
2909 {
2910         /*
2911          * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2912          * NOT ptr[2].
2913          */
2914         if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
2915                 return failval;
2916         }
2917         return SVAL(ptr,off);
2918 }
2919 
2920 /****************************************************************
2921  Return an IVAL at a pointer, or failval if beyond the end.
2922 ****************************************************************/
2923 
2924 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
     /* [<][>][^][v][top][bottom][index][help] */
2925 {
2926         /*
2927          * Note we use off+3 here, not off+4 as IVAL accesses 
2928          * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2929          */
2930         if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
2931                 return failval;
2932         }
2933         return IVAL(ptr,off);
2934 }
2935 
2936 /****************************************************************
2937  Split DOM\user into DOM and user. Do not mix with winbind variants of that
2938  call (they take care of winbind separator and other winbind specific settings).
2939 ****************************************************************/
2940 
2941 void split_domain_user(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
2942                        const char *full_name,
2943                        char **domain,
2944                        char **user)
2945 {
2946         const char *p = NULL;
2947 
2948         p = strchr_m(full_name, '\\');
2949 
2950         if (p != NULL) {
2951                 *domain = talloc_strndup(mem_ctx, full_name,
2952                                          PTR_DIFF(p, full_name));
2953                 *user = talloc_strdup(mem_ctx, p+1);
2954         } else {
2955                 *domain = talloc_strdup(mem_ctx, "");
2956                 *user = talloc_strdup(mem_ctx, full_name);
2957         }
2958 }
2959 
2960 #if 0
2961 
2962 Disable these now we have checked all code paths and ensured
2963 NULL returns on zero request. JRA.
2964 
2965 /****************************************************************
2966  talloc wrapper functions that guarentee a null pointer return
2967  if size == 0.
2968 ****************************************************************/
2969 
2970 #ifndef MAX_TALLOC_SIZE
2971 #define MAX_TALLOC_SIZE 0x10000000
2972 #endif
2973 
2974 /*
2975  *    talloc and zero memory.
2976  *    - returns NULL if size is zero.
2977  */
2978 
2979 void *_talloc_zero_zeronull(const void *ctx, size_t size, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
2980 {
2981         void *p;
2982 
2983         if (size == 0) {
2984                 return NULL;
2985         }
2986 
2987         p = talloc_named_const(ctx, size, name);
2988 
2989         if (p) {
2990                 memset(p, '\0', size);
2991         }
2992 
2993         return p;
2994 }
2995 
2996 /*
2997  *   memdup with a talloc.
2998  *   - returns NULL if size is zero.
2999  */
3000 
3001 void *_talloc_memdup_zeronull(const void *t, const void *p, size_t size, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
3002 {
3003         void *newp;
3004 
3005         if (size == 0) {
3006                 return NULL;
3007         }
3008 
3009         newp = talloc_named_const(t, size, name);
3010         if (newp) {
3011                 memcpy(newp, p, size);
3012         }
3013 
3014         return newp;
3015 }
3016 
3017 /*
3018  *   alloc an array, checking for integer overflow in the array size.
3019  *   - returns NULL if count or el_size are zero.
3020  */
3021 
3022 void *_talloc_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
3023 {
3024         if (count >= MAX_TALLOC_SIZE/el_size) {
3025                 return NULL;
3026         }
3027 
3028         if (el_size == 0 || count == 0) {
3029                 return NULL;
3030         }
3031 
3032         return talloc_named_const(ctx, el_size * count, name);
3033 }
3034 
3035 /*
3036  *   alloc an zero array, checking for integer overflow in the array size
3037  *   - returns NULL if count or el_size are zero.
3038  */
3039 
3040 void *_talloc_zero_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
3041 {
3042         if (count >= MAX_TALLOC_SIZE/el_size) {
3043                 return NULL;
3044         }
3045 
3046         if (el_size == 0 || count == 0) {
3047                 return NULL;
3048         }
3049 
3050         return _talloc_zero(ctx, el_size * count, name);
3051 }
3052 
3053 /*
3054  *   Talloc wrapper that returns NULL if size == 0.
3055  */
3056 void *talloc_zeronull(const void *context, size_t size, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
3057 {
3058         if (size == 0) {
3059                 return NULL;
3060         }
3061         return talloc_named_const(context, size, name);
3062 }
3063 #endif
3064 
3065 /* Split a path name into filename and stream name components. Canonicalise
3066  * such that an implicit $DATA token is always explicit.
3067  *
3068  * The "specification" of this function can be found in the
3069  * run_local_stream_name() function in torture.c, I've tried those
3070  * combinations against a W2k3 server.
3071  */
3072 
3073 NTSTATUS split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
     /* [<][>][^][v][top][bottom][index][help] */
3074                                 char **pbase, char **pstream)
3075 {
3076         char *base = NULL;
3077         char *stream = NULL;
3078         char *sname; /* stream name */
3079         const char *stype; /* stream type */
3080 
3081         DEBUG(10, ("split_ntfs_stream_name called for [%s]\n", fname));
3082 
3083         sname = strchr_m(fname, ':');
3084 
3085         if (lp_posix_pathnames() || (sname == NULL)) {
3086                 if (pbase != NULL) {
3087                         base = talloc_strdup(mem_ctx, fname);
3088                         NT_STATUS_HAVE_NO_MEMORY(base);
3089                 }
3090                 goto done;
3091         }
3092 
3093         if (pbase != NULL) {
3094                 base = talloc_strndup(mem_ctx, fname, PTR_DIFF(sname, fname));
3095                 NT_STATUS_HAVE_NO_MEMORY(base);
3096         }
3097 
3098         sname += 1;
3099 
3100         stype = strchr_m(sname, ':');
3101 
3102         if (stype == NULL) {
3103                 sname = talloc_strdup(mem_ctx, sname);
3104                 stype = "$DATA";
3105         }
3106         else {
3107                 if (StrCaseCmp(stype, ":$DATA") != 0) {
3108                         /*
3109                          * If there is an explicit stream type, so far we only
3110                          * allow $DATA. Is there anything else allowed? -- vl
3111                          */
3112                         DEBUG(10, ("[%s] is an invalid stream type\n", stype));
3113                         TALLOC_FREE(base);
3114                         return NT_STATUS_OBJECT_NAME_INVALID;
3115                 }
3116                 sname = talloc_strndup(mem_ctx, sname, PTR_DIFF(stype, sname));
3117                 stype += 1;
3118         }
3119 
3120         if (sname == NULL) {
3121                 TALLOC_FREE(base);
3122                 return NT_STATUS_NO_MEMORY;
3123         }
3124 
3125         if (sname[0] == '\0') {
3126                 /*
3127                  * no stream name, so no stream
3128                  */
3129                 goto done;
3130         }
3131 
3132         if (pstream != NULL) {
3133                 stream = talloc_asprintf(mem_ctx, "%s:%s", sname, stype);
3134                 if (stream == NULL) {
3135                         TALLOC_FREE(sname);
3136                         TALLOC_FREE(base);
3137                         return NT_STATUS_NO_MEMORY;
3138                 }
3139                 /*
3140                  * upper-case the type field
3141                  */
3142                 strupper_m(strchr_m(stream, ':')+1);
3143         }
3144 
3145  done:
3146         if (pbase != NULL) {
3147                 *pbase = base;
3148         }
3149         if (pstream != NULL) {
3150                 *pstream = stream;
3151         }
3152         return NT_STATUS_OK;
3153 }
3154 
3155 bool is_valid_policy_hnd(const struct policy_handle *hnd)
     /* [<][>][^][v][top][bottom][index][help] */
3156 {
3157         struct policy_handle tmp;
3158         ZERO_STRUCT(tmp);
3159         return (memcmp(&tmp, hnd, sizeof(tmp)) != 0);
3160 }
3161 
3162 bool policy_hnd_equal(const struct policy_handle *hnd1,
     /* [<][>][^][v][top][bottom][index][help] */
3163                       const struct policy_handle *hnd2)
3164 {
3165         if (!hnd1 || !hnd2) {
3166                 return false;
3167         }
3168 
3169         return (memcmp(hnd1, hnd2, sizeof(*hnd1)) == 0);
3170 }
3171 
3172 /****************************************************************
3173  strip off leading '\\' from a hostname
3174 ****************************************************************/
3175 
3176 const char *strip_hostname(const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
3177 {
3178         if (!s) {
3179                 return NULL;
3180         }
3181 
3182         if (strlen_m(s) < 3) {
3183                 return s;
3184         }
3185 
3186         if (s[0] == '\\') s++;
3187         if (s[0] == '\\') s++;
3188 
3189         return s;
3190 }

/* [<][>][^][v][top][bottom][index][help] */