📄 libsmbclient.c
字号:
/* Unix SMB/Netbios implementation. SMB client library implementation Copyright (C) Andrew Tridgell 1998 Copyright (C) Richard Sharpe 2000, 2002 Copyright (C) John Terpstra 2000 Copyright (C) Tom Jansen (Ninja ISD) 2002 Copyright (C) Derrell Lipman 2003, 2004 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 "include/libsmb_internal.h"/* * DOS Attribute values (used internally) */typedef struct DOS_ATTR_DESC { int mode; SMB_OFF_T size; time_t a_time; time_t c_time; time_t m_time; SMB_INO_T inode;} DOS_ATTR_DESC;/* * Internal flags for extended attributes *//* internal mode values */#define SMBC_XATTR_MODE_ADD 1#define SMBC_XATTR_MODE_REMOVE 2#define SMBC_XATTR_MODE_REMOVE_ALL 3#define SMBC_XATTR_MODE_SET 4#define SMBC_XATTR_MODE_CHOWN 5#define SMBC_XATTR_MODE_CHGRP 6#define CREATE_ACCESS_READ READ_CONTROL_ACCESS/*We should test for this in configure ... */#ifndef ENOTSUP#define ENOTSUP EOPNOTSUPP#endif/* * Functions exported by libsmb_cache.c that we need here */int smbc_default_cache_functions(SMBCCTX *context);/* * check if an element is part of the list. * FIXME: Does not belong here ! * Can anyone put this in a macro in dlinklist.h ? * -- Tom */static int DLIST_CONTAINS(SMBCFILE * list, SMBCFILE *p) { if (!p || !list) return False; do { if (p == list) return True; list = list->next; } while (list); return False;}/* * Find an lsa pipe handle associated with a cli struct. */static struct rpc_pipe_client *find_lsa_pipe_hnd(struct cli_state *ipc_cli){ struct rpc_pipe_client *pipe_hnd; for (pipe_hnd = ipc_cli->pipe_list; pipe_hnd; pipe_hnd = pipe_hnd->next) { if (pipe_hnd->pipe_idx == PI_LSARPC) { return pipe_hnd; } } return NULL;}static intsmbc_close_ctx(SMBCCTX *context, SMBCFILE *file);static off_tsmbc_lseek_ctx(SMBCCTX *context, SMBCFILE *file, off_t offset, int whence);extern BOOL in_client;/* * Is the logging working / configfile read ? */static int smbc_initialized = 0;static int hex2int( unsigned int _char ){ if ( _char >= 'A' && _char <='F') return _char - 'A' + 10; if ( _char >= 'a' && _char <='f') return _char - 'a' + 10; if ( _char >= '0' && _char <='9') return _char - '0'; return -1;}/* * smbc_urldecode() * * Convert strings of %xx to their single character equivalent. Each 'x' must * be a valid hexadecimal digit, or that % sequence is left undecoded. * * dest may, but need not be, the same pointer as src. * * Returns the number of % sequences which could not be converted due to lack * of two following hexadecimal digits. */intsmbc_urldecode(char *dest, char * src, size_t max_dest_len){ int old_length = strlen(src); int i = 0; int err_count = 0; pstring temp; char * p; if ( old_length == 0 ) { return 0; } p = temp; while ( i < old_length ) { unsigned char character = src[ i++ ]; if (character == '%') { int a = i+1 < old_length ? hex2int( src[i] ) : -1; int b = i+1 < old_length ? hex2int( src[i+1] ) : -1; /* Replace valid sequence */ if (a != -1 && b != -1) { /* Replace valid %xx sequence with %dd */ character = (a * 16) + b; if (character == '\0') { break; /* Stop at %00 */ } i += 2; } else { err_count++; } } *p++ = character; } *p = '\0'; strncpy(dest, temp, max_dest_len); return err_count;}/* * smbc_urlencode() * * Convert any characters not specifically allowed in a URL into their %xx * equivalent. * * Returns the remaining buffer length. */intsmbc_urlencode(char * dest, char * src, int max_dest_len){ char hex[] = "0123456789ABCDEF"; for (; *src != '\0' && max_dest_len >= 3; src++) { if ((*src < '0' && *src != '-' && *src != '.') || (*src > '9' && *src < 'A') || (*src > 'Z' && *src < 'a' && *src != '_') || (*src > 'z')) { *dest++ = '%'; *dest++ = hex[(*src >> 4) & 0x0f]; *dest++ = hex[*src & 0x0f]; max_dest_len -= 3; } else { *dest++ = *src; max_dest_len--; } } *dest++ = '\0'; max_dest_len--; return max_dest_len;}/* * Function to parse a path and turn it into components * * The general format of an SMB URI is explain in Christopher Hertel's CIFS * book, at http://ubiqx.org/cifs/Appendix-D.html. We accept a subset of the * general format ("smb:" only; we do not look for "cifs:"). * * * We accept: * smb://[[[domain;]user[:password@]]server[/share[/path[/file]]]][?options] * * Meaning of URLs: * * smb:// Show all workgroups. * * The method of locating the list of workgroups varies * depending upon the setting of the context variable * context->options.browse_max_lmb_count. This value * determine the maximum number of local master browsers to * query for the list of workgroups. In order to ensure that * a complete list of workgroups is obtained, all master * browsers must be queried, but if there are many * workgroups, the time spent querying can begin to add up. * For small networks (not many workgroups), it is suggested * that this variable be set to 0, indicating query all local * master browsers. When the network has many workgroups, a * reasonable setting for this variable might be around 3. * * smb://name/ if name<1D> or name<1B> exists, list servers in * workgroup, else, if name<20> exists, list all shares * for server ... * * If "options" are provided, this function returns the entire option list as a * string, for later parsing by the caller. Note that currently, no options * are supported. */static const char *smbc_prefix = "smb:";static intsmbc_parse_path(SMBCCTX *context, const char *fname, char *server, int server_len, char *share, int share_len, char *path, int path_len, char *user, int user_len, char *password, int password_len, char *options, int options_len){ static pstring s; pstring userinfo; const char *p; char *q, *r; int len; server[0] = share[0] = path[0] = user[0] = password[0] = (char)0; if (options != NULL && options_len > 0) { options[0] = (char)0; } pstrcpy(s, fname); /* see if it has the right prefix */ len = strlen(smbc_prefix); if (strncmp(s,smbc_prefix,len) || (s[len] != '/' && s[len] != 0)) { return -1; /* What about no smb: ? */ } p = s + len; /* Watch the test below, we are testing to see if we should exit */ if (strncmp(p, "//", 2) && strncmp(p, "\\\\", 2)) { DEBUG(1, ("Invalid path (does not begin with smb://")); return -1; } p += 2; /* Skip the double slash */ /* See if any options were specified */ if ((q = strrchr(p, '?')) != NULL ) { /* There are options. Null terminate here and point to them */ *q++ = '\0'; DEBUG(4, ("Found options '%s'", q)); /* Copy the options */ if (options != NULL && options_len > 0) { safe_strcpy(options, q, options_len - 1); } } if (*p == (char)0) goto decoding; if (*p == '/') { strncpy(server, context->workgroup, ((strlen(context->workgroup) < 16) ? strlen(context->workgroup) : 16)); return 0; } /* * ok, its for us. Now parse out the server, share etc. * * However, we want to parse out [[domain;]user[:password]@] if it * exists ... */ /* check that '@' occurs before '/', if '/' exists at all */ q = strchr_m(p, '@'); r = strchr_m(p, '/'); if (q && (!r || q < r)) { pstring username, passwd, domain; const char *u = userinfo; next_token(&p, userinfo, "@", sizeof(fstring)); username[0] = passwd[0] = domain[0] = 0; if (strchr_m(u, ';')) { next_token(&u, domain, ";", sizeof(fstring)); } if (strchr_m(u, ':')) { next_token(&u, username, ":", sizeof(fstring)); pstrcpy(passwd, u); } else { pstrcpy(username, u); } if (username[0]) strncpy(user, username, user_len); /* FIXME, domain */ if (passwd[0]) strncpy(password, passwd, password_len); } if (!next_token(&p, server, "/", sizeof(fstring))) { return -1; } if (*p == (char)0) goto decoding; /* That's it ... */ if (!next_token(&p, share, "/", sizeof(fstring))) { return -1; } safe_strcpy(path, p, path_len - 1); all_string_sub(path, "/", "\\", 0); decoding: (void) smbc_urldecode(path, path, path_len); (void) smbc_urldecode(server, server, server_len); (void) smbc_urldecode(share, share, share_len); (void) smbc_urldecode(user, user, user_len); (void) smbc_urldecode(password, password, password_len); return 0;}/* * Verify that the options specified in a URL are valid */static intsmbc_check_options(char *server, char *share, char *path, char *options){ DEBUG(4, ("smbc_check_options(): server='%s' share='%s' " "path='%s' options='%s'\n", server, share, path, options)); /* No options at all is always ok */ if (! *options) return 0; /* Currently, we don't support any options. */ return -1;}/* * Convert an SMB error into a UNIX error ... */static intsmbc_errno(SMBCCTX *context, struct cli_state *c){ int ret = cli_errno(c); if (cli_is_dos_error(c)) { uint8 eclass; uint32 ecode; cli_dos_error(c, &eclass, &ecode); DEBUG(3,("smbc_error %d %d (0x%x) -> %d\n", (int)eclass, (int)ecode, (int)ecode, ret)); } else { NTSTATUS status; status = cli_nt_error(c); DEBUG(3,("smbc errno %s -> %d\n", nt_errstr(status), ret)); } return ret;}/* * Check a server for being alive and well. * returns 0 if the server is in shape. Returns 1 on error * * Also useable outside libsmbclient to enable external cache * to do some checks too. */static intsmbc_check_server(SMBCCTX * context, SMBCSRV * server) { if ( send_keepalive(server->cli.fd) == False ) return 1; /* connection is ok */ return 0;}/* * Remove a server from the cached server list it's unused. * On success, 0 is returned. 1 is returned if the server could not be removed. * * Also useable outside libsmbclient */intsmbc_remove_unused_server(SMBCCTX * context, SMBCSRV * srv){ SMBCFILE * file; /* are we being fooled ? */ if (!context || !context->internal || !context->internal->_initialized || !srv) return 1; /* Check all open files/directories for a relation with this server */ for (file = context->internal->_files; file; file=file->next) { if (file->srv == srv) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -