📄 util.c
字号:
/* Unix SMB/CIFS implementation. Samba utility functions Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 2001-2002 Copyright (C) Simo Sorce 2001 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "includes.h"extern fstring local_machine;extern char *global_clobber_region_function;extern unsigned int global_clobber_region_line;extern fstring remote_arch;/* Max allowable allococation - 256mb - 0x10000000 */#define MAX_ALLOC_SIZE (1024*1024*256)#if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))#ifdef WITH_NISPLUS_HOME#ifdef BROKEN_NISPLUS_INCLUDE_FILES/* * The following lines are needed due to buggy include files * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA. * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as * an enum in /usr/include/rpcsvc/nis.h. */#if defined(GROUP)#undef GROUP#endif#if defined(GROUP_OBJ)#undef GROUP_OBJ#endif#endif /* BROKEN_NISPLUS_INCLUDE_FILES */#include <rpcsvc/nis.h>#endif /* WITH_NISPLUS_HOME */#endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */enum protocol_types Protocol = PROTOCOL_COREPLUS;/* a default finfo structure to ensure all fields are sensible */file_info def_finfo = {-1,0,0,0,0,0,0,"",""};/* this is used by the chaining code */int chain_size = 0;int trans_num = 0;static enum remote_arch_types ra_type = RA_UNKNOWN;pstring user_socket_options=DEFAULT_SOCKET_OPTIONS; /*********************************************************************** Definitions for all names.***********************************************************************/static char *smb_myname;static char *smb_myworkgroup;static char *smb_scope;static int smb_num_netbios_names;static char **smb_my_netbios_names;/*********************************************************************** Allocate and set myname. Ensure upper case.***********************************************************************/BOOL set_global_myname(const char *myname){ SAFE_FREE(smb_myname); smb_myname = SMB_STRDUP(myname); if (!smb_myname) return False; strupper_m(smb_myname); return True;}const char *global_myname(void){ return smb_myname;}/*********************************************************************** Allocate and set myworkgroup. Ensure upper case.***********************************************************************/BOOL set_global_myworkgroup(const char *myworkgroup){ SAFE_FREE(smb_myworkgroup); smb_myworkgroup = SMB_STRDUP(myworkgroup); if (!smb_myworkgroup) return False; strupper_m(smb_myworkgroup); return True;}const char *lp_workgroup(void){ return smb_myworkgroup;}/*********************************************************************** Allocate and set scope. Ensure upper case.***********************************************************************/BOOL set_global_scope(const char *scope){ SAFE_FREE(smb_scope); smb_scope = SMB_STRDUP(scope); if (!smb_scope) return False; strupper_m(smb_scope); return True;}/********************************************************************* Ensure scope is never null string.*********************************************************************/const char *global_scope(void){ if (!smb_scope) set_global_scope(""); return smb_scope;}static void free_netbios_names_array(void){ int i; for (i = 0; i < smb_num_netbios_names; i++) SAFE_FREE(smb_my_netbios_names[i]); SAFE_FREE(smb_my_netbios_names); smb_num_netbios_names = 0;}static BOOL allocate_my_netbios_names_array(size_t number){ free_netbios_names_array(); smb_num_netbios_names = number + 1; smb_my_netbios_names = SMB_MALLOC_ARRAY( char *, smb_num_netbios_names ); if (!smb_my_netbios_names) return False; memset(smb_my_netbios_names, '\0', sizeof(char *) * smb_num_netbios_names); return True;}static BOOL set_my_netbios_names(const char *name, int i){ SAFE_FREE(smb_my_netbios_names[i]); smb_my_netbios_names[i] = SMB_STRDUP(name); if (!smb_my_netbios_names[i]) return False; strupper_m(smb_my_netbios_names[i]); return True;}const char *my_netbios_names(int i){ return smb_my_netbios_names[i];}BOOL set_netbios_aliases(const char **str_array){ size_t namecount; /* Work out the max number of netbios aliases that we have */ for( namecount=0; str_array && (str_array[namecount] != NULL); namecount++ ) ; if ( global_myname() && *global_myname()) namecount++; /* Allocate space for the netbios aliases */ if (!allocate_my_netbios_names_array(namecount)) return False; /* Use the global_myname string first */ namecount=0; if ( global_myname() && *global_myname()) { set_my_netbios_names( global_myname(), namecount ); namecount++; } if (str_array) { size_t i; for ( i = 0; str_array[i] != NULL; i++) { size_t n; BOOL duplicate = False; /* Look for duplicates */ for( n=0; n<namecount; n++ ) { if( strequal( str_array[i], my_netbios_names(n) ) ) { duplicate = True; break; } } if (!duplicate) { if (!set_my_netbios_names(str_array[i], namecount)) return False; namecount++; } } } return True;}/**************************************************************************** Common name initialization code.****************************************************************************/BOOL init_names(void){ char *p; int n; if (global_myname() == NULL || *global_myname() == '\0') { if (!set_global_myname(myhostname())) { DEBUG( 0, ( "init_structs: malloc fail.\n" ) ); return False; } } if (!set_netbios_aliases(lp_netbios_aliases())) { DEBUG( 0, ( "init_structs: malloc fail.\n" ) ); return False; } fstrcpy( local_machine, global_myname() ); trim_char( local_machine, ' ', ' ' ); p = strchr( local_machine, ' ' ); if (p) *p = 0; strlower_m( local_machine ); DEBUG( 5, ("Netbios name list:-\n") ); for( n=0; my_netbios_names(n); n++ ) DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names(n) ) ); return( True );}/**************************************************************************n Find a suitable temporary directory. The result should be copied immediately as it may be overwritten by a subsequent call.****************************************************************************/const char *tmpdir(void){ char *p; if ((p = getenv("TMPDIR"))) return p; return "/tmp";}/**************************************************************************** Add a gid to an array of gids if it's not already there.****************************************************************************/void add_gid_to_array_unique(TALLOC_CTX *mem_ctx, gid_t gid, gid_t **gids, size_t *num_gids){ int i; for (i=0; i<*num_gids; i++) { if ((*gids)[i] == gid) return; } if (mem_ctx != NULL) *gids = TALLOC_REALLOC_ARRAY(mem_ctx, *gids, gid_t, *num_gids+1); else *gids = SMB_REALLOC_ARRAY(*gids, gid_t, *num_gids+1); if (*gids == NULL) return; (*gids)[*num_gids] = gid; *num_gids += 1;}/**************************************************************************** Like atoi but gets the value up to the separator character.****************************************************************************/static const char *Atoic(const char *p, int *n, const char *c){ if (!isdigit((int)*p)) { DEBUG(5, ("Atoic: malformed number\n")); return NULL; } (*n) = atoi(p); while ((*p) && isdigit((int)*p)) p++; if (strchr_m(c, *p) == NULL) { DEBUG(5, ("Atoic: no separator characters (%s) not found\n", c)); return NULL; } return p;}/************************************************************************* Reads a list of numbers. *************************************************************************/const char *get_numlist(const char *p, uint32 **num, int *count){ int val; if (num == NULL || count == NULL) return NULL; (*count) = 0; (*num ) = NULL; while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':') { uint32 *tn; tn = SMB_REALLOC_ARRAY((*num), uint32, (*count)+1); if (tn == NULL) { SAFE_FREE(*num); return NULL; } else (*num) = tn; (*num)[(*count)] = val; (*count)++; p++; } return p;}/******************************************************************* Check if a file exists - call vfs_file_exist for samba files.********************************************************************/BOOL file_exist(const char *fname,SMB_STRUCT_STAT *sbuf){ SMB_STRUCT_STAT st; if (!sbuf) sbuf = &st; if (sys_stat(fname,sbuf) != 0) return(False); return((S_ISREG(sbuf->st_mode)) || (S_ISFIFO(sbuf->st_mode)));}/******************************************************************* Check a files mod time.********************************************************************/time_t file_modtime(const char *fname){ SMB_STRUCT_STAT st; if (sys_stat(fname,&st) != 0) return(0); return(st.st_mtime);}/******************************************************************* Check if a directory exists.********************************************************************/BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st){ SMB_STRUCT_STAT st2; BOOL ret; if (!st) st = &st2; if (sys_stat(dname,st) != 0) return(False); ret = S_ISDIR(st->st_mode); if(!ret) errno = ENOTDIR; return ret;}/******************************************************************* Returns the size in bytes of the named file.********************************************************************/SMB_OFF_T get_file_size(char *file_name){ SMB_STRUCT_STAT buf; buf.st_size = 0; if(sys_stat(file_name,&buf) != 0) return (SMB_OFF_T)-1; return(buf.st_size);}/******************************************************************* Return a string representing an attribute for a file.********************************************************************/char *attrib_string(uint16 mode){ static fstring attrstr; attrstr[0] = 0; if (mode & aVOLID) fstrcat(attrstr,"V"); if (mode & aDIR) fstrcat(attrstr,"D"); if (mode & aARCH) fstrcat(attrstr,"A"); if (mode & aHIDDEN) fstrcat(attrstr,"H"); if (mode & aSYSTEM) fstrcat(attrstr,"S"); if (mode & aRONLY) fstrcat(attrstr,"R"); return(attrstr);}/******************************************************************* Show a smb message structure.********************************************************************/void show_msg(char *buf){ int i; int bcc=0; if (!DEBUGLVL(5)) return; DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n", smb_len(buf), (int)CVAL(buf,smb_com), (int)CVAL(buf,smb_rcls), (int)CVAL(buf,smb_reh), (int)SVAL(buf,smb_err), (int)CVAL(buf,smb_flg), (int)SVAL(buf,smb_flg2))); DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n", (int)SVAL(buf,smb_tid), (int)SVAL(buf,smb_pid), (int)SVAL(buf,smb_uid), (int)SVAL(buf,smb_mid))); DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct))); for (i=0;i<(int)CVAL(buf,smb_wct);i++) DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i, SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i))); bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct))); DEBUGADD(5,("smb_bcc=%d\n",bcc)); if (DEBUGLEVEL < 10) return; if (DEBUGLEVEL < 50) bcc = MIN(bcc, 512); dump_data(10, smb_buf(buf), bcc); }/******************************************************************* Set the length and marker of an smb packet.********************************************************************/void smb_setlen(char *buf,int len){ _smb_setlen(buf,len); SCVAL(buf,4,0xFF); SCVAL(buf,5,'S'); SCVAL(buf,6,'M'); SCVAL(buf,7,'B');}/******************************************************************* Setup the word count and byte count for a smb message.********************************************************************/int set_message(char *buf,int num_words,int num_bytes,BOOL zero){ if (zero) memset(buf + smb_size,'\0',num_words*2 + num_bytes); SCVAL(buf,smb_wct,num_words); SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes); smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4); return (smb_size + num_words*2 + num_bytes);}/******************************************************************* Setup only the byte count for a smb message.********************************************************************/int set_message_bcc(char *buf,int num_bytes){ int num_words = CVAL(buf,smb_wct); SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes); smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4); return (smb_size + num_words*2 + num_bytes);}/******************************************************************* Setup only the byte count for a smb message, using the end of the message as a marker.********************************************************************/int set_message_end(void *outbuf,void *end_ptr){ return set_message_bcc((char *)outbuf,PTR_DIFF(end_ptr,smb_buf((char *)outbuf)));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -