smbw.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 1,563 行 · 第 1/3 页

C
1,563
字号
/*    Unix SMB/CIFS implementation.   SMB wrapper functions   Copyright (C) Andrew Tridgell 1998      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"#include "realcalls.h"pstring smbw_cwd;static struct smbw_file *smbw_files;static struct smbw_server *smbw_srvs;struct bitmap *smbw_file_bmap;fstring smbw_prefix = SMBW_PREFIX;int smbw_busy=0;/* needs to be here because of dumb include files on some systems */int creat_bits = O_WRONLY|O_CREAT|O_TRUNC;/***************************************************** initialise structures*******************************************************/void smbw_init(void){	extern BOOL in_client;	static int initialised;	char *p;	int eno;	pstring line;	if (initialised) return;	initialised = 1;	eno = errno;	smbw_busy++;	DEBUGLEVEL = 0;	setup_logging("smbsh",True);	dbf = x_stderr;	if ((p=smbw_getshared("LOGFILE"))) {		dbf = sys_fopen(p, "a");	}	smbw_file_bmap = bitmap_allocate(SMBW_MAX_OPEN);	if (!smbw_file_bmap) {		exit(1);	}	in_client = True;	load_interfaces();	if ((p=smbw_getshared("SERVICESF"))) {		pstrcpy(dyn_CONFIGFILE, p);	}	lp_load(dyn_CONFIGFILE,True,False,False);	if (!init_names())		exit(1);	if ((p=smbw_getshared("DEBUG"))) {		DEBUGLEVEL = atoi(p);	}	if ((p=smbw_getshared("RESOLVE_ORDER"))) {		lp_set_name_resolve_order(p);	}	if ((p=smbw_getshared("PREFIX"))) {		slprintf(smbw_prefix,sizeof(fstring)-1, "/%s/", p);		all_string_sub(smbw_prefix,"//", "/", 0);		DEBUG(2,("SMBW_PREFIX is %s\n", smbw_prefix));	}	slprintf(line,sizeof(line)-1,"PWD_%d", (int)getpid());		p = smbw_getshared(line);	if (!p) {		sys_getwd(smbw_cwd);	}	pstrcpy(smbw_cwd, p);	DEBUG(4,("Initial cwd is %s\n", smbw_cwd));	smbw_busy--;	set_maxfiles(SMBW_MAX_OPEN);	BlockSignals(True,SIGPIPE);	errno = eno;}/***************************************************** determine if a file descriptor is a smb one*******************************************************/int smbw_fd(int fd){	if (smbw_busy) return 0;	return smbw_file_bmap && bitmap_query(smbw_file_bmap, fd);}/***************************************************** determine if a file descriptor is an internal smbw fd*******************************************************/int smbw_local_fd(int fd){	struct smbw_server *srv;		smbw_init();	if (smbw_busy) return 0;	if (smbw_shared_fd(fd)) return 1;	for (srv=smbw_srvs;srv;srv=srv->next) {		if (srv->cli.fd == fd) return 1;	}	return 0;}/***************************************************** a crude inode number generator*******************************************************/ino_t smbw_inode(const char *name){	if (!*name) return 2;	return (ino_t)str_checksum(name);}/***************************************************** remove redundent stuff from a filename*******************************************************/void clean_fname(char *name){	char *p, *p2;	int l;	int modified = 1;	if (!name) return;	while (modified) {		modified = 0;		DEBUG(5,("cleaning %s\n", name));		if ((p=strstr(name,"/./"))) {			modified = 1;			while (*p) {				p[0] = p[2];				p++;			}		}		if ((p=strstr(name,"//"))) {			modified = 1;			while (*p) {				p[0] = p[1];				p++;			}		}		if (strcmp(name,"/../")==0) {			modified = 1;			name[1] = 0;		}		if ((p=strstr(name,"/../"))) {			modified = 1;			for (p2=(p>name?p-1:p);p2>name;p2--) {				if (p2[0] == '/') break;			}			while (*p2) {				p2[0] = p2[3];				p2++;			}		}		if (strcmp(name,"/..")==0) {			modified = 1;			name[1] = 0;		}		l = strlen(name);		p = l>=3?(name+l-3):name;		if (strcmp(p,"/..")==0) {			modified = 1;			for (p2=p-1;p2>name;p2--) {				if (p2[0] == '/') break;			}			if (p2==name) {				p[0] = '/';				p[1] = 0;			} else {				p2[0] = 0;			}		}		l = strlen(name);		p = l>=2?(name+l-2):name;		if (strcmp(p,"/.")==0) {			if (p == name) {				p[1] = 0;			} else {				p[0] = 0;			}		}		if (strncmp(p=name,"./",2) == 0) {      			modified = 1;			do {				p[0] = p[2];			} while (*p++);		}		l = strlen(p=name);		if (l > 1 && p[l-1] == '/') {			modified = 1;			p[l-1] = 0;		}	}}/***************************************************** find a workgroup (any workgroup!) that has a master browser on the local network*******************************************************/static char *smbw_find_workgroup(void){	fstring server;	char *p;	struct in_addr *ip_list = NULL;	int count = 0;	int i;	/* first off see if an existing workgroup name exists */	p = smbw_getshared("WORKGROUP");	if (!p) p = lp_workgroup();		slprintf(server, sizeof(server), "%s#1D", p);	if (smbw_server(server, "IPC$")) return p;	/* go looking for workgroups */	if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {		DEBUG(1,("No workgroups found!"));		return p;	}	for (i=0;i<count;i++) {		static fstring name;		if (name_status_find("*", 0, 0x1d, ip_list[i], name)) {			slprintf(server, sizeof(server), "%s#1D", name);			if (smbw_server(server, "IPC$")) {				smbw_setshared("WORKGROUP", name);				SAFE_FREE(ip_list);				return name;			}		}	}	SAFE_FREE(ip_list);	return p;}/***************************************************** parse a smb path into its components. server is one of  1) the name of the SMB server  2) WORKGROUP#1D for share listing  3) WORKGROUP#__ for workgroup listingshare is the share on the server to querypath is the SMB path on the serverreturn the full path (ie. add cwd if needed)*******************************************************/char *smbw_parse_path(const char *fname, char *server, char *share, char *path){	static pstring s;	char *p;	int len;	fstring workgroup;	/* add cwd if necessary */	if (fname[0] != '/') {		slprintf(s, sizeof(s), "%s/%s", smbw_cwd, fname);	} else {		pstrcpy(s, fname);	}	clean_fname(s);	/* see if it has the right prefix */	len = strlen(smbw_prefix)-1;	if (strncmp(s,smbw_prefix,len) || 	    (s[len] != '/' && s[len] != 0)) return s;	/* ok, its for us. Now parse out the workgroup, share etc. */	p = s+len;	if (*p == '/') p++;	if (!next_token(&p, workgroup, "/", sizeof(fstring))) {		/* we're in /smb - give a list of workgroups */		slprintf(server,sizeof(fstring), "%s#01", smbw_find_workgroup());		fstrcpy(share,"IPC$");		pstrcpy(path,"");		return s;	}	if (!next_token(&p, server, "/", sizeof(fstring))) {		/* we are in /smb/WORKGROUP */		slprintf(server,sizeof(fstring), "%s#1D", workgroup);		fstrcpy(share,"IPC$");		pstrcpy(path,"");	}	if (!next_token(&p, share, "/", sizeof(fstring))) {		/* we are in /smb/WORKGROUP/SERVER */		fstrcpy(share,"IPC$");		pstrcpy(path,"");	}	pstrcpy(path, p);	all_string_sub(path, "/", "\\", 0);	return s;}/***************************************************** determine if a path name (possibly relative) is in the smb name space*******************************************************/int smbw_path(const char *path){	fstring server, share;	pstring s;	char *cwd;	int len;	if(!path)		return 0;	/* this is needed to prevent recursion with the BSD malloc which	   opens /etc/malloc.conf on the first call */	if (strncmp(path,"/etc/", 5) == 0) {		return 0;	}	smbw_init();	len = strlen(smbw_prefix)-1;	if (path[0] == '/' && strncmp(path,smbw_prefix,len)) {		return 0;	}	if (smbw_busy) return 0;	DEBUG(3,("smbw_path(%s)\n", path));	cwd = smbw_parse_path(path, server, share, s);	if (strncmp(cwd,smbw_prefix,len) == 0 &&	    (cwd[len] == '/' || cwd[len] == 0)) {		return 1;	}	return 0;}/***************************************************** return a unix errno from a SMB error pair*******************************************************/int smbw_errno(struct cli_state *c){	return cli_errno(c);}/* Return a username and password given a server and share name */void get_envvar_auth_data(char *server, char *share, char **workgroup,			  char **username, char **password){	/* Fall back to shared memory/environment variables */	*username = smbw_getshared("USER");	if (!*username) *username = getenv("USER");	if (!*username) *username = "guest";	*workgroup = smbw_getshared("WORKGROUP");	if (!*workgroup) *workgroup = lp_workgroup();	*password = smbw_getshared("PASSWORD");	if (!*password) *password = "";}static smbw_get_auth_data_fn get_auth_data_fn = get_envvar_auth_data;/*****************************************************set the get auth data function******************************************************/void smbw_set_auth_data_fn(smbw_get_auth_data_fn fn){	get_auth_data_fn = fn;}/***************************************************** return a connection to a server (existing or new)*******************************************************/struct smbw_server *smbw_server(char *server, char *share){	struct smbw_server *srv=NULL;	struct cli_state c;	char *username;	char *password;	char *workgroup;	struct nmb_name called, calling;	char *p, *server_n = server;	fstring group;	pstring ipenv;	struct in_addr ip;        zero_ip(&ip);	ZERO_STRUCT(c);	get_auth_data_fn(server, share, &workgroup, &username, &password);	/* try to use an existing connection */	for (srv=smbw_srvs;srv;srv=srv->next) {		if (strcmp(server,srv->server_name)==0 &&		    strcmp(share,srv->share_name)==0 &&		    strcmp(workgroup,srv->workgroup)==0 &&		    strcmp(username, srv->username) == 0) 			return srv;	}	if (server[0] == 0) {		errno = EPERM;		return NULL;	}	make_nmb_name(&calling, global_myname(), 0x0);	make_nmb_name(&called , server, 0x20);	DEBUG(4,("server_n=[%s] server=[%s]\n", server_n, server));	if ((p=strchr_m(server_n,'#')) && 	    (strcmp(p+1,"1D")==0 || strcmp(p+1,"01")==0)) {		struct in_addr sip;		pstring s;		fstrcpy(group, server_n);		p = strchr_m(group,'#');		*p = 0;				/* cache the workgroup master lookup */		slprintf(s,sizeof(s)-1,"MASTER_%s", group);		if (!(server_n = smbw_getshared(s))) {			if (!find_master_ip(group, &sip)) {				errno = ENOENT;				return NULL;			}			fstrcpy(group, inet_ntoa(sip));			server_n = group;			smbw_setshared(s,server_n);		}	}	DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server)); again:	slprintf(ipenv,sizeof(ipenv)-1,"HOST_%s", server_n);        zero_ip(&ip);	if ((p=smbw_getshared(ipenv))) {		ip = *(interpret_addr2(p));	}	/* have to open a new connection */	if (!cli_initialise(&c) || !cli_connect(&c, server_n, &ip)) {		errno = ENOENT;		return NULL;	}	if (!cli_session_request(&c, &calling, &called)) {		cli_shutdown(&c);		if (strcmp(called.name, "*SMBSERVER")) {			make_nmb_name(&called , "*SMBSERVER", 0x20);			goto again;		}		errno = ENOENT;		return NULL;	}	DEBUG(4,(" session request ok\n"));	if (!cli_negprot(&c)) {		cli_shutdown(&c);		errno = ENOENT;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?