lib/util.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    Samba utility functions
00004    Copyright (C) Andrew Tridgell 1992-1998
00005    Copyright (C) Jeremy Allison 2001-2002
00006    Copyright (C) Simo Sorce 2001
00007    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
00008    Copyright (C) James Peach 2006
00009 
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 2 of the License, or
00013    (at your option) any later version.
00014    
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019    
00020    You should have received a copy of the GNU General Public License
00021    along with this program; if not, write to the Free Software
00022    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00023 */
00024 
00025 #include "includes.h"
00026 
00027 extern fstring local_machine;
00028 extern char *global_clobber_region_function;
00029 extern unsigned int global_clobber_region_line;
00030 extern fstring remote_arch;
00031 
00032 /* Max allowable allococation - 256mb - 0x10000000 */
00033 #define MAX_ALLOC_SIZE (1024*1024*256)
00034 
00035 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
00036 #ifdef WITH_NISPLUS_HOME
00037 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
00038 /*
00039  * The following lines are needed due to buggy include files
00040  * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
00041  * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
00042  * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
00043  * an enum in /usr/include/rpcsvc/nis.h.
00044  */
00045 
00046 #if defined(GROUP)
00047 #undef GROUP
00048 #endif
00049 
00050 #if defined(GROUP_OBJ)
00051 #undef GROUP_OBJ
00052 #endif
00053 
00054 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
00055 
00056 #include <rpcsvc/nis.h>
00057 
00058 #endif /* WITH_NISPLUS_HOME */
00059 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
00060 
00061 enum protocol_types Protocol = PROTOCOL_COREPLUS;
00062 
00063 /* a default finfo structure to ensure all fields are sensible */
00064 file_info def_finfo;
00065 
00066 /* this is used by the chaining code */
00067 int chain_size = 0;
00068 
00069 int trans_num = 0;
00070 
00071 static enum remote_arch_types ra_type = RA_UNKNOWN;
00072 pstring user_socket_options=DEFAULT_SOCKET_OPTIONS;   
00073 
00074 /***********************************************************************
00075  Definitions for all names.
00076 ***********************************************************************/
00077 
00078 static char *smb_myname;
00079 static char *smb_myname_override;
00080 static char *smb_myworkgroup;
00081 static char *smb_scope;
00082 static int smb_num_netbios_names;
00083 static char **smb_my_netbios_names;
00084 
00085 /***********************************************************************
00086  Allocate and set myname. Ensure upper case.
00087 ***********************************************************************/
00088 
00089 BOOL set_global_myname(const char *myname)
00090 {
00091         SAFE_FREE(smb_myname);
00092         smb_myname = SMB_STRDUP(myname);
00093         if (!smb_myname)
00094                 return False;
00095         strupper_m(smb_myname);
00096         return True;
00097 }
00098 
00099 const char *global_myname(void)
00100 {
00101         return smb_myname;
00102 }
00103 
00104 
00105 /***********************************************************************
00106  Allocate and set override for myname. Ensure upper case.
00107 ***********************************************************************/
00108 
00109 BOOL set_global_myname_override(const char *myname)
00110 {
00111         SAFE_FREE(smb_myname_override);
00112         smb_myname_override = strdup(myname);
00113         if (!smb_myname_override)
00114                 return False;
00115         strupper_m(smb_myname_override);
00116         return True;
00117 }
00118 
00119 const char *global_myname_override(void)
00120 {
00121         return smb_myname_override;
00122 }
00123 
00124 
00125 /***********************************************************************
00126  Allocate and set myworkgroup. Ensure upper case.
00127 ***********************************************************************/
00128 
00129 BOOL set_global_myworkgroup(const char *myworkgroup)
00130 {
00131         SAFE_FREE(smb_myworkgroup);
00132         smb_myworkgroup = SMB_STRDUP(myworkgroup);
00133         if (!smb_myworkgroup)
00134                 return False;
00135         strupper_m(smb_myworkgroup);
00136         return True;
00137 }
00138 
00139 const char *lp_workgroup(void)
00140 {
00141         return smb_myworkgroup;
00142 }
00143 
00144 /***********************************************************************
00145  Allocate and set scope. Ensure upper case.
00146 ***********************************************************************/
00147 
00148 BOOL set_global_scope(const char *scope)
00149 {
00150         SAFE_FREE(smb_scope);
00151         smb_scope = SMB_STRDUP(scope);
00152         if (!smb_scope)
00153                 return False;
00154         strupper_m(smb_scope);
00155         return True;
00156 }
00157 
00158 /*********************************************************************
00159  Ensure scope is never null string.
00160 *********************************************************************/
00161 
00162 const char *global_scope(void)
00163 {
00164         if (!smb_scope)
00165                 set_global_scope("");
00166         return smb_scope;
00167 }
00168 
00169 static void free_netbios_names_array(void)
00170 {
00171         int i;
00172 
00173         for (i = 0; i < smb_num_netbios_names; i++)
00174                 SAFE_FREE(smb_my_netbios_names[i]);
00175 
00176         SAFE_FREE(smb_my_netbios_names);
00177         smb_num_netbios_names = 0;
00178 }
00179 
00180 static BOOL allocate_my_netbios_names_array(size_t number)
00181 {
00182         free_netbios_names_array();
00183 
00184         smb_num_netbios_names = number + 1;
00185         smb_my_netbios_names = SMB_MALLOC_ARRAY( char *, smb_num_netbios_names );
00186 
00187         if (!smb_my_netbios_names)
00188                 return False;
00189 
00190         memset(smb_my_netbios_names, '\0', sizeof(char *) * smb_num_netbios_names);
00191         return True;
00192 }
00193 
00194 static BOOL set_my_netbios_names(const char *name, int i)
00195 {
00196         SAFE_FREE(smb_my_netbios_names[i]);
00197 
00198         smb_my_netbios_names[i] = SMB_STRDUP(name);
00199         if (!smb_my_netbios_names[i])
00200                 return False;
00201         strupper_m(smb_my_netbios_names[i]);
00202         return True;
00203 }
00204 
00205 /***********************************************************************
00206  Free memory allocated to global objects
00207 ***********************************************************************/
00208 
00209 void gfree_names(void)
00210 {
00211         SAFE_FREE( smb_myname );
00212         SAFE_FREE( smb_myworkgroup );
00213         SAFE_FREE( smb_scope );
00214         free_netbios_names_array();
00215 }
00216 
00217 void gfree_all( void )
00218 {
00219         gfree_names();  
00220         gfree_loadparm();
00221         gfree_case_tables();
00222         gfree_debugsyms();
00223         gfree_charcnv();
00224         gfree_messages();
00225         gfree_interfaces();
00226 
00227         /* release the talloc null_context memory last */
00228         talloc_disable_null_tracking();
00229 }
00230 
00231 const char *my_netbios_names(int i)
00232 {
00233         return smb_my_netbios_names[i];
00234 }
00235 
00236 BOOL set_netbios_aliases(const char **str_array)
00237 {
00238         size_t namecount;
00239 
00240         /* Work out the max number of netbios aliases that we have */
00241         for( namecount=0; str_array && (str_array[namecount] != NULL); namecount++ )
00242                 ;
00243 
00244         if ( global_myname() && *global_myname())
00245                 namecount++;
00246 
00247         /* Allocate space for the netbios aliases */
00248         if (!allocate_my_netbios_names_array(namecount))
00249                 return False;
00250 
00251         /* Use the global_myname string first */
00252         namecount=0;
00253         if ( global_myname() && *global_myname()) {
00254                 set_my_netbios_names( global_myname(), namecount );
00255                 namecount++;
00256         }
00257 
00258         if (str_array) {
00259                 size_t i;
00260                 for ( i = 0; str_array[i] != NULL; i++) {
00261                         size_t n;
00262                         BOOL duplicate = False;
00263 
00264                         /* Look for duplicates */
00265                         for( n=0; n<namecount; n++ ) {
00266                                 if( strequal( str_array[i], my_netbios_names(n) ) ) {
00267                                         duplicate = True;
00268                                         break;
00269                                 }
00270                         }
00271                         if (!duplicate) {
00272                                 if (!set_my_netbios_names(str_array[i], namecount))
00273                                         return False;
00274                                 namecount++;
00275                         }
00276                 }
00277         }
00278         return True;
00279 }
00280 
00281 /****************************************************************************
00282   Common name initialization code.
00283 ****************************************************************************/
00284 
00285 BOOL init_names(void)
00286 {
00287         char *p;
00288         int n;
00289 
00290         if (global_myname() == NULL || *global_myname() == '\0') {
00291                 if (!set_global_myname(myhostname())) {
00292                         DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
00293                         return False;
00294                 }
00295         }
00296 
00297         if (!set_netbios_aliases(lp_netbios_aliases())) {
00298                 DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
00299                 return False;
00300         }                       
00301 
00302         fstrcpy( local_machine, global_myname() );
00303         trim_char( local_machine, ' ', ' ' );
00304         p = strchr( local_machine, ' ' );
00305         if (p)
00306                 *p = 0;
00307         strlower_m( local_machine );
00308 
00309         DEBUG( 5, ("Netbios name list:-\n") );
00310         for( n=0; my_netbios_names(n); n++ )
00311                 DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names(n) ) );
00312 
00313         return( True );
00314 }
00315 
00316 /**************************************************************************n
00317  Find a suitable temporary directory. The result should be copied immediately
00318  as it may be overwritten by a subsequent call.
00319 ****************************************************************************/
00320 
00321 const char *tmpdir(void)
00322 {
00323         char *p;
00324         if ((p = getenv("TMPDIR")))
00325                 return p;
00326         return "/tmp";
00327 }
00328 
00329 /****************************************************************************
00330  Add a gid to an array of gids if it's not already there.
00331 ****************************************************************************/
00332 
00333 BOOL add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid,
00334                              gid_t **gids, size_t *num_gids)
00335 {
00336         int i;
00337 
00338         if ((*num_gids != 0) && (*gids == NULL)) {
00339                 /*
00340                  * A former call to this routine has failed to allocate memory
00341                  */
00342                 return False;
00343         }
00344 
00345         for (i=0; i<*num_gids; i++) {
00346                 if ((*gids)[i] == gid) {
00347                         return True;
00348                 }
00349         }
00350 
00351         *gids = TALLOC_REALLOC_ARRAY(mem_ctx, *gids, gid_t, *num_gids+1);
00352         if (*gids == NULL) {
00353                 *num_gids = 0;
00354                 return False;
00355         }
00356 
00357         (*gids)[*num_gids] = gid;
00358         *num_gids += 1;
00359         return True;
00360 }
00361 
00362 /****************************************************************************
00363  Like atoi but gets the value up to the separator character.
00364 ****************************************************************************/
00365 
00366 static const char *Atoic(const char *p, int *n, const char *c)
00367 {
00368         if (!isdigit((int)*p)) {
00369                 DEBUG(5, ("Atoic: malformed number\n"));
00370                 return NULL;
00371         }
00372 
00373         (*n) = atoi(p);
00374 
00375         while ((*p) && isdigit((int)*p))
00376                 p++;
00377 
00378         if (strchr_m(c, *p) == NULL) {
00379                 DEBUG(5, ("Atoic: no separator characters (%s) not found\n", c));
00380                 return NULL;
00381         }
00382 
00383         return p;
00384 }
00385 
00386 /*************************************************************************
00387  Reads a list of numbers.
00388  *************************************************************************/
00389 
00390 const char *get_numlist(const char *p, uint32 **num, int *count)
00391 {
00392         int val;
00393 
00394         if (num == NULL || count == NULL)
00395                 return NULL;
00396 
00397         (*count) = 0;
00398         (*num  ) = NULL;
00399 
00400         while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':') {
00401                 *num = SMB_REALLOC_ARRAY((*num), uint32, (*count)+1);
00402                 if (!(*num)) {
00403                         return NULL;
00404                 }
00405                 (*num)[(*count)] = val;
00406                 (*count)++;
00407                 p++;
00408         }
00409 
00410         return p;
00411 }
00412 
00413 /*******************************************************************
00414  Check if a file exists - call vfs_file_exist for samba files.
00415 ********************************************************************/
00416 
00417 BOOL file_exist(const char *fname,SMB_STRUCT_STAT *sbuf)
00418 {
00419         SMB_STRUCT_STAT st;
00420         if (!sbuf)
00421                 sbuf = &st;
00422   
00423         if (sys_stat(fname,sbuf) != 0) 
00424                 return(False);
00425 
00426         return((S_ISREG(sbuf->st_mode)) || (S_ISFIFO(sbuf->st_mode)));
00427 }
00428 
00429 /*******************************************************************
00430  Check a files mod time.
00431 ********************************************************************/
00432 
00433 time_t file_modtime(const char *fname)
00434 {
00435         SMB_STRUCT_STAT st;
00436   
00437         if (sys_stat(fname,&st) != 0) 
00438                 return(0);
00439 
00440         return(st.st_mtime);
00441 }
00442 
00443 /*******************************************************************
00444  Check if a directory exists.
00445 ********************************************************************/
00446 
00447 BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
00448 {
00449         SMB_STRUCT_STAT st2;
00450         BOOL ret;
00451 
00452         if (!st)
00453                 st = &st2;
00454 
00455         if (sys_stat(dname,st) != 0) 
00456                 return(False);
00457 
00458         ret = S_ISDIR(st->st_mode);
00459         if(!ret)
00460                 errno = ENOTDIR;
00461         return ret;
00462 }
00463 
00464 /*******************************************************************
00465  Returns the size in bytes of the named file.
00466 ********************************************************************/
00467 
00468 SMB_OFF_T get_file_size(char *file_name)
00469 {
00470         SMB_STRUCT_STAT buf;
00471         buf.st_size = 0;
00472         if(sys_stat(file_name,&buf) != 0)
00473                 return (SMB_OFF_T)-1;
00474         return(buf.st_size);
00475 }
00476 
00477 /*******************************************************************
00478  Return a string representing an attribute for a file.
00479 ********************************************************************/
00480 
00481 char *attrib_string(uint16 mode)
00482 {
00483         static fstring attrstr;
00484 
00485         attrstr[0] = 0;
00486 
00487         if (mode & aVOLID) fstrcat(attrstr,"V");
00488         if (mode & aDIR) fstrcat(attrstr,"D");
00489         if (mode & aARCH) fstrcat(attrstr,"A");
00490         if (mode & aHIDDEN) fstrcat(attrstr,"H");
00491         if (mode & aSYSTEM) fstrcat(attrstr,"S");
00492         if (mode & aRONLY) fstrcat(attrstr,"R");          
00493 
00494         return(attrstr);
00495 }
00496 
00497 /*******************************************************************
00498  Show a smb message structure.
00499 ********************************************************************/
00500 
00501 void show_msg(char *buf)
00502 {
00503         int i;
00504         int bcc=0;
00505 
00506         if (!DEBUGLVL(5))
00507                 return;
00508         
00509         DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
00510                         smb_len(buf),
00511                         (int)CVAL(buf,smb_com),
00512                         (int)CVAL(buf,smb_rcls),
00513                         (int)CVAL(buf,smb_reh),
00514                         (int)SVAL(buf,smb_err),
00515                         (int)CVAL(buf,smb_flg),
00516                         (int)SVAL(buf,smb_flg2)));
00517         DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
00518                         (int)SVAL(buf,smb_tid),
00519                         (int)SVAL(buf,smb_pid),
00520                         (int)SVAL(buf,smb_uid),
00521                         (int)SVAL(buf,smb_mid)));
00522         DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct)));
00523 
00524         for (i=0;i<(int)CVAL(buf,smb_wct);i++)
00525                 DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
00526                         SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
00527         
00528         bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
00529 
00530         DEBUGADD(5,("smb_bcc=%d\n",bcc));
00531 
00532         if (DEBUGLEVEL < 10)
00533                 return;
00534 
00535         if (DEBUGLEVEL < 50)
00536                 bcc = MIN(bcc, 512);
00537 
00538         dump_data(10, smb_buf(buf), bcc);       
00539 }
00540 
00541 /*******************************************************************
00542  Set the length and marker of an smb packet.
00543 ********************************************************************/
00544 
00545 void smb_setlen(char *buf,int len)
00546 {
00547         _smb_setlen(buf,len);
00548 
00549         SCVAL(buf,4,0xFF);
00550         SCVAL(buf,5,'S');
00551         SCVAL(buf,6,'M');
00552         SCVAL(buf,7,'B');
00553 }
00554 
00555 /*******************************************************************
00556  Setup the word count and byte count for a smb message.
00557 ********************************************************************/
00558 
00559 int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
00560 {
00561         if (zero && (num_words || num_bytes)) {
00562                 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
00563         }
00564         SCVAL(buf,smb_wct,num_words);
00565         SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);  
00566         smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
00567         return (smb_size + num_words*2 + num_bytes);
00568 }
00569 
00570 /*******************************************************************
00571  Setup only the byte count for a smb message.
00572 ********************************************************************/
00573 
00574 int set_message_bcc(char *buf,int num_bytes)
00575 {
00576         int num_words = CVAL(buf,smb_wct);
00577         SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);  
00578         smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
00579         return (smb_size + num_words*2 + num_bytes);
00580 }
00581 
00582 /*******************************************************************
00583  Setup only the byte count for a smb message, using the end of the
00584  message as a marker.
00585 ********************************************************************/
00586 
00587 int set_message_end(void *outbuf,void *end_ptr)
00588 {
00589         return set_message_bcc((char *)outbuf,PTR_DIFF(end_ptr,smb_buf((char *)outbuf)));
00590 }
00591 
00592 /*******************************************************************
00593  Reduce a file name, removing .. elements.
00594 ********************************************************************/
00595 
00596 void dos_clean_name(char *s)
00597 {
00598         char *p=NULL;
00599 
00600         DEBUG(3,("dos_clean_name [%s]\n",s));
00601 
00602         /* remove any double slashes */
00603         all_string_sub(s, "\\\\", "\\", 0);
00604 
00605         /* Remove leading .\\ characters */
00606         if(strncmp(s, ".\\", 2) == 0) {
00607                 trim_string(s, ".\\", NULL);
00608                 if(*s == 0)
00609                         pstrcpy(s,".\\");
00610         }
00611 
00612         while ((p = strstr_m(s,"\\..\\")) != NULL) {
00613                 pstring s1;
00614 
00615                 *p = 0;
00616                 pstrcpy(s1,p+3);
00617 
00618                 if ((p=strrchr_m(s,'\\')) != NULL)
00619                         *p = 0;
00620                 else
00621                         *s = 0;
00622                 pstrcat(s,s1);
00623         }  
00624 
00625         trim_string(s,NULL,"\\..");
00626         all_string_sub(s, "\\.\\", "\\", 0);
00627 }
00628 
00629 /*******************************************************************
00630  Reduce a file name, removing .. elements. 
00631 ********************************************************************/
00632 
00633 void unix_clean_name(char *s)
00634 {
00635         char *p=NULL;
00636 
00637         DEBUG(3,("unix_clean_name [%s]\n",s));
00638 
00639         /* remove any double slashes */
00640         all_string_sub(s, "//","/", 0);
00641 
00642         /* Remove leading ./ characters */
00643         if(strncmp(s, "./", 2) == 0) {
00644                 trim_string(s, "./", NULL);
00645                 if(*s == 0)
00646                         pstrcpy(s,"./");
00647         }
00648 
00649         while ((p = strstr_m(s,"/../")) != NULL) {
00650                 pstring s1;
00651 
00652                 *p = 0;
00653                 pstrcpy(s1,p+3);
00654 
00655                 if ((p=strrchr_m(s,'/')) != NULL)
00656                         *p = 0;
00657                 else
00658                         *s = 0;
00659                 pstrcat(s,s1);
00660         }  
00661 
00662         trim_string(s,NULL,"/..");
00663         all_string_sub(s, "/./", "/", 0);
00664 }
00665 
00666 void clean_name(char *s)
00667 {
00668         dos_clean_name(s);
00669         unix_clean_name(s);
00670 }
00671 
00672 /*******************************************************************
00673  Close the low 3 fd's and open dev/null in their place.
00674 ********************************************************************/
00675 
00676 void close_low_fds(BOOL stderr_too)
00677 {
00678 #ifndef VALGRIND
00679         int fd;
00680         int i;
00681 
00682         close(0);
00683         close(1); 
00684 
00685         if (stderr_too)
00686                 close(2);
00687 
00688         /* try and use up these file descriptors, so silly
00689                 library routines writing to stdout etc won't cause havoc */
00690         for (i=0;i<3;i++) {
00691                 if (i == 2 && !stderr_too)
00692                         continue;
00693 
00694                 fd = sys_open("/dev/null",O_RDWR,0);
00695                 if (fd < 0)
00696                         fd = sys_open("/dev/null",O_WRONLY,0);
00697                 if (fd < 0) {
00698                         DEBUG(0,("Can't open /dev/null\n"));
00699                         return;
00700                 }
00701                 if (fd != i) {
00702                         DEBUG(0,("Didn't get file descriptor %d\n",i));
00703                         return;
00704                 }
00705         }
00706 #endif
00707 }
00708 
00709 /*******************************************************************
00710  Write data into an fd at a given offset. Ignore seek errors.
00711 ********************************************************************/
00712 
00713 ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos)
00714 {
00715         size_t total=0;
00716         ssize_t ret;
00717 
00718         if (pos == (SMB_OFF_T)-1) {
00719                 return write_data(fd, buffer, N);
00720         }
00721 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
00722         while (total < N) {
00723                 ret = sys_pwrite(fd,buffer + total,N - total, pos);
00724                 if (ret == -1 && errno == ESPIPE) {
00725                         return write_data(fd, buffer + total,N - total);
00726                 }
00727                 if (ret == -1) {
00728                         DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
00729                         return -1;
00730                 }
00731                 if (ret == 0) {
00732                         return total;
00733                 }
00734                 total += ret;
00735                 pos += ret;
00736         }
00737         return (ssize_t)total;
00738 #else
00739         /* Use lseek and write_data. */
00740         if (sys_lseek(fd, pos, SEEK_SET) == -1) {
00741                 if (errno != ESPIPE) {
00742                         return -1;
00743                 }
00744         }
00745         return write_data(fd, buffer, N);
00746 #endif
00747 }
00748 
00749 /****************************************************************************
00750  Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
00751  else
00752   if SYSV use O_NDELAY
00753   if BSD use FNDELAY
00754 ****************************************************************************/
00755 
00756 int set_blocking(int fd, BOOL set)
00757 {
00758         int val;
00759 #ifdef O_NONBLOCK
00760 #define FLAG_TO_SET O_NONBLOCK
00761 #else
00762 #ifdef SYSV
00763 #define FLAG_TO_SET O_NDELAY
00764 #else /* BSD */
00765 #define FLAG_TO_SET FNDELAY
00766 #endif
00767 #endif
00768 
00769         if((val = sys_fcntl_long(fd, F_GETFL, 0)) == -1)
00770                 return -1;
00771         if(set) /* Turn blocking on - ie. clear nonblock flag */
00772                 val &= ~FLAG_TO_SET;
00773         else
00774                 val |= FLAG_TO_SET;
00775         return sys_fcntl_long( fd, F_SETFL, val);
00776 #undef FLAG_TO_SET
00777 }
00778 
00779 /****************************************************************************
00780  Transfer some data between two fd's.
00781 ****************************************************************************/
00782 
00783 #ifndef TRANSFER_BUF_SIZE
00784 #define TRANSFER_BUF_SIZE 65536
00785 #endif
00786 
00787 ssize_t transfer_file_internal(int infd, int outfd, size_t n, ssize_t (*read_fn)(int, void *, size_t),
00788                                                 ssize_t (*write_fn)(int, const void *, size_t))
00789 {
00790         char *buf;
00791         size_t total = 0;
00792         ssize_t read_ret;
00793         ssize_t write_ret;
00794         size_t num_to_read_thistime;
00795         size_t num_written = 0;
00796 
00797         if ((buf = SMB_MALLOC_ARRAY(char, TRANSFER_BUF_SIZE)) == NULL)
00798                 return -1;
00799 
00800         while (total < n) {
00801                 num_to_read_thistime = MIN((n - total), TRANSFER_BUF_SIZE);
00802 
00803                 read_ret = (*read_fn)(infd, buf, num_to_read_thistime);
00804                 if (read_ret == -1) {
00805                         DEBUG(0,("transfer_file_internal: read failure. Error = %s\n", strerror(errno) ));
00806                         SAFE_FREE(buf);
00807                         return -1;
00808                 }
00809                 if (read_ret == 0)
00810                         break;
00811 
00812                 num_written = 0;
00813  
00814                 while (num_written < read_ret) {
00815                         write_ret = (*write_fn)(outfd,buf + num_written, read_ret - num_written);
00816  
00817                         if (write_ret == -1) {
00818                                 DEBUG(0,("transfer_file_internal: write failure. Error = %s\n", strerror(errno) ));
00819                                 SAFE_FREE(buf);
00820                                 return -1;
00821                         }
00822                         if (write_ret == 0)
00823                                 return (ssize_t)total;
00824  
00825                         num_written += (size_t)write_ret;
00826                 }
00827 
00828                 total += (size_t)read_ret;
00829         }
00830 
00831         SAFE_FREE(buf);
00832         return (ssize_t)total;          
00833 }
00834 
00835 SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n)
00836 {
00837         return (SMB_OFF_T)transfer_file_internal(infd, outfd, (size_t)n, sys_read, sys_write);
00838 }
00839 
00840 /*******************************************************************
00841  Sleep for a specified number of milliseconds.
00842 ********************************************************************/
00843 
00844 void smb_msleep(unsigned int t)
00845 {
00846 #if defined(HAVE_NANOSLEEP)
00847         struct timespec tval;
00848         int ret;
00849 
00850         tval.tv_sec = t/1000;
00851         tval.tv_nsec = 1000000*(t%1000);
00852 
00853         do {
00854                 errno = 0;
00855                 ret = nanosleep(&tval, &tval);
00856         } while (ret < 0 && errno == EINTR && (tval.tv_sec > 0 || tval.tv_nsec > 0));
00857 #else
00858         unsigned int tdiff=0;
00859         struct timeval tval,t1,t2;  
00860         fd_set fds;
00861 
00862         GetTimeOfDay(&t1);
00863         t2 = t1;
00864   
00865         while (tdiff < t) {
00866                 tval.tv_sec = (t-tdiff)/1000;
00867                 tval.tv_usec = 1000*((t-tdiff)%1000);
00868 
00869                 /* Never wait for more than 1 sec. */
00870                 if (tval.tv_sec > 1) {
00871                         tval.tv_sec = 1; 
00872                         tval.tv_usec = 0;
00873                 }
00874 
00875                 FD_ZERO(&fds);
00876                 errno = 0;
00877                 sys_select_intr(0,&fds,NULL,NULL,&tval);
00878 
00879                 GetTimeOfDay(&t2);
00880                 if (t2.tv_sec < t1.tv_sec) {
00881                         /* Someone adjusted time... */
00882                         t1 = t2;
00883                 }
00884 
00885                 tdiff = TvalDiff(&t1,&t2);
00886         }
00887 #endif
00888 }
00889 
00890 /****************************************************************************
00891  Become a daemon, discarding the controlling terminal.
00892 ****************************************************************************/
00893 
00894 void become_daemon(BOOL Fork, BOOL no_process_group)
00895 {
00896         if (Fork) {
00897                 if (sys_fork()) {
00898                         _exit(0);
00899                 }
00900         }
00901 
00902   /* detach from the terminal */
00903 #ifdef HAVE_SETSID
00904         if (!no_process_group) setsid();
00905 #elif defined(TIOCNOTTY)
00906         if (!no_process_group) {
00907                 int i = sys_open("/dev/tty", O_RDWR, 0);
00908                 if (i != -1) {
00909                         ioctl(i, (int) TIOCNOTTY, (char *)0);      
00910                         close(i);
00911                 }
00912         }
00913 #endif /* HAVE_SETSID */
00914 
00915         /* Close fd's 0,1,2. Needed if started by rsh */
00916         close_low_fds(False);  /* Don't close stderr, let the debug system
00917                                   attach it to the logfile */
00918 }
00919 
00920 /****************************************************************************
00921  Put up a yes/no prompt.
00922 ****************************************************************************/
00923 
00924 BOOL yesno(char *p)
00925 {
00926         pstring ans;
00927         printf("%s",p);
00928 
00929         if (!fgets(ans,sizeof(ans)-1,stdin))
00930                 return(False);
00931 
00932         if (*ans == 'y' || *ans == 'Y')
00933                 return(True);
00934 
00935         return(False);
00936 }
00937 
00938 #if defined(PARANOID_MALLOC_CHECKER)
00939 
00940 /****************************************************************************
00941  Internal malloc wrapper. Externally visible.
00942 ****************************************************************************/
00943 
00944 void *malloc_(size_t size)
00945 {
00946         if (size == 0) {
00947                 return NULL;
00948         }
00949 #undef malloc
00950         return malloc(size);
00951 #define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
00952 }
00953 
00954 /****************************************************************************
00955  Internal calloc wrapper. Not externally visible.
00956 ****************************************************************************/
00957 
00958 static void *calloc_(size_t count, size_t size)
00959 {
00960         if (size == 0 || count == 0) {
00961                 return NULL;
00962         }
00963 #undef calloc
00964         return calloc(count, size);
00965 #define calloc(n,s) __ERROR_DONT_USE_CALLOC_DIRECTLY
00966 }
00967 
00968 /****************************************************************************
00969  Internal realloc wrapper. Not externally visible.
00970 ****************************************************************************/
00971 
00972 static void *realloc_(void *ptr, size_t size)
00973 {
00974 #undef realloc
00975         return realloc(ptr, size);
00976 #define realloc(p,s) __ERROR_DONT_USE_RELLOC_DIRECTLY
00977 }
00978 
00979 #endif /* PARANOID_MALLOC_CHECKER */
00980 
00981 /****************************************************************************
00982  Type-safe malloc.
00983 ****************************************************************************/
00984 
00985 void *malloc_array(size_t el_size, unsigned int count)
00986 {
00987         if (count >= MAX_ALLOC_SIZE/el_size) {
00988                 return NULL;
00989         }
00990 
00991         if (el_size == 0 || count == 0) {
00992                 return NULL;
00993         }
00994 #if defined(PARANOID_MALLOC_CHECKER)
00995         return malloc_(el_size*count);
00996 #else
00997         return malloc(el_size*count);
00998 #endif
00999 }
01000 
01001 /****************************************************************************
01002  Type-safe memalign
01003 ****************************************************************************/
01004 
01005 void *memalign_array(size_t el_size, size_t align, unsigned int count)
01006 {
01007         if (count >= MAX_ALLOC_SIZE/el_size) {
01008                 return NULL;
01009         }
01010 
01011         return sys_memalign(align, el_size*count);
01012 }
01013 
01014 /****************************************************************************
01015  Type-safe calloc.
01016 ****************************************************************************/
01017 
01018 void *calloc_array(size_t size, size_t nmemb)
01019 {
01020         if (nmemb >= MAX_ALLOC_SIZE/size) {
01021                 return NULL;
01022         }
01023         if (size == 0 || nmemb == 0) {
01024                 return NULL;
01025         }
01026 #if defined(PARANOID_MALLOC_CHECKER)
01027         return calloc_(nmemb, size);
01028 #else
01029         return calloc(nmemb, size);
01030 #endif
01031 }
01032 
01033 /****************************************************************************
01034  Expand a pointer to be a particular size.
01035  Note that this version of Realloc has an extra parameter that decides
01036  whether to free the passed in storage on allocation failure or if the
01037  new size is zero.
01038 
01039  This is designed for use in the typical idiom of :
01040 
01041  p = SMB_REALLOC(p, size)
01042  if (!p) {
01043     return error;
01044  }
01045 
01046  and not to have to keep track of the old 'p' contents to free later, nor
01047  to worry if the size parameter was zero. In the case where NULL is returned
01048  we guarentee that p has been freed.
01049 
01050  If free later semantics are desired, then pass 'free_old_on_error' as False which
01051  guarentees that the old contents are not freed on error, even if size == 0. To use
01052  this idiom use :
01053 
01054  tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
01055  if (!tmp) {
01056     SAFE_FREE(p);
01057     return error;
01058  } else {
01059     p = tmp;
01060  }
01061 
01062  Changes were instigated by Coverity error checking. JRA.
01063 ****************************************************************************/
01064 
01065 void *Realloc(void *p, size_t size, BOOL free_old_on_error)
01066 {
01067         void *ret=NULL;
01068 
01069         if (size == 0) {
01070                 if (free_old_on_error) {
01071                         SAFE_FREE(p);
01072                 }
01073                 DEBUG(2,("Realloc asked for 0 bytes\n"));
01074                 return NULL;
01075         }
01076 
01077 #if defined(PARANOID_MALLOC_CHECKER)
01078         if (!p) {
01079                 ret = (void *)malloc_(size);
01080         } else {
01081                 ret = (void *)realloc_(p,size);
01082         }
01083 #else
01084         if (!p) {
01085                 ret = (void *)malloc(size);
01086         } else {
01087                 ret = (void *)realloc(p,size);
01088         }
01089 #endif
01090 
01091         if (!ret) {
01092                 if (free_old_on_error && p) {
01093                         SAFE_FREE(p);
01094                 }
01095                 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
01096         }
01097 
01098         return(ret);
01099 }
01100 
01101 /****************************************************************************
01102  Type-safe realloc.
01103 ****************************************************************************/
01104 
01105 void *realloc_array(void *p, size_t el_size, unsigned int count, BOOL free_old_on_error)
01106 {
01107         if (count >= MAX_ALLOC_SIZE/el_size) {
01108                 if (free_old_on_error) {
01109                         SAFE_FREE(p);
01110                 }
01111                 return NULL;
01112         }
01113         return Realloc(p, el_size*count, free_old_on_error);
01114 }
01115 
01116 /****************************************************************************
01117  (Hopefully) efficient array append.
01118 ****************************************************************************/
01119 
01120 void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
01121                         void *element, void *_array, uint32 *num_elements,
01122                         ssize_t *array_size)
01123 {
01124         void **array = (void **)_array;
01125 
01126         if (*array_size < 0) {
01127                 return;
01128         }
01129 
01130         if (*array == NULL) {
01131                 if (*array_size == 0) {
01132                         *array_size = 128;
01133                 }
01134 
01135                 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
01136                         goto error;
01137                 }
01138 
01139                 *array = TALLOC(mem_ctx, element_size * (*array_size));
01140                 if (*array == NULL) {
01141                         goto error;
01142                 }
01143         }
01144 
01145         if (*num_elements == *array_size) {
01146                 *array_size *= 2;
01147 
01148                 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
01149                         goto error;
01150                 }
01151 
01152                 *array = TALLOC_REALLOC(mem_ctx, *array,
01153                                         element_size * (*array_size));
01154 
01155                 if (*array == NULL) {
01156                         goto error;
01157                 }
01158         }
01159 
01160         memcpy((char *)(*array) + element_size*(*num_elements),
01161                element, element_size);
01162         *num_elements += 1;
01163 
01164         return;
01165 
01166  error:
01167         *num_elements = 0;
01168         *array_size = -1;
01169 }
01170 
01171 /****************************************************************************
01172  Free memory, checks for NULL.
01173  Use directly SAFE_FREE()
01174  Exists only because we need to pass a function pointer somewhere --SSS
01175 ****************************************************************************/
01176 
01177 void safe_free(void *p)
01178 {
01179         SAFE_FREE(p);
01180 }
01181 
01182 /****************************************************************************
01183  Get my own name and IP.
01184 ****************************************************************************/
01185 
01186 BOOL get_myname(char *my_name)
01187 {
01188         pstring hostname;
01189 
01190         *hostname = 0;
01191 
01192         /* get my host name */
01193         if (gethostname(hostname, sizeof(hostname)) == -1) {
01194                 DEBUG(0,("gethostname failed\n"));
01195                 return False;
01196         } 
01197 
01198         /* Ensure null termination. */
01199         hostname[sizeof(hostname)-1] = '\0';
01200 
01201         if (my_name) {
01202                 /* split off any parts after an initial . */
01203                 char *p = strchr_m(hostname,'.');
01204 
01205                 if (p)
01206                         *p = 0;
01207                 
01208                 fstrcpy(my_name,hostname);
01209         }
01210         
01211         return(True);
01212 }
01213 
01214 /****************************************************************************
01215  Get my own canonical name, including domain.
01216 ****************************************************************************/
01217 
01218 BOOL get_mydnsfullname(fstring my_dnsname)
01219 {
01220         static fstring dnshostname;
01221         struct hostent *hp;
01222 
01223         if (!*dnshostname) {
01224                 /* get my host name */
01225                 if (gethostname(dnshostname, sizeof(dnshostname)) == -1) {
01226                         *dnshostname = '\0';
01227                         DEBUG(0,("gethostname failed\n"));
01228                         return False;
01229                 } 
01230 
01231                 /* Ensure null termination. */
01232                 dnshostname[sizeof(dnshostname)-1] = '\0';
01233 
01234                 /* Ensure we get the cannonical name. */
01235                 if (!(hp = sys_gethostbyname(dnshostname))) {
01236                         *dnshostname = '\0';
01237                         return False;
01238                 }
01239                 fstrcpy(dnshostname, hp->h_name);
01240         }
01241         fstrcpy(my_dnsname, dnshostname);
01242         return True;
01243 }
01244 
01245 /****************************************************************************
01246  Get my own domain name.
01247 ****************************************************************************/
01248 
01249 BOOL get_mydnsdomname(fstring my_domname)
01250 {
01251         fstring domname;
01252         char *p;
01253 
01254         *my_domname = '\0';
01255         if (!get_mydnsfullname(domname)) {
01256                 return False;
01257         }       
01258         p = strchr_m(domname, '.');
01259         if (p) {
01260                 p++;
01261                 fstrcpy(my_domname, p);
01262                 return True;
01263         }
01264 
01265         return False;
01266 }
01267 
01268 /****************************************************************************
01269  Interpret a protocol description string, with a default.
01270 ****************************************************************************/
01271 
01272 int interpret_protocol(const char *str,int def)
01273 {
01274         if (strequal(str,"NT1"))
01275                 return(PROTOCOL_NT1);
01276         if (strequal(str,"LANMAN2"))
01277                 return(PROTOCOL_LANMAN2);
01278         if (strequal(str,"LANMAN1"))
01279                 return(PROTOCOL_LANMAN1);
01280         if (strequal(str,"CORE"))
01281                 return(PROTOCOL_CORE);
01282         if (strequal(str,"COREPLUS"))
01283                 return(PROTOCOL_COREPLUS);
01284         if (strequal(str,"CORE+"))
01285                 return(PROTOCOL_COREPLUS);
01286   
01287         DEBUG(0,("Unrecognised protocol level %s\n",str));
01288   
01289         return(def);
01290 }
01291 
01292 /****************************************************************************
01293  Return true if a string could be a pure IP address.
01294 ****************************************************************************/
01295 
01296 BOOL is_ipaddress(const char *str)
01297 {
01298         BOOL pure_address = True;
01299         int i;
01300   
01301         for (i=0; pure_address && str[i]; i++)
01302                 if (!(isdigit((int)str[i]) || str[i] == '.'))
01303                         pure_address = False;
01304 
01305         /* Check that a pure number is not misinterpreted as an IP */
01306         pure_address = pure_address && (strchr_m(str, '.') != NULL);
01307 
01308         return pure_address;
01309 }
01310 
01311 /****************************************************************************
01312  Interpret an internet address or name into an IP address in 4 byte form.
01313 ****************************************************************************/
01314 
01315 uint32 interpret_addr(const char *str)
01316 {
01317         struct hostent *hp;
01318         uint32 res;
01319 
01320         if (strcmp(str,"0.0.0.0") == 0)
01321                 return(0);
01322         if (strcmp(str,"255.255.255.255") == 0)
01323                 return(0xFFFFFFFF);
01324 
01325   /* if it's in the form of an IP address then get the lib to interpret it */
01326         if (is_ipaddress(str)) {
01327                 res = inet_addr(str);
01328         } else {
01329                 /* otherwise assume it's a network name of some sort and use 
01330                         sys_gethostbyname */
01331                 if ((hp = sys_gethostbyname(str)) == 0) {
01332                         DEBUG(3,("sys_gethostbyname: Unknown host. %s\n",str));
01333                         return 0;
01334                 }
01335 
01336                 if(hp->h_addr == NULL) {
01337                         DEBUG(3,("sys_gethostbyname: host address is invalid for host %s\n",str));
01338                         return 0;
01339                 }
01340                 putip((char *)&res,(char *)hp->h_addr);
01341         }
01342 
01343         if (res == (uint32)-1)
01344                 return(0);
01345 
01346         return(res);
01347 }
01348 
01349 /*******************************************************************
01350  A convenient addition to interpret_addr().
01351 ******************************************************************/
01352 
01353 struct in_addr *interpret_addr2(const char *str)
01354 {
01355         static struct in_addr ret;
01356         uint32 a = interpret_addr(str);
01357         ret.s_addr = a;
01358         return(&ret);
01359 }
01360 
01361 /*******************************************************************
01362  Check if an IP is the 0.0.0.0.
01363 ******************************************************************/
01364 
01365 BOOL is_zero_ip(struct in_addr ip)
01366 {
01367         uint32 a;
01368         putip((char *)&a,(char *)&ip);
01369         return(a == 0);
01370 }
01371 
01372 /*******************************************************************
01373  Set an IP to 0.0.0.0.
01374 ******************************************************************/
01375 
01376 void zero_ip(struct in_addr *ip)
01377 {
01378         static BOOL init;
01379         static struct in_addr ipzero;
01380 
01381         if (!init) {
01382                 ipzero = *interpret_addr2("0.0.0.0");
01383                 init = True;
01384         }
01385 
01386         *ip = ipzero;
01387 }
01388 
01389 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
01390 /******************************************************************
01391  Remove any mount options such as -rsize=2048,wsize=2048 etc.
01392  Based on a fix from <Thomas.Hepper@icem.de>.
01393 *******************************************************************/
01394 
01395 static void strip_mount_options( pstring *str)
01396 {
01397         if (**str == '-') { 
01398                 char *p = *str;
01399                 while(*p && !isspace(*p))
01400                         p++;
01401                 while(*p && isspace(*p))
01402                         p++;
01403                 if(*p) {
01404                         pstring tmp_str;
01405 
01406                         pstrcpy(tmp_str, p);
01407                         pstrcpy(*str, tmp_str);
01408                 }
01409         }
01410 }
01411 
01412 /*******************************************************************
01413  Patch from jkf@soton.ac.uk
01414  Split Luke's automount_server into YP lookup and string splitter
01415  so can easily implement automount_path(). 
01416  As we may end up doing both, cache the last YP result. 
01417 *******************************************************************/
01418 
01419 #ifdef WITH_NISPLUS_HOME
01420 char *automount_lookup(const char *user_name)
01421 {
01422         static fstring last_key = "";
01423         static pstring last_value = "";
01424  
01425         char *nis_map = (char *)lp_nis_home_map_name();
01426  
01427         char buffer[NIS_MAXATTRVAL + 1];
01428         nis_result *result;
01429         nis_object *object;
01430         entry_obj  *entry;
01431  
01432         if (strcmp(user_name, last_key)) {
01433                 slprintf(buffer, sizeof(buffer)-1, "[key=%s],%s", user_name, nis_map);
01434                 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
01435  
01436                 if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
01437                         if (result->status != NIS_SUCCESS) {
01438                                 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
01439                                 fstrcpy(last_key, ""); pstrcpy(last_value, "");
01440                         } else {
01441                                 object = result->objects.objects_val;
01442                                 if (object->zo_data.zo_type == ENTRY_OBJ) {
01443                                         entry = &object->zo_data.objdata_u.en_data;
01444                                         DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
01445                                         DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
01446  
01447                                         pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
01448                                         pstring_sub(last_value, "&", user_name);
01449                                         fstrcpy(last_key, user_name);
01450                                 }
01451                         }
01452                 }
01453                 nis_freeresult(result);
01454         }
01455 
01456         strip_mount_options(&last_value);
01457 
01458         DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
01459         return last_value;
01460 }
01461 #else /* WITH_NISPLUS_HOME */
01462 
01463 char *automount_lookup(const char *user_name)
01464 {
01465         static fstring last_key = "";
01466         static pstring last_value = "";
01467 
01468         int nis_error;        /* returned by yp all functions */
01469         char *nis_result;     /* yp_match inits this */
01470         int nis_result_len;  /* and set this */
01471         char *nis_domain;     /* yp_get_default_domain inits this */
01472         char *nis_map = (char *)lp_nis_home_map_name();
01473 
01474         if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
01475                 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
01476                 return last_value;
01477         }
01478 
01479         DEBUG(5, ("NIS Domain: %s\n", nis_domain));
01480 
01481         if (!strcmp(user_name, last_key)) {
01482                 nis_result = last_value;
01483                 nis_result_len = strlen(last_value);
01484                 nis_error = 0;
01485         } else {
01486                 if ((nis_error = yp_match(nis_domain, nis_map, user_name, strlen(user_name),
01487                                 &nis_result, &nis_result_len)) == 0) {
01488                         fstrcpy(last_key, user_name);
01489                         pstrcpy(last_value, nis_result);
01490                         strip_mount_options(&last_value);
01491 
01492                 } else if(nis_error == YPERR_KEY) {
01493 
01494                         /* If Key lookup fails user home server is not in nis_map 
01495                                 use default information for server, and home directory */
01496                         last_value[0] = 0;
01497                         DEBUG(3, ("YP Key not found:  while looking up \"%s\" in map \"%s\"\n", 
01498                                         user_name, nis_map));
01499                         DEBUG(3, ("using defaults for server and home directory\n"));
01500                 } else {
01501                         DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n", 
01502                                         yperr_string(nis_error), user_name, nis_map));
01503                 }
01504         }
01505 
01506         DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
01507         return last_value;
01508 }
01509 #endif /* WITH_NISPLUS_HOME */
01510 #endif
01511 
01512 /*******************************************************************
01513  Are two IPs on the same subnet?
01514 ********************************************************************/
01515 
01516 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
01517 {
01518         uint32 net1,net2,nmask;
01519 
01520         nmask = ntohl(mask.s_addr);
01521         net1  = ntohl(ip1.s_addr);
01522         net2  = ntohl(ip2.s_addr);
01523             
01524         return((net1 & nmask) == (net2 & nmask));
01525 }
01526 
01527 
01528 /****************************************************************************
01529  Check if a process exists. Does this work on all unixes?
01530 ****************************************************************************/
01531 
01532 BOOL process_exists(const struct process_id pid)
01533 {
01534         if (procid_is_me(&pid)) {
01535                 return True;
01536         }
01537 
01538         if (!procid_is_local(&pid)) {
01539                 /* This *SEVERELY* needs fixing. */
01540                 return True;
01541         }
01542 
01543         /* Doing kill with a non-positive pid causes messages to be
01544          * sent to places we don't want. */
01545         SMB_ASSERT(pid.pid > 0);
01546         return(kill(pid.pid,0) == 0 || errno != ESRCH);
01547 }
01548 
01549 BOOL process_exists_by_pid(pid_t pid)
01550 {
01551         return process_exists(pid_to_procid(pid));
01552 }
01553 
01554 /*******************************************************************
01555  Convert a uid into a user name.
01556 ********************************************************************/
01557 
01558 const char *uidtoname(uid_t uid)
01559 {
01560         static fstring name;
01561         struct passwd *pass;
01562 
01563         pass = getpwuid_alloc(NULL, uid);
01564         if (pass) {
01565                 fstrcpy(name, pass->pw_name);
01566                 TALLOC_FREE(pass);
01567         } else {
01568                 slprintf(name, sizeof(name) - 1, "%ld",(long int)uid);
01569         }
01570         return name;
01571 }
01572 
01573 
01574 /*******************************************************************
01575  Convert a gid into a group name.
01576 ********************************************************************/
01577 
01578 char *gidtoname(gid_t gid)
01579 {
01580         static fstring name;
01581         struct group *grp;
01582 
01583         grp = getgrgid(gid);
01584         if (grp)
01585                 return(grp->gr_name);
01586         slprintf(name,sizeof(name) - 1, "%d",(int)gid);
01587         return(name);
01588 }
01589 
01590 /*******************************************************************
01591  Convert a user name into a uid. 
01592 ********************************************************************/
01593 
01594 uid_t nametouid(const char *name)
01595 {
01596         struct passwd *pass;
01597         char *p;
01598         uid_t u;
01599 
01600         pass = getpwnam_alloc(NULL, name);
01601         if (pass) {
01602                 u = pass->pw_uid;
01603                 TALLOC_FREE(pass);
01604                 return u;
01605         }
01606 
01607         u = (uid_t)strtol(name, &p, 0);
01608         if ((p != name) && (*p == '\0'))
01609                 return u;
01610 
01611         return (uid_t)-1;
01612 }
01613 
01614 /*******************************************************************
01615  Convert a name to a gid_t if possible. Return -1 if not a group. 
01616 ********************************************************************/
01617 
01618 gid_t nametogid(const char *name)
01619 {
01620         struct group *grp;
01621         char *p;
01622         gid_t g;
01623 
01624         g = (gid_t)strtol(name, &p, 0);
01625         if ((p != name) && (*p == '\0'))
01626                 return g;
01627 
01628         grp = sys_getgrnam(name);
01629         if (grp)
01630                 return(grp->gr_gid);
01631         return (gid_t)-1;
01632 }
01633 
01634 /*******************************************************************
01635  Something really nasty happened - panic !
01636 ********************************************************************/
01637 
01638 void smb_panic(const char *const why)
01639 {
01640         char *cmd;
01641         int result;
01642 
01643 #ifdef DEVELOPER
01644         {
01645 
01646                 if (global_clobber_region_function) {
01647                         DEBUG(0,("smb_panic: clobber_region() last called from [%s(%u)]\n",
01648                                          global_clobber_region_function,
01649                                          global_clobber_region_line));
01650                 } 
01651         }
01652 #endif
01653 
01654         DEBUG(0,("PANIC (pid %llu): %s\n",
01655                     (unsigned long long)sys_getpid(), why));
01656         log_stack_trace();
01657 
01658         cmd = lp_panic_action();
01659         if (cmd && *cmd) {
01660                 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
01661                 result = system(cmd);
01662 
01663                 if (result == -1)
01664                         DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
01665                                           strerror(errno)));
01666                 else
01667                         DEBUG(0, ("smb_panic(): action returned status %d\n",
01668                                           WEXITSTATUS(result)));
01669         }
01670 
01671         dump_core();
01672 }
01673 
01674 /*******************************************************************
01675  Print a backtrace of the stack to the debug log. This function
01676  DELIBERATELY LEAKS MEMORY. The expectation is that you should
01677  exit shortly after calling it.
01678 ********************************************************************/
01679 
01680 #ifdef HAVE_LIBUNWIND_H
01681 #include <libunwind.h>
01682 #endif
01683 
01684 #ifdef HAVE_EXECINFO_H
01685 #include <execinfo.h>
01686 #endif
01687 
01688 #ifdef HAVE_LIBEXC_H
01689 #include <libexc.h>
01690 #endif
01691 
01692 void log_stack_trace(void)
01693 {
01694 #ifdef HAVE_LIBUNWIND
01695         /* Try to use libunwind before any other technique since on ia64
01696          * libunwind correctly walks the stack in more circumstances than
01697          * backtrace.
01698          */ 
01699         unw_cursor_t cursor;
01700         unw_context_t uc;
01701         unsigned i = 0;
01702 
01703         char procname[256];
01704         unw_word_t ip, sp, off;
01705 
01706         procname[sizeof(procname) - 1] = '\0';
01707 
01708         if (unw_getcontext(&uc) != 0) {
01709                 goto libunwind_failed;
01710         }
01711 
01712         if (unw_init_local(&cursor, &uc) != 0) {
01713                 goto libunwind_failed;
01714         }
01715 
01716         DEBUG(0, ("BACKTRACE:\n"));
01717 
01718         do {
01719             ip = sp = 0;
01720             unw_get_reg(&cursor, UNW_REG_IP, &ip);
01721             unw_get_reg(&cursor, UNW_REG_SP, &sp);
01722 
01723             switch (unw_get_proc_name(&cursor,
01724                         procname, sizeof(procname) - 1, &off) ) {
01725             case 0:
01726                     /* Name found. */
01727             case -UNW_ENOMEM:
01728                     /* Name truncated. */
01729                     DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
01730                             i, procname, (long long)off,
01731                             (long long)ip, (long long) sp));
01732                     break;
01733             default:
01734             /* case -UNW_ENOINFO: */
01735             /* case -UNW_EUNSPEC: */
01736                     /* No symbol name found. */
01737                     DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
01738                             i, "<unknown symbol>",
01739                             (long long)ip, (long long) sp));
01740             }
01741             ++i;
01742         } while (unw_step(&cursor) > 0);
01743 
01744         return;
01745 
01746 libunwind_failed:
01747         DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
01748 
01749 #elif HAVE_BACKTRACE_SYMBOLS
01750         void *backtrace_stack[BACKTRACE_STACK_SIZE];
01751         size_t backtrace_size;
01752         char **backtrace_strings;
01753 
01754         /* get the backtrace (stack frames) */
01755         backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
01756         backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
01757 
01758         DEBUG(0, ("BACKTRACE: %lu stack frames:\n", 
01759                   (unsigned long)backtrace_size));
01760         
01761         if (backtrace_strings) {
01762                 int i;
01763 
01764                 for (i = 0; i < backtrace_size; i++)
01765                         DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
01766 
01767                 /* Leak the backtrace_strings, rather than risk what free() might do */
01768         }
01769 
01770 #elif HAVE_LIBEXC
01771 
01772         /* The IRIX libexc library provides an API for unwinding the stack. See
01773          * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
01774          * since we are about to abort anyway, it hardly matters.
01775          */
01776 
01777 #define NAMESIZE 32 /* Arbitrary */
01778 
01779         __uint64_t      addrs[BACKTRACE_STACK_SIZE];
01780         char *          names[BACKTRACE_STACK_SIZE];
01781         char            namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
01782 
01783         int             i;
01784         int             levels;
01785 
01786         ZERO_ARRAY(addrs);
01787         ZERO_ARRAY(names);
01788         ZERO_ARRAY(namebuf);
01789 
01790         /* We need to be root so we can open our /proc entry to walk
01791          * our stack. It also helps when we want to dump core.
01792          */
01793         become_root();
01794 
01795         for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
01796                 names[i] = namebuf + (i * NAMESIZE);
01797         }
01798 
01799         levels = trace_back_stack(0, addrs, names,
01800                         BACKTRACE_STACK_SIZE, NAMESIZE - 1);
01801 
01802         DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
01803         for (i = 0; i < levels; i++) {
01804                 DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
01805         }
01806 #undef NAMESIZE
01807 
01808 #else
01809         DEBUG(0, ("unable to produce a stack trace on this platform\n"));
01810 #endif
01811 }
01812 
01813 /*******************************************************************
01814   A readdir wrapper which just returns the file name.
01815  ********************************************************************/
01816 
01817 const char *readdirname(SMB_STRUCT_DIR *p)
01818 {
01819         SMB_STRUCT_DIRENT *ptr;
01820         char *dname;
01821 
01822         if (!p)
01823                 return(NULL);
01824   
01825         ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
01826         if (!ptr)
01827                 return(NULL);
01828 
01829         dname = ptr->d_name;
01830 
01831 #ifdef NEXT2
01832         if (telldir(p) < 0)
01833                 return(NULL);
01834 #endif
01835 
01836 #ifdef HAVE_BROKEN_READDIR_NAME
01837         /* using /usr/ucb/cc is BAD */
01838         dname = dname - 2;
01839 #endif
01840 
01841         {
01842                 static pstring buf;
01843                 int len = NAMLEN(ptr);
01844                 memcpy(buf, dname, len);
01845                 buf[len] = 0;
01846                 dname = buf;
01847         }
01848 
01849         return(dname);
01850 }
01851 
01852 /*******************************************************************
01853  Utility function used to decide if the last component 
01854  of a path matches a (possibly wildcarded) entry in a namelist.
01855 ********************************************************************/
01856 
01857 BOOL is_in_path(const char *name, name_compare_entry *namelist, BOOL case_sensitive)
01858 {
01859         const char *last_component;
01860 
01861         /* if we have no list it's obviously not in the path */
01862         if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
01863                 return False;
01864         }
01865 
01866         DEBUG(8, ("is_in_path: %s\n", name));
01867 
01868         /* Get the last component of the unix name. */
01869         last_component = strrchr_m(name, '/');
01870         if (!last_component) {
01871                 last_component = name;
01872         } else {
01873                 last_component++; /* Go past '/' */
01874         }
01875 
01876         for(; namelist->name != NULL; namelist++) {
01877                 if(namelist->is_wild) {
01878                         if (mask_match(last_component, namelist->name, case_sensitive)) {
01879                                 DEBUG(8,("is_in_path: mask match succeeded\n"));
01880                                 return True;
01881                         }
01882                 } else {
01883                         if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
01884                                                 (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0))) {
01885                                 DEBUG(8,("is_in_path: match succeeded\n"));
01886                                 return True;
01887                         }
01888                 }
01889         }
01890         DEBUG(8,("is_in_path: match not found\n"));
01891         return False;
01892 }
01893 
01894 /*******************************************************************
01895  Strip a '/' separated list into an array of 
01896  name_compare_enties structures suitable for 
01897  passing to is_in_path(). We do this for
01898  speed so we can pre-parse all the names in the list 
01899  and don't do it for each call to is_in_path().
01900  namelist is modified here and is assumed to be 
01901  a copy owned by the caller.
01902  We also check if the entry contains a wildcard to
01903  remove a potentially expensive call to mask_match
01904  if possible.
01905 ********************************************************************/
01906  
01907 void set_namearray(name_compare_entry **ppname_array, char *namelist)
01908 {
01909         char *name_end;
01910         char *nameptr = namelist;
01911         int num_entries = 0;
01912         int i;
01913 
01914         (*ppname_array) = NULL;
01915 
01916         if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0'))) 
01917                 return;
01918 
01919         /* We need to make two passes over the string. The
01920                 first to count the number of elements, the second
01921                 to split it.
01922         */
01923 
01924         while(*nameptr) {
01925                 if ( *nameptr == '/' ) {
01926                         /* cope with multiple (useless) /s) */
01927                         nameptr++;
01928                         continue;
01929                 }
01930                 /* find the next / */
01931                 name_end = strchr_m(nameptr, '/');
01932 
01933                 /* oops - the last check for a / didn't find one. */
01934                 if (name_end == NULL)
01935                         break;
01936 
01937                 /* next segment please */
01938                 nameptr = name_end + 1;
01939                 num_entries++;
01940         }
01941 
01942         if(num_entries == 0)
01943                 return;
01944 
01945         if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
01946                 DEBUG(0,("set_namearray: malloc fail\n"));
01947                 return;
01948         }
01949 
01950         /* Now copy out the names */
01951         nameptr = namelist;
01952         i = 0;
01953         while(*nameptr) {
01954                 if ( *nameptr == '/' ) {
01955                         /* cope with multiple (useless) /s) */
01956                         nameptr++;
01957                         continue;
01958                 }
01959                 /* find the next / */
01960                 if ((name_end = strchr_m(nameptr, '/')) != NULL)
01961                         *name_end = 0;
01962 
01963                 /* oops - the last check for a / didn't find one. */
01964                 if(name_end == NULL) 
01965                         break;
01966 
01967                 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
01968                 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
01969                         DEBUG(0,("set_namearray: malloc fail (1)\n"));
01970                         return;
01971                 }
01972 
01973                 /* next segment please */
01974                 nameptr = name_end + 1;
01975                 i++;
01976         }
01977   
01978         (*ppname_array)[i].name = NULL;
01979 
01980         return;
01981 }
01982 
01983 /****************************************************************************
01984  Routine to free a namearray.
01985 ****************************************************************************/
01986 
01987 void free_namearray(name_compare_entry *name_array)
01988 {
01989         int i;
01990 
01991         if(name_array == NULL)
01992                 return;
01993 
01994         for(i=0; name_array[i].name!=NULL; i++)
01995                 SAFE_FREE(name_array[i].name);
01996         SAFE_FREE(name_array);
01997 }
01998 
01999 #undef DBGC_CLASS
02000 #define DBGC_CLASS DBGC_LOCKING
02001 
02002 /****************************************************************************
02003  Simple routine to do POSIX file locking. Cruft in NFS and 64->32 bit mapping
02004  is dealt with in posix.c
02005  Returns True if the lock was granted, False otherwise.
02006 ****************************************************************************/
02007 
02008 BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
02009 {
02010         SMB_STRUCT_FLOCK lock;
02011         int ret;
02012 
02013         DEBUG(8,("fcntl_lock fd=%d op=%d offset=%.0f count=%.0f type=%d\n",
02014                 fd,op,(double)offset,(double)count,type));
02015 
02016         lock.l_type = type;
02017         lock.l_whence = SEEK_SET;
02018         lock.l_start = offset;
02019         lock.l_len = count;
02020         lock.l_pid = 0;
02021 
02022         ret = sys_fcntl_ptr(fd,op,&lock);
02023 
02024         if (ret == -1) {
02025                 int sav = errno;
02026                 DEBUG(3,("fcntl_lock: lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
02027                         (double)offset,(double)count,op,type,strerror(errno)));
02028                 errno = sav;
02029                 return False;
02030         }
02031 
02032         /* everything went OK */
02033         DEBUG(8,("fcntl_lock: Lock call successful\n"));
02034 
02035         return True;
02036 }
02037 
02038 /****************************************************************************
02039  Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
02040  is dealt with in posix.c
02041  Returns True if we have information regarding this lock region (and returns
02042  F_UNLCK in *ptype if the region is unlocked). False if the call failed.
02043 ****************************************************************************/
02044 
02045 BOOL fcntl_getlock(int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
02046 {
02047         SMB_STRUCT_FLOCK lock;
02048         int ret;
02049 
02050         DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
02051                     fd,(double)*poffset,(double)*pcount,*ptype));
02052 
02053         lock.l_type = *ptype;
02054         lock.l_whence = SEEK_SET;
02055         lock.l_start = *poffset;
02056         lock.l_len = *pcount;
02057         lock.l_pid = 0;
02058 
02059         ret = sys_fcntl_ptr(fd,SMB_F_GETLK,&lock);
02060 
02061         if (ret == -1) {
02062                 int sav = errno;
02063                 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
02064                         (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
02065                 errno = sav;
02066                 return False;
02067         }
02068 
02069         *ptype = lock.l_type;
02070         *poffset = lock.l_start;
02071         *pcount = lock.l_len;
02072         *ppid = lock.l_pid;
02073         
02074         DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
02075                         fd, (int)lock.l_type, (unsigned int)lock.l_pid));
02076         return True;
02077 }
02078 
02079 #undef DBGC_CLASS
02080 #define DBGC_CLASS DBGC_ALL
02081 
02082 /*******************************************************************
02083  Is the name specified one of my netbios names.
02084  Returns true if it is equal, false otherwise.
02085 ********************************************************************/
02086 
02087 BOOL is_myname(const char *s)
02088 {
02089         int n;
02090         BOOL ret = False;
02091 
02092         for (n=0; my_netbios_names(n); n++) {
02093                 if (strequal(my_netbios_names(n), s)) {
02094                         ret=True;
02095                         break;
02096                 }
02097         }
02098         DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
02099         return(ret);
02100 }
02101 
02102 BOOL is_myname_or_ipaddr(const char *s)
02103 {
02104         fstring name, dnsname;
02105         char *servername;
02106 
02107         if ( !s )
02108                 return False;
02109 
02110         /* santize the string from '\\name' */
02111 
02112         fstrcpy( name, s );
02113 
02114         servername = strrchr_m( name, '\\' );
02115         if ( !servername )
02116                 servername = name;
02117         else
02118                 servername++;
02119 
02120         /* optimize for the common case */
02121 
02122         if (strequal(servername, global_myname())) 
02123                 return True;
02124 
02125         /* check for an alias */
02126 
02127         if (is_myname(servername))
02128                 return True;
02129 
02130         /* check for loopback */
02131 
02132         if (strequal(servername, "127.0.0.1")) 
02133                 return True;
02134 
02135         if (strequal(servername, "localhost")) 
02136                 return True;
02137 
02138         /* maybe it's my dns name */
02139 
02140         if ( get_mydnsfullname( dnsname ) )
02141                 if ( strequal( servername, dnsname ) )
02142                         return True;
02143                 
02144         /* handle possible CNAME records */
02145 
02146         if ( !is_ipaddress( servername ) ) {
02147                 /* use DNS to resolve the name, but only the first address */
02148                 struct hostent *hp;
02149 
02150                 if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
02151                         struct in_addr return_ip;
02152                         putip( (char*)&return_ip, (char*)hp->h_addr );
02153                         fstrcpy( name, inet_ntoa( return_ip ) );
02154                         servername = name;
02155                 }       
02156         }
02157                 
02158         /* maybe its an IP address? */
02159         if (is_ipaddress(servername)) {
02160                 struct iface_struct nics[MAX_INTERFACES];
02161                 int i, n;
02162                 uint32 ip;
02163                 
02164                 ip = interpret_addr(servername);
02165                 if ((ip==0) || (ip==0xffffffff))
02166                         return False;
02167                         
02168                 n = get_interfaces(nics, MAX_INTERFACES);
02169                 for (i=0; i<n; i++) {
02170                         if (ip == nics[i].ip.s_addr)
02171                                 return True;
02172                 }
02173         }       
02174 
02175         /* no match */
02176         return False;
02177 }
02178 
02179 /*******************************************************************
02180  Is the name specified our workgroup/domain.
02181  Returns true if it is equal, false otherwise.
02182 ********************************************************************/
02183 
02184 BOOL is_myworkgroup(const char *s)
02185 {
02186         BOOL ret = False;
02187 
02188         if (strequal(s, lp_workgroup())) {
02189                 ret=True;
02190         }
02191 
02192         DEBUG(8, ("is_myworkgroup(\"%s\") returns %d\n", s, ret));
02193         return(ret);
02194 }
02195 
02196 /*******************************************************************
02197  we distinguish between 2K and XP by the "Native Lan Manager" string
02198    WinXP => "Windows 2002 5.1"
02199    WinXP 64bit => "Windows XP 5.2"
02200    Win2k => "Windows 2000 5.0"
02201    NT4   => "Windows NT 4.0" 
02202    Win9x => "Windows 4.0"
02203  Windows 2003 doesn't set the native lan manager string but 
02204  they do set the domain to "Windows 2003 5.2" (probably a bug).
02205 ********************************************************************/
02206 
02207 void ra_lanman_string( const char *native_lanman )
02208 {       
02209         if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
02210                 set_remote_arch( RA_WINXP );
02211         else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
02212                 set_remote_arch( RA_WINXP );
02213         else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
02214                 set_remote_arch( RA_WIN2K3 );
02215 }
02216 
02217 /*******************************************************************
02218  Set the horrid remote_arch string based on an enum.
02219 ********************************************************************/
02220 
02221 void set_remote_arch(enum remote_arch_types type)
02222 {
02223         ra_type = type;
02224         switch( type ) {
02225         case RA_WFWG:
02226                 fstrcpy(remote_arch, "WfWg");
02227                 break;
02228         case RA_OS2:
02229                 fstrcpy(remote_arch, "OS2");
02230                 break;
02231         case RA_WIN95:
02232                 fstrcpy(remote_arch, "Win95");
02233                 break;
02234         case RA_WINNT:
02235                 fstrcpy(remote_arch, "WinNT");
02236                 break;
02237         case RA_WIN2K:
02238                 fstrcpy(remote_arch, "Win2K");
02239                 break;
02240         case RA_WINXP:
02241                 fstrcpy(remote_arch, "WinXP");
02242                 break;
02243         case RA_WIN2K3:
02244                 fstrcpy(remote_arch, "Win2K3");
02245                 break;
02246         case RA_VISTA:
02247                 fstrcpy(remote_arch, "Vista");
02248                 break;
02249         case RA_SAMBA:
02250                 fstrcpy(remote_arch,"Samba");
02251                 break;
02252         case RA_CIFSFS:
02253                 fstrcpy(remote_arch,"CIFSFS");
02254                 break;
02255         default:
02256                 ra_type = RA_UNKNOWN;
02257                 fstrcpy(remote_arch, "UNKNOWN");
02258                 break;
02259         }
02260 
02261         DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n", remote_arch));
02262 }
02263 
02264 /*******************************************************************
02265  Get the remote_arch type.
02266 ********************************************************************/
02267 
02268 enum remote_arch_types get_remote_arch(void)
02269 {
02270         return ra_type;
02271 }
02272 
02273 void print_asc(int level, const unsigned char *buf,int len)
02274 {
02275         int i;
02276         for (i=0;i<len;i++)
02277                 DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
02278 }
02279 
02280 void dump_data(int level, const char *buf1,int len)
02281 {
02282         const unsigned char *buf = (const unsigned char *)buf1;
02283         int i=0;
02284         if (len<=0) return;
02285 
02286         if (!DEBUGLVL(level)) return;
02287         
02288         DEBUGADD(level,("[%03X] ",i));
02289         for (i=0;i<len;) {
02290                 DEBUGADD(level,("%02X ",(int)buf[i]));
02291                 i++;
02292                 if (i%8 == 0) DEBUGADD(level,(" "));
02293                 if (i%16 == 0) {      
02294                         print_asc(level,&buf[i-16],8); DEBUGADD(level,(" "));
02295                         print_asc(level,&buf[i-8],8); DEBUGADD(level,("\n"));
02296                         if (i<len) DEBUGADD(level,("[%03X] ",i));
02297                 }
02298         }
02299         if (i%16) {
02300                 int n;
02301                 n = 16 - (i%16);
02302                 DEBUGADD(level,(" "));
02303                 if (n>8) DEBUGADD(level,(" "));
02304                 while (n--) DEBUGADD(level,("   "));
02305                 n = MIN(8,i%16);
02306                 print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,( " " ));
02307                 n = (i%16) - n;
02308                 if (n>0) print_asc(level,&buf[i-n],n); 
02309                 DEBUGADD(level,("\n"));    
02310         }       
02311 }
02312 
02313 void dump_data_pw(const char *msg, const uchar * data, size_t len)
02314 {
02315 #ifdef DEBUG_PASSWORD
02316         DEBUG(11, ("%s", msg));
02317         if (data != NULL && len > 0)
02318         {
02319                 dump_data(11, (const char *)data, len);
02320         }
02321 #endif
02322 }
02323 
02324 char *tab_depth(int depth)
02325 {
02326         static pstring spaces;
02327         memset(spaces, ' ', depth * 4);
02328         spaces[depth * 4] = 0;
02329         return spaces;
02330 }
02331 
02332 /*****************************************************************************
02333  Provide a checksum on a string
02334 
02335  Input:  s - the null-terminated character string for which the checksum
02336              will be calculated.
02337 
02338   Output: The checksum value calculated for s.
02339 *****************************************************************************/
02340 
02341 int str_checksum(const char *s)
02342 {
02343         int res = 0;
02344         int c;
02345         int i=0;
02346         
02347         while(*s) {
02348                 c = *s;
02349                 res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
02350                 s++;
02351                 i++;
02352         }
02353         return(res);
02354 }
02355 
02356 /*****************************************************************
02357  Zero a memory area then free it. Used to catch bugs faster.
02358 *****************************************************************/  
02359 
02360 void zero_free(void *p, size_t size)
02361 {
02362         memset(p, 0, size);
02363         SAFE_FREE(p);
02364 }
02365 
02366 /*****************************************************************
02367  Set our open file limit to a requested max and return the limit.
02368 *****************************************************************/  
02369 
02370 int set_maxfiles(int requested_max)
02371 {
02372 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
02373         struct rlimit rlp;
02374         int saved_current_limit;
02375 
02376         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
02377                 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
02378                         strerror(errno) ));
02379                 /* just guess... */
02380                 return requested_max;
02381         }
02382 
02383         /* 
02384          * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
02385          * account for the extra fd we need 
02386          * as well as the log files and standard
02387          * handles etc. Save the limit we want to set in case
02388          * we are running on an OS that doesn't support this limit (AIX)
02389          * which always returns RLIM_INFINITY for rlp.rlim_max.
02390          */
02391 
02392         /* Try raising the hard (max) limit to the requested amount. */
02393 
02394 #if defined(RLIM_INFINITY)
02395         if (rlp.rlim_max != RLIM_INFINITY) {
02396                 int orig_max = rlp.rlim_max;
02397 
02398                 if ( rlp.rlim_max < requested_max )
02399                         rlp.rlim_max = requested_max;
02400 
02401                 /* This failing is not an error - many systems (Linux) don't
02402                         support our default request of 10,000 open files. JRA. */
02403 
02404                 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
02405                         DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n", 
02406                                 (int)rlp.rlim_max, strerror(errno) ));
02407 
02408                         /* Set failed - restore original value from get. */
02409                         rlp.rlim_max = orig_max;
02410                 }
02411         }
02412 #endif
02413 
02414         /* Now try setting the soft (current) limit. */
02415 
02416         saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
02417 
02418         if(setrlimit(RLIMIT_NOFILE, &rlp)) {
02419                 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n", 
02420                         (int)rlp.rlim_cur, strerror(errno) ));
02421                 /* just guess... */
02422                 return saved_current_limit;
02423         }
02424 
02425         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
02426                 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
02427                         strerror(errno) ));
02428                 /* just guess... */
02429                 return saved_current_limit;
02430     }
02431 
02432 #if defined(RLIM_INFINITY)
02433         if(rlp.rlim_cur == RLIM_INFINITY)
02434                 return saved_current_limit;
02435 #endif
02436 
02437         if((int)rlp.rlim_cur > saved_current_limit)
02438                 return saved_current_limit;
02439 
02440         return rlp.rlim_cur;
02441 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
02442         /*
02443          * No way to know - just guess...
02444          */
02445         return requested_max;
02446 #endif
02447 }
02448 
02449 /*****************************************************************
02450  Possibly replace mkstemp if it is broken.
02451 *****************************************************************/  
02452 
02453 int smb_mkstemp(char *name_template)
02454 {
02455 #if HAVE_SECURE_MKSTEMP
02456         return mkstemp(name_template);
02457 #else
02458         /* have a reasonable go at emulating it. Hope that
02459            the system mktemp() isn't completly hopeless */
02460         char *p = mktemp(name_template);
02461         if (!p)
02462                 return -1;
02463         return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
02464 #endif
02465 }
02466 
02467 /*****************************************************************
02468  malloc that aborts with smb_panic on fail or zero size.
02469  *****************************************************************/  
02470 
02471 void *smb_xmalloc_array(size_t size, unsigned int count)
02472 {
02473         void *p;
02474         if (size == 0)
02475                 smb_panic("smb_xmalloc_array: called with zero size.\n");
02476         if (count >= MAX_ALLOC_SIZE/size) {
02477                 smb_panic("smb_xmalloc: alloc size too large.\n");
02478         }
02479         if ((p = SMB_MALLOC(size*count)) == NULL) {
02480                 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
02481                         (unsigned long)size, (unsigned long)count));
02482                 smb_panic("smb_xmalloc_array: malloc fail.\n");
02483         }
02484         return p;
02485 }
02486 
02487 /**
02488  Memdup with smb_panic on fail.
02489 **/
02490 
02491 void *smb_xmemdup(const void *p, size_t size)
02492 {
02493         void *p2;
02494         p2 = SMB_XMALLOC_ARRAY(unsigned char,size);
02495         memcpy(p2, p, size);
02496         return p2;
02497 }
02498 
02499 /**
02500  strdup that aborts on malloc fail.
02501 **/
02502 
02503 char *smb_xstrdup(const char *s)
02504 {
02505 #if defined(PARANOID_MALLOC_CHECKER)
02506 #ifdef strdup
02507 #undef strdup
02508 #endif
02509 #endif
02510 
02511 #ifndef HAVE_STRDUP
02512 #define strdup rep_strdup
02513 #endif
02514 
02515         char *s1 = strdup(s);
02516 #if defined(PARANOID_MALLOC_CHECKER)
02517 #ifdef strdup
02518 #undef strdup
02519 #endif
02520 #define strdup(s) __ERROR_DONT_USE_STRDUP_DIRECTLY
02521 #endif
02522         if (!s1)
02523                 smb_panic("smb_xstrdup: malloc fail\n");
02524         return s1;
02525 
02526 }
02527 
02528 /**
02529  strndup that aborts on malloc fail.
02530 **/
02531 
02532 char *smb_xstrndup(const char *s, size_t n)
02533 {
02534 #if defined(PARANOID_MALLOC_CHECKER)
02535 #ifdef strndup
02536 #undef strndup
02537 #endif
02538 #endif
02539 
02540 #if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP))
02541 #undef HAVE_STRNDUP
02542 #define strndup rep_strndup
02543 #endif
02544 
02545         char *s1 = strndup(s, n);
02546 #if defined(PARANOID_MALLOC_CHECKER)
02547 #ifdef strndup
02548 #undef strndup
02549 #endif
02550 #define strndup(s,n) __ERROR_DONT_USE_STRNDUP_DIRECTLY
02551 #endif
02552         if (!s1)
02553                 smb_panic("smb_xstrndup: malloc fail\n");
02554         return s1;
02555 }
02556 
02557 /*
02558   vasprintf that aborts on malloc fail
02559 */
02560 
02561  int smb_xvasprintf(char **ptr, const char *format, va_list ap)
02562 {
02563         int n;
02564         va_list ap2;
02565 
02566         VA_COPY(ap2, ap);
02567 
02568         n = vasprintf(ptr, format, ap2);
02569         if (n == -1 || ! *ptr)
02570                 smb_panic("smb_xvasprintf: out of memory");
02571         return n;
02572 }
02573 
02574 /*****************************************************************
02575  Like strdup but for memory.
02576 *****************************************************************/  
02577 
02578 void *memdup(const void *p, size_t size)
02579 {
02580         void *p2;
02581         if (size == 0)
02582                 return NULL;
02583         p2 = SMB_MALLOC(size);
02584         if (!p2)
02585                 return NULL;
02586         memcpy(p2, p, size);
02587         return p2;
02588 }
02589 
02590 /*****************************************************************
02591  Get local hostname and cache result.
02592 *****************************************************************/  
02593 
02594 char *myhostname(void)
02595 {
02596         static pstring ret;
02597         if (ret[0] == 0)
02598                 get_myname(ret);
02599         return ret;
02600 }
02601 
02602 /*****************************************************************
02603  A useful function for returning a path in the Samba lock directory.
02604 *****************************************************************/  
02605 
02606 char *lock_path(const char *name)
02607 {
02608         static pstring fname;
02609 
02610         pstrcpy(fname,lp_lockdir());
02611         trim_char(fname,'\0','/');
02612         
02613         if (!directory_exist(fname,NULL))
02614                 mkdir(fname,0755);
02615         
02616         pstrcat(fname,"/");
02617         pstrcat(fname,name);
02618 
02619         return fname;
02620 }
02621 
02622 /*****************************************************************
02623  A useful function for returning a path in the Samba pid directory.
02624 *****************************************************************/
02625 
02626 char *pid_path(const char *name)
02627 {
02628         static pstring fname;
02629 
02630         pstrcpy(fname,lp_piddir());
02631         trim_char(fname,'\0','/');
02632 
02633         if (!directory_exist(fname,NULL))
02634                 mkdir(fname,0755);
02635 
02636         pstrcat(fname,"/");
02637         pstrcat(fname,name);
02638 
02639         return fname;
02640 }
02641 
02642 /**
02643  * @brief Returns an absolute path to a file in the Samba lib directory.
02644  *
02645  * @param name File to find, relative to LIBDIR.
02646  *
02647  * @retval Pointer to a static #pstring containing the full path.
02648  **/
02649 
02650 char *lib_path(const char *name)
02651 {
02652         static pstring fname;
02653         fstr_sprintf(fname, "%s/%s", dyn_LIBDIR, name);
02654         return fname;
02655 }
02656 
02657 /**
02658  * @brief Returns the platform specific shared library extension.
02659  *
02660  * @retval Pointer to a static #fstring containing the extension.
02661  **/
02662 
02663 const char *shlib_ext(void)
02664 {
02665   return dyn_SHLIBEXT;
02666 }
02667 
02668 /*******************************************************************
02669  Given a filename - get its directory name
02670  NB: Returned in static storage.  Caveats:
02671  o  Not safe in thread environment.
02672  o  Caller must not free.
02673  o  If caller wishes to preserve, they should copy.
02674 ********************************************************************/
02675 
02676 char *parent_dirname(const char *path)
02677 {
02678         static pstring dirpath;
02679         char *p;
02680 
02681         if (!path)
02682                 return(NULL);
02683 
02684         pstrcpy(dirpath, path);
02685         p = strrchr_m(dirpath, '/');  /* Find final '/', if any */
02686         if (!p) {
02687                 pstrcpy(dirpath, ".");    /* No final "/", so dir is "." */
02688         } else {
02689                 if (p == dirpath)
02690                         ++p;    /* For root "/", leave "/" in place */
02691                 *p = '\0';
02692         }
02693         return dirpath;
02694 }
02695 
02696 BOOL parent_dirname_talloc(TALLOC_CTX *mem_ctx, const char *dir,
02697                            char **parent, const char **name)
02698 {
02699         char *p;
02700         ptrdiff_t len;
02701  
02702         p = strrchr_m(dir, '/'); /* Find final '/', if any */
02703 
02704         if (p == NULL) {
02705                 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
02706                         return False;
02707                 }
02708                 if (name) {
02709                         *name = "";
02710                 }
02711                 return True;
02712         }
02713 
02714         len = p-dir;
02715 
02716         if (!(*parent = TALLOC_ARRAY(mem_ctx, char, len+1))) {
02717                 return False;
02718         }
02719         memcpy(*parent, dir, len);
02720         (*parent)[len] = '\0';
02721 
02722         if (name) {
02723                 *name = p+1;
02724         }
02725         return True;
02726 }
02727 
02728 /*******************************************************************
02729  Determine if a pattern contains any Microsoft wildcard characters.
02730 *******************************************************************/
02731 
02732 BOOL ms_has_wild(const char *s)
02733 {
02734         char c;
02735 
02736         if (lp_posix_pathnames()) {
02737                 /* With posix pathnames no characters are wild. */
02738                 return False;
02739         }
02740 
02741         while ((c = *s++)) {
02742                 switch (c) {
02743                 case '*':
02744                 case '?':
02745                 case '<':
02746                 case '>':
02747                 case '"':
02748                         return True;
02749                 }
02750         }
02751         return False;
02752 }
02753 
02754 BOOL ms_has_wild_w(const smb_ucs2_t *s)
02755 {
02756         smb_ucs2_t c;
02757         if (!s) return False;
02758         while ((c = *s++)) {
02759                 switch (c) {
02760                 case UCS2_CHAR('*'):
02761                 case UCS2_CHAR('?'):
02762                 case UCS2_CHAR('<'):
02763                 case UCS2_CHAR('>'):
02764                 case UCS2_CHAR('"'):
02765                         return True;
02766                 }
02767         }
02768         return False;
02769 }
02770 
02771 /*******************************************************************
02772  A wrapper that handles case sensitivity and the special handling
02773  of the ".." name.
02774 *******************************************************************/
02775 
02776 BOOL mask_match(const char *string, const char *pattern, BOOL is_case_sensitive)
02777 {
02778         if (strcmp(string,"..") == 0)
02779                 string = ".";
02780         if (strcmp(pattern,".") == 0)
02781                 return False;
02782         
02783         return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
02784 }
02785 
02786 /*******************************************************************
02787  A wrapper that handles case sensitivity and the special handling
02788  of the ".." name. Varient that is only called by old search code which requires
02789  pattern translation.
02790 *******************************************************************/
02791 
02792 BOOL mask_match_search(const char *string, const char *pattern, BOOL is_case_sensitive)
02793 {
02794         if (strcmp(string,"..") == 0)
02795                 string = ".";
02796         if (strcmp(pattern,".") == 0)
02797                 return False;
02798         
02799         return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
02800 }
02801 
02802 /*******************************************************************
02803  A wrapper that handles a list of patters and calls mask_match()
02804  on each.  Returns True if any of the patterns match.
02805 *******************************************************************/
02806 
02807 BOOL mask_match_list(const char *string, char **list, int listLen, BOOL is_case_sensitive)
02808 {
02809        while (listLen-- > 0) {
02810                if (mask_match(string, *list++, is_case_sensitive))
02811                        return True;
02812        }
02813        return False;
02814 }
02815 
02816 /*********************************************************
02817  Recursive routine that is called by unix_wild_match.
02818 *********************************************************/
02819 
02820 static BOOL unix_do_match(const char *regexp, const char *str)
02821 {
02822         const char *p;
02823 
02824         for( p = regexp; *p && *str; ) {
02825 
02826                 switch(*p) {
02827                         case '?':
02828                                 str++;
02829                                 p++;
02830                                 break;
02831 
02832                         case '*':
02833 
02834                                 /*
02835                                  * Look for a character matching 
02836                                  * the one after the '*'.
02837                                  */
02838                                 p++;
02839                                 if(!*p)
02840                                         return True; /* Automatic match */
02841                                 while(*str) {
02842 
02843                                         while(*str && (*p != *str))
02844                                                 str++;
02845 
02846                                         /*
02847                                          * Patch from weidel@multichart.de. In the case of the regexp
02848                                          * '*XX*' we want to ensure there are at least 2 'X' characters
02849                                          * in the string after the '*' for a match to be made.
02850                                          */
02851 
02852                                         {
02853                                                 int matchcount=0;
02854 
02855                                                 /*
02856                                                  * Eat all the characters that match, but count how many there were.
02857                                                  */
02858 
02859                                                 while(*str && (*p == *str)) {
02860                                                         str++;
02861                                                         matchcount++;
02862                                                 }
02863 
02864                                                 /*
02865                                                  * Now check that if the regexp had n identical characters that
02866                                                  * matchcount had at least that many matches.
02867                                                  */
02868 
02869                                                 while ( *(p+1) && (*(p+1) == *p)) {
02870                                                         p++;
02871                                                         matchcount--;
02872                                                 }
02873 
02874                                                 if ( matchcount <= 0 )
02875                                                         return False;
02876                                         }
02877 
02878                                         str--; /* We've eaten the match char after the '*' */
02879 
02880                                         if(unix_do_match(p, str))
02881                                                 return True;
02882 
02883                                         if(!*str)
02884                                                 return False;
02885                                         else
02886                                                 str++;
02887                                 }
02888                                 return False;
02889 
02890                         default:
02891                                 if(*str != *p)
02892                                         return False;
02893                                 str++;
02894                                 p++;
02895                                 break;
02896                 }
02897         }
02898 
02899         if(!*p && !*str)
02900                 return True;
02901 
02902         if (!*p && str[0] == '.' && str[1] == 0)
02903                 return(True);
02904   
02905         if (!*str && *p == '?') {
02906                 while (*p == '?')
02907                         p++;
02908                 return(!*p);
02909         }
02910 
02911         if(!*str && (*p == '*' && p[1] == '\0'))
02912                 return True;
02913 
02914         return False;
02915 }
02916 
02917 /*******************************************************************
02918  Simple case insensitive interface to a UNIX wildcard matcher.
02919  Returns True if match, False if not.
02920 *******************************************************************/
02921 
02922 BOOL unix_wild_match(const char *pattern, const char *string)
02923 {
02924         pstring p2, s2;
02925         char *p;
02926 
02927         pstrcpy(p2, pattern);
02928         pstrcpy(s2, string);
02929         strlower_m(p2);
02930         strlower_m(s2);
02931 
02932         /* Remove any *? and ** from the pattern as they are meaningless */
02933         for(p = p2; *p; p++)
02934                 while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
02935                         pstrcpy( &p[1], &p[2]);
02936  
02937         if (strequal(p2,"*"))
02938                 return True;
02939 
02940         return unix_do_match(p2, s2);
02941 }
02942 
02943 /**********************************************************************
02944  Converts a name to a fully qualified domain name.
02945  Returns True if lookup succeeded, False if not (then fqdn is set to name)
02946 ***********************************************************************/
02947                                                                                                                                                    
02948 BOOL name_to_fqdn(fstring fqdn, const char *name)
02949 {
02950         struct hostent *hp = sys_gethostbyname(name);
02951 
02952         if ( hp && hp->h_name && *hp->h_name ) {
02953                 char *full = NULL;
02954 
02955                 /* find out if the fqdn is returned as an alias
02956                  * to cope with /etc/hosts files where the first
02957                  * name is not the fqdn but the short name */
02958                 if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
02959                         int i;
02960                         for (i = 0; hp->h_aliases[i]; i++) {
02961                                 if (strchr_m(hp->h_aliases[i], '.')) {
02962                                         full = hp->h_aliases[i];
02963                                         break;
02964                                 }
02965                         }
02966                 }
02967                 if (full && (StrCaseCmp(full, "localhost.localdomain") == 0)) {
02968                         DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
02969                         DEBUGADD(1, ("    Specifing the machine hostname for address 127.0.0.1 may lead\n"));
02970                         DEBUGADD(1, ("    to Kerberos authentication problems as localhost.localdomain\n"));
02971                         DEBUGADD(1, ("    may end up being used instead of the real machine FQDN.\n"));
02972                         full = hp->h_name;
02973                 }
02974                         
02975                 if (!full) {
02976                         full = hp->h_name;
02977                 }
02978 
02979                 DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
02980                 fstrcpy(fqdn, full);
02981                 return True;
02982         } else {
02983                 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
02984                 fstrcpy(fqdn, name);
02985                 return False;
02986         }
02987 }
02988 
02989 /**********************************************************************
02990  Extension to talloc_get_type: Abort on type mismatch
02991 ***********************************************************************/
02992 
02993 void *talloc_check_name_abort(const void *ptr, const char *name)
02994 {
02995         void *result;
02996 
02997         result = talloc_check_name(ptr, name);
02998         if (result != NULL)
02999                 return result;
03000 
03001         DEBUG(0, ("Talloc type mismatch, expected %s, got %s\n",
03002                   name, talloc_get_name(ptr)));
03003         smb_panic("aborting");
03004         /* Keep the compiler happy */
03005         return NULL;
03006 }
03007 
03008 
03009 #ifdef __INSURE__
03010 
03011 /*******************************************************************
03012 This routine is a trick to immediately catch errors when debugging
03013 with insure. A xterm with a gdb is popped up when insure catches
03014 a error. It is Linux specific.
03015 ********************************************************************/
03016 
03017 int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6)
03018 {
03019         static int (*fn)();
03020         int ret;
03021         char pidstr[10];
03022         /* you can get /usr/bin/backtrace from 
03023            http://samba.org/ftp/unpacked/junkcode/backtrace */
03024         pstring cmd = "/usr/bin/backtrace %d";
03025 
03026         slprintf(pidstr, sizeof(pidstr)-1, "%d", sys_getpid());
03027         pstring_sub(cmd, "%d", pidstr);
03028 
03029         if (!fn) {
03030                 static void *h;
03031                 h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);
03032                 fn = dlsym(h, "_Insure_trap_error");
03033 
03034                 if (!h || h == _Insure_trap_error) {
03035                         h = dlopen("/usr/local/parasoft/lib.linux2/libinsure.so", RTLD_LAZY);
03036                         fn = dlsym(h, "_Insure_trap_error");
03037                 }               
03038         }
03039 
03040         ret = fn(a1, a2, a3, a4, a5, a6);
03041 
03042         system(cmd);
03043 
03044         return ret;
03045 }
03046 #endif
03047 
03048 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
03049 {
03050         switch (share_access & ~FILE_SHARE_DELETE) {
03051                 case FILE_SHARE_NONE:
03052                         return DENY_ALL;
03053                 case FILE_SHARE_READ:
03054                         return DENY_WRITE;
03055                 case FILE_SHARE_WRITE:
03056                         return DENY_READ;
03057                 case FILE_SHARE_READ|FILE_SHARE_WRITE:
03058                         return DENY_NONE;
03059         }
03060         if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
03061                 return DENY_DOS;
03062         } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
03063                 return DENY_FCB;
03064         }
03065 
03066         return (uint32)-1;
03067 }
03068 
03069 pid_t procid_to_pid(const struct process_id *proc)
03070 {
03071         return proc->pid;
03072 }
03073 
03074 struct process_id pid_to_procid(pid_t pid)
03075 {
03076         struct process_id result;
03077         result.pid = pid;
03078         return result;
03079 }
03080 
03081 struct process_id procid_self(void)
03082 {
03083         return pid_to_procid(sys_getpid());
03084 }
03085 
03086 struct server_id server_id_self(void)
03087 {
03088         struct server_id id;
03089         id.id = procid_self();
03090         return id;
03091 }
03092 
03093 BOOL procid_equal(const struct process_id *p1, const struct process_id *p2)
03094 {
03095         return (p1->pid == p2->pid);
03096 }
03097 
03098 BOOL cluster_id_equal(const struct server_id *id1,
03099                       const struct server_id *id2)
03100 {
03101         return procid_equal(&id1->id, &id2->id);
03102 }
03103 
03104 BOOL procid_is_me(const struct process_id *pid)
03105 {
03106         return (pid->pid == sys_getpid());
03107 }
03108 
03109 struct process_id interpret_pid(const char *pid_string)
03110 {
03111         return pid_to_procid(atoi(pid_string));
03112 }
03113 
03114 char *procid_str_static(const struct process_id *pid)
03115 {
03116         static fstring str;
03117         fstr_sprintf(str, "%d", pid->pid);
03118         return str;
03119 }
03120 
03121 char *procid_str(TALLOC_CTX *mem_ctx, const struct process_id *pid)
03122 {
03123         return talloc_strdup(mem_ctx, procid_str_static(pid));
03124 }
03125 
03126 BOOL procid_valid(const struct process_id *pid)
03127 {
03128         return (pid->pid != -1);
03129 }
03130 
03131 BOOL procid_is_local(const struct process_id *pid)
03132 {
03133         return True;
03134 }
03135 
03136 int this_is_smp(void)
03137 {
03138 #if defined(HAVE_SYSCONF)
03139 
03140 #if defined(SYSCONF_SC_NPROC_ONLN)
03141         return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0;
03142 #elif defined(SYSCONF_SC_NPROCESSORS_ONLN)
03143         return (sysconf(_SC_NPROCESSORS_ONLN) > 1) ? 1 : 0;
03144 #else
03145         return 0;
03146 #endif
03147 
03148 #else
03149         return 0;
03150 #endif
03151 }
03152 
03153 /****************************************************************
03154  Check if an offset into a buffer is safe.
03155  If this returns True it's safe to indirect into the byte at
03156  pointer ptr+off.
03157 ****************************************************************/
03158 
03159 BOOL is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
03160 {
03161         const char *end_base = buf_base + buf_len;
03162         char *end_ptr = ptr + off;
03163 
03164         if (!buf_base || !ptr) {
03165                 return False;
03166         }
03167 
03168         if (end_base < buf_base || end_ptr < ptr) {
03169                 return False; /* wrap. */
03170         }
03171 
03172         if (end_ptr < end_base) {
03173                 return True;
03174         }
03175         return False;
03176 }
03177 
03178 /****************************************************************
03179  Return a safe pointer into a buffer, or NULL.
03180 ****************************************************************/
03181 
03182 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
03183 {
03184         return is_offset_safe(buf_base, buf_len, ptr, off) ?
03185                         ptr + off : NULL;
03186 }
03187 
03188 /****************************************************************
03189  Return a safe pointer into a string within a buffer, or NULL.
03190 ****************************************************************/
03191 
03192 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
03193 {
03194         if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
03195                 return NULL;
03196         }
03197         /* Check if a valid string exists at this offset. */
03198         if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
03199                 return NULL;
03200         }
03201         return ptr + off;
03202 }
03203 
03204 /****************************************************************
03205  Return an SVAL at a pointer, or failval if beyond the end.
03206 ****************************************************************/
03207 
03208 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
03209 {
03210         /*
03211          * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
03212          * NOT ptr[2].
03213          */
03214         if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
03215                 return failval;
03216         }
03217         return SVAL(ptr,off);
03218 }
03219 
03220 /****************************************************************
03221  Return an IVAL at a pointer, or failval if beyond the end.
03222 ****************************************************************/
03223 
03224 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
03225 {
03226         /*
03227          * Note we use off+3 here, not off+4 as IVAL accesses 
03228          * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
03229          */
03230         if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
03231                 return failval;
03232         }
03233         return IVAL(ptr,off);
03234 }
03235 
03236 /****************************************************************
03237  talloc wrapper functions that guarentee a null pointer return
03238  if size == 0.
03239 ****************************************************************/
03240 
03241 #ifndef MAX_TALLOC_SIZE
03242 #define MAX_TALLOC_SIZE 0x10000000
03243 #endif
03244 
03245 /*
03246  *    talloc and zero memory.
03247  *    - returns NULL if size is zero.
03248  */
03249 
03250 void *_talloc_zero_zeronull(const void *ctx, size_t size, const char *name)
03251 {
03252         void *p;
03253 
03254         if (size == 0) {
03255                 return NULL;
03256         }
03257 
03258         p = talloc_named_const(ctx, size, name);
03259 
03260         if (p) {
03261                 memset(p, '\0', size);
03262         }
03263 
03264         return p;
03265 }
03266 
03267 /*
03268  *   memdup with a talloc.
03269  *   - returns NULL if size is zero.
03270  */
03271 
03272 void *_talloc_memdup_zeronull(const void *t, const void *p, size_t size, const char *name)
03273 {
03274         void *newp;
03275 
03276         if (size == 0) {
03277                 return NULL;
03278         }
03279 
03280         newp = talloc_named_const(t, size, name);
03281         if (newp) {
03282                 memcpy(newp, p, size);
03283         }
03284 
03285         return newp;
03286 }
03287 
03288 /*
03289  *   alloc an array, checking for integer overflow in the array size.
03290  *   - returns NULL if count or el_size are zero.
03291  */
03292 
03293 void *_talloc_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
03294 {
03295         if (count >= MAX_TALLOC_SIZE/el_size) {
03296                 return NULL;
03297         }
03298 
03299         if (el_size == 0 || count == 0) {
03300                 return NULL;
03301         }
03302 
03303         return talloc_named_const(ctx, el_size * count, name);
03304 }
03305 
03306 /*
03307  *   alloc an zero array, checking for integer overflow in the array size
03308  *   - returns NULL if count or el_size are zero.
03309  */
03310 
03311 void *_talloc_zero_array_zeronull(const void *ctx, size_t el_size, unsigned count, const char *name)
03312 {
03313         if (count >= MAX_TALLOC_SIZE/el_size) {
03314                 return NULL;
03315         }
03316 
03317         if (el_size == 0 || count == 0) {
03318                 return NULL;
03319         }
03320 
03321         return _talloc_zero(ctx, el_size * count, name);
03322 }
03323 
03324 /*
03325  *   Talloc wrapper that returns NULL if size == 0.
03326  */
03327 void *talloc_zeronull(const void *context, size_t size, const char *name)
03328 {
03329         if (size == 0) {
03330                 return NULL;
03331         }
03332         return talloc_named_const(context, size, name);
03333 }

Sambaに対してSat Aug 29 21:23:00 2009に生成されました。  doxygen 1.4.7