1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

updating release notes & merging Derrel Lipman's libsmbclient patch from HEAD

(This used to be commit 5fbfaa687a)
This commit is contained in:
Gerald Carter 2004-03-19 16:22:47 +00:00
parent ebf27cf5a1
commit 56ce613679
5 changed files with 548 additions and 119 deletions

View File

@ -714,7 +714,7 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
/* create a socket to write to */
res = socket(PF_INET, type, 0);
if (res == -1) {
DEBUG(0,("socket error\n"));
DEBUG(0,("socket error (%s)\n", strerror(errno)));
return -1;
}

View File

@ -1590,42 +1590,88 @@ struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip,
return NULL;
}
/* Return the IP address and workgroup of a master browser on the
network. */
/*
* Given the IP address of a master browser on the network, return its
* workgroup and connect to it.
*
* This function is provided to allow additional processing beyond what
* get_ipc_connect_master_ip_bcast() does, e.g. to retrieve the list of master
* browsers and obtain each master browsers' list of domains (in case the
* first master browser is recently on the network and has not yet
* synchronized with other master browsers and therefore does not yet have the
* entire network browse list)
*/
struct cli_state *get_ipc_connect_master_ip(struct ip_service * mb_ip, pstring workgroup, struct user_auth_info *user_info)
{
static fstring name;
struct cli_state *cli;
struct in_addr server_ip;
DEBUG(99, ("Looking up name of master browser %s\n",
inet_ntoa(mb_ip->ip)));
/*
* Do a name status query to find out the name of the master browser.
* We use <01><02>__MSBROWSE__<02>#01 if *#00 fails because a domain
* master browser will not respond to a wildcard query (or, at least,
* an NT4 server acting as the domain master browser will not).
*
* We might be able to use ONLY the query on MSBROWSE, but that's not
* yet been tested with all Windows versions, so until it is, leave
* the original wildcard query as the first choice and fall back to
* MSBROWSE if the wildcard query fails.
*/
if (!name_status_find("*", 0, 0x1d, mb_ip->ip, name) &&
!name_status_find(MSBROWSE, 1, 0x1d, mb_ip->ip, name)) {
DEBUG(99, ("Could not retrieve name status for %s\n",
inet_ntoa(mb_ip->ip)));
return NULL;
}
if (!find_master_ip(name, &server_ip)) {
DEBUG(99, ("Could not find master ip for %s\n", name));
return NULL;
}
pstrcpy(workgroup, name);
DEBUG(4, ("found master browser %s, %s\n",
name, inet_ntoa(mb_ip->ip)));
cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info);
return cli;
}
/*
* Return the IP address and workgroup of a master browser on the network, and
* connect to it.
*/
struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user_auth_info *user_info)
{
struct ip_service *ip_list;
struct cli_state *cli;
int i, count;
struct in_addr server_ip;
DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
/* Go looking for workgroups by broadcasting on the local network */
if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
DEBUG(99, ("No master browsers responded\n"));
return False;
}
for (i = 0; i < count; i++) {
static fstring name;
DEBUG(99, ("Found master browser %s\n", inet_ntoa(ip_list[i].ip)));
if (!name_status_find("*", 0, 0x1d, ip_list[i].ip, name))
continue;
if (!find_master_ip(name, &server_ip))
continue;
pstrcpy(workgroup, name);
DEBUG(4, ("found master browser %s, %s\n",
name, inet_ntoa(ip_list[i].ip)));
cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info);
if (!cli)
continue;
return cli;
cli = get_ipc_connect_master_ip(&ip_list[i], workgroup, user_info);
if (cli)
return(cli);
}
return NULL;

View File

@ -367,6 +367,17 @@ void cli_nt_netlogon_netsec_session_close(struct cli_state *cli)
void cli_close_connection(struct cli_state *cli)
{
/*
* tell our peer to free his resources. Wihtout this, when an
* application attempts to do a graceful shutdown and calls
* smbc_free_context() to clean up all connections, some connections
* can remain active on the peer end, until some (long) timeout period
* later. This tree disconnect forces the peer to clean up, since the
* connection will be going away.
*/
if ( cli->cnum != (uint16)-1 )
cli_tdis(cli);
cli_nt_session_close(cli);
cli_nt_netlogon_netsec_session_close(cli);

View File

@ -159,10 +159,15 @@ static int smbc_remove_cached_server(SMBCCTX * context, SMBCSRV * server)
*/
static int smbc_purge_cached(SMBCCTX * context)
{
struct smbc_server_cache * srv = NULL;
struct smbc_server_cache * srv;
struct smbc_server_cache * next;
int could_not_purge_all = 0;
for (srv=((struct smbc_server_cache *) context->server_cache);srv;srv=srv->next) {
for (srv = ((struct smbc_server_cache *) context->server_cache),
next = (srv ? srv->next :NULL);
srv;
srv = next, next = (srv ? srv->next : NULL)) {
if (smbc_remove_unused_server(context, srv->server)) {
/* could not be removed */
could_not_purge_all = 1;

View File

@ -156,18 +156,63 @@ decode_urlpart(char *segment, size_t sizeof_segment)
/*
* Function to parse a path and turn it into components
*
* We accept smb://[[[domain;]user[:password@]]server[/share[/path[/file]]]]
* 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:"), and expand on
* what he calls "context", herein called "options" to avoid conflict with the
* SMBCCTX context used throughout this library. We add the "mb" keyword
* which applies as follows:
*
* smb:// means show all the workgroups
* smb://name/ means, if name<1D> or name<1B> exists, list servers in workgroup,
* else, if name<20> exists, list all shares for server ...
*
* We accept:
* smb://[[[domain;]user[:password@]]server[/share[/path[/file]]]][?options]
*
* Meaning of URLs:
*
* smb:// show all workgroups known by the first master browser found
* smb://?mb=.any same as smb:// (i.e. without any options)
*
* smb://?mb=.all show all workgroups known by every master browser found.
* Why might you want this? In an "appliance" application
* where the workgroup/domain being used on the local network
* is not known ahead of time, but where one wanted to
* provide network services via samba, a unique workgroup
* could be used. However, when the appliance is first
* started, the local samba instance's master browser has not
* synchronized with the other master browser(s) on the
* network (and might not synchronize for 12 minutes) and
* therefore is not aware of the workgroup/ domain names
* available on the network. This option may be used to
* overcome the problem of a libsmbclient application
* arbitrarily selecting the local (still ignorant) master
* browser to obtain its list of workgroups/domains and
* getting back a practically emmpty list. By requesting
* the list of workgroups/domains from each found master
* browser on the local network, a complete list of
* workgroups/domains can be built.
*
* smb://?mb=name NOT YET IMPLEMENTED -- show all workgroups known by the
* master browser whose name is "name"
*
* 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.
*/
static const char *smbc_prefix = "smb:";
static int
smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share, char *path,
char *user, char *password) /* FIXME, lengths of strings */
smbc_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;
@ -176,10 +221,11 @@ smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share,
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);
/* clean_fname(s); causing problems ... */
/* see if it has the right prefix */
len = strlen(smbc_prefix);
if (strncmp(s,smbc_prefix,len) || (s[len] != '/' && s[len] != 0)) {
@ -192,11 +238,25 @@ smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share,
if (strncmp(p, "//", 2) && strncmp(p, "\\\\", 2)) {
DEBUG(1, ("Invalid path (does not begin with smb://"));
return -1;
}
p += 2; /* Skip the // or \\ */
p += 2; /* Skip the double slash */
/* See if any options were specified */
if (q = strrchr(p, '?')) {
/* 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;
@ -247,10 +307,10 @@ smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share,
}
if (username[0])
strncpy(user, username, sizeof(fstring)); /* FIXME, size and domain */
strncpy(user, username, user_len); /* FIXME, domain */
if (passwd[0])
strncpy(password, passwd, sizeof(fstring)); /* FIXME, size */
strncpy(password, passwd, password_len);
}
@ -268,16 +328,50 @@ smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share,
}
pstrcpy(path, p);
safe_strcpy(path, p, path_len - 1);
all_string_sub(path, "/", "\\", 0);
decoding:
decode_urlpart(path, sizeof(pstring));
decode_urlpart(server, sizeof(fstring));
decode_urlpart(share, sizeof(fstring));
decode_urlpart(user, sizeof(fstring));
decode_urlpart(password, sizeof(fstring));
decode_urlpart(path, path_len);
decode_urlpart(server, server_len);
decode_urlpart(share, share_len);
decode_urlpart(user, user_len);
decode_urlpart(password, password_len);
return 0;
}
/*
* Verify that the options specified in a URL are valid
*/
static int smbc_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;
/*
* For right now, we only support a very few options possibilities.
* No options are supported if server, share, or path are not empty.
* If all are empty, then we support the following two choices right
* now:
*
* mb=.any
* mb=.all
*/
if ((*server || *share || *path) && *options) {
/* Invalid: options provided with server, share, or path */
DEBUG(1, ("Found unsupported options (%s) with non-empty server, share, or path\n", options));
return -1;
}
if (strcmp(options, "mb=.any") != 0 &&
strcmp(options, "mb=.all") != 0) {
DEBUG(1, ("Found unsupported options (%s)\n", options));
return -1;
}
return 0;
}
@ -285,7 +379,6 @@ smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share,
/*
* Convert an SMB error into a UNIX error ...
*/
static int smbc_errno(SMBCCTX *context, struct cli_state *c)
{
int ret = cli_errno(c);
@ -469,6 +562,7 @@ SMBCSRV *smbc_server(SMBCCTX *context,
DEBUG(4,("smbc_server: server_n=[%s] server=[%s]\n", server_n, server));
#if 0 /* djl: obsolete code? neither group nor p is used beyond here */
if ((p=strchr_m(server_n,'#')) &&
(strcmp(p+1,"1D")==0 || strcmp(p+1,"01")==0)) {
@ -477,6 +571,7 @@ SMBCSRV *smbc_server(SMBCCTX *context,
*p = 0;
}
#endif
DEBUG(4,(" -> server_n=[%s] server=[%s]\n", server_n, server));
@ -503,7 +598,6 @@ SMBCSRV *smbc_server(SMBCCTX *context,
*/
c.port = 445;
if (!cli_connect(&c, server_n, &ip)) {
cli_shutdown(&c);
errno = ENETUNREACH;
return NULL;
}
@ -598,6 +692,7 @@ SMBCSRV *smbc_server(SMBCCTX *context,
DEBUG(2, ("Server connect ok: //%s/%s: %p\n",
server, share, srv));
DLIST_ADD(context->internal->_servers, srv);
return srv;
failed:
@ -648,17 +743,16 @@ SMBCSRV *smbc_attr_server(SMBCCTX *context,
password, 0,
Undefined, NULL);
if (! NT_STATUS_IS_OK(nt_status)) {
DEBUG(0,("cli_full_connection failed! (%s)\n",
DEBUG(1,("cli_full_connection failed! (%s)\n",
nt_errstr(nt_status)));
errno = ENOTSUP;
return NULL;
}
if (!cli_nt_session_open(ipc_cli, PI_LSARPC)) {
DEBUG(0, ("cli_nt_session_open fail! (%s)\n",
nt_errstr(nt_status)));
DEBUG(1, ("cli_nt_session_open fail!\n"));
errno = ENOTSUP;
free(ipc_cli);
cli_shutdown(ipc_cli);
return NULL;
}
@ -673,14 +767,14 @@ SMBCSRV *smbc_attr_server(SMBCCTX *context,
if (!NT_STATUS_IS_OK(nt_status)) {
errno = smbc_errno(context, ipc_cli);
free(ipc_cli);
cli_shutdown(ipc_cli);
return NULL;
}
ipc_srv = (SMBCSRV *)malloc(sizeof(*ipc_srv));
if (!ipc_srv) {
errno = ENOMEM;
free(ipc_cli);
cli_shutdown(ipc_cli);
return NULL;
}
@ -690,14 +784,23 @@ SMBCSRV *smbc_attr_server(SMBCCTX *context,
free(ipc_cli);
/* now add it to the cache (internal or external) */
errno = 0; /* let cache function set errno if it likes */
if (context->callbacks.add_cached_srv_fn(context, ipc_srv,
server,
"IPC$$",
workgroup,
username)) {
DEBUG(3, (" Failed to add server to cache\n"));
if (errno == 0) {
errno = ENOMEM;
}
cli_shutdown(&ipc_srv->cli);
free(ipc_srv);
return NULL;
}
DLIST_ADD(context->internal->_servers, ipc_srv);
}
return ipc_srv;
@ -730,7 +833,16 @@ static SMBCFILE *smbc_open_ctx(SMBCCTX *context, const char *fname, int flags, m
}
smbc_parse_path(context, fname, server, share, path, user, password); /* FIXME, check errors */
if (smbc_parse_path(context, fname,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
user, sizeof(user),
password, sizeof(password),
NULL, 0)) {
errno = EINVAL;
return NULL;
}
if (user[0] == (char)0) fstrcpy(user, context->user);
@ -1042,7 +1154,16 @@ static int smbc_unlink_ctx(SMBCCTX *context, const char *fname)
}
smbc_parse_path(context, fname, server, share, path, user, password); /* FIXME, check errors */
if (smbc_parse_path(context, fname,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
user, sizeof(user),
password, sizeof(password),
NULL, 0)) {
errno = EINVAL;
return -1;
}
if (user[0] == (char)0) fstrcpy(user, context->user);
@ -1141,11 +1262,23 @@ static int smbc_rename_ctx(SMBCCTX *ocontext, const char *oname,
DEBUG(4, ("smbc_rename(%s,%s)\n", oname, nname));
smbc_parse_path(ocontext, oname, server1, share1, path1, user1, password1);
smbc_parse_path(ocontext, oname,
server1, sizeof(server1),
share1, sizeof(share1),
path1, sizeof(path1),
user1, sizeof(user1),
password1, sizeof(password1),
NULL, 0);
if (user1[0] == (char)0) fstrcpy(user1, ocontext->user);
smbc_parse_path(ncontext, nname, server2, share2, path2, user2, password2);
smbc_parse_path(ncontext, nname,
server2, sizeof(server2),
share2, sizeof(share2),
path2, sizeof(path2),
user2, sizeof(user2),
password2, sizeof(password2),
NULL, 0);
if (user2[0] == (char)0) fstrcpy(user2, ncontext->user);
@ -1348,7 +1481,16 @@ static int smbc_stat_ctx(SMBCCTX *context, const char *fname, struct stat *st)
DEBUG(4, ("smbc_stat(%s)\n", fname));
smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
if (smbc_parse_path(context, fname,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
user, sizeof(user),
password, sizeof(password),
NULL, 0)) {
errno = EINVAL;
return -1;
}
if (user[0] == (char)0) fstrcpy(user, context->user);
@ -1360,27 +1502,6 @@ static int smbc_stat_ctx(SMBCCTX *context, const char *fname, struct stat *st)
return -1; /* errno set by smbc_server */
}
/* if (strncmp(srv->cli.dev, "IPC", 3) == 0) {
mode = aDIR | aRONLY;
}
else if (strncmp(srv->cli.dev, "LPT", 3) == 0) {
if (strcmp(path, "\\") == 0) {
mode = aDIR | aRONLY;
}
else {
mode = aRONLY;
smbc_stat_printjob(srv, path, &size, &m_time);
c_time = a_time = m_time;
}
else { */
if (!smbc_getatr(context, srv, path, &mode, &size,
&c_time, &a_time, &m_time, &ino)) {
@ -1462,16 +1583,7 @@ static int smbc_fstat_ctx(SMBCCTX *context, SMBCFILE *file, struct stat *st)
/*
* Routine to open a directory
*
* We want to allow:
*
* smb: which should list all the workgroups available
* smb:workgroup
* smb:workgroup//server
* smb://server
* smb://server/share
* smb://<IP-addr> which should list shares on server
* smb://<IP-addr>/share which should list files on share
* We accept the URL syntax explained in smbc_parse_path(), above.
*/
static void smbc_remove_dir(SMBCFILE *dir)
@ -1536,7 +1648,6 @@ static int add_dirent(SMBCFILE *dir, const char *name, const char *comment, uint
ZERO_STRUCTP(dir->dir_list);
dir->dir_end = dir->dir_next = dir->dir_list;
}
else {
@ -1552,7 +1663,6 @@ static int add_dirent(SMBCFILE *dir, const char *name, const char *comment, uint
ZERO_STRUCTP(dir->dir_end->next);
dir->dir_end = dir->dir_end->next;
}
dir->dir_end->next = NULL;
@ -1575,6 +1685,46 @@ static int add_dirent(SMBCFILE *dir, const char *name, const char *comment, uint
}
static void
list_unique_wg_fn(const char *name, uint32 type, const char *comment, void *state)
{
SMBCFILE *dir = (SMBCFILE *)state;
struct smbc_dir_list *dir_list;
struct smbc_dirent *dirent;
int dirent_type;
int remove = 0;
dirent_type = dir->dir_type;
if (add_dirent(dir, name, comment, dirent_type) < 0) {
/* An error occurred, what do we do? */
/* FIXME: Add some code here */
}
/* Point to the one just added */
dirent = dir->dir_end->dirent;
/* See if this was a duplicate */
for (dir_list = dir->dir_list;
dir_list != dir->dir_end;
dir_list = dir_list->next) {
if (! remove &&
strcmp(dir_list->dirent->name, dirent->name) == 0) {
/* Duplicate. End end of list need to be removed. */
remove = 1;
}
if (remove && dir_list->next == dir->dir_end) {
/* Found the end of the list. Remove it. */
dir->dir_end = dir_list;
free(dir_list->next);
dir_list->next = NULL;
break;
}
}
}
static void
list_fn(const char *name, uint32 type, const char *comment, void *state)
{
@ -1615,7 +1765,6 @@ list_fn(const char *name, uint32 type, const char *comment, void *state)
/* FIXME: Add some code here */
}
}
static void
@ -1635,7 +1784,7 @@ dir_list_fn(file_info *finfo, const char *mask, void *state)
static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
{
fstring server, share, user, password;
fstring server, share, user, password, options;
pstring workgroup;
pstring path;
SMBCSRV *srv = NULL;
@ -1656,13 +1805,26 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
return NULL;
}
if (smbc_parse_path(context, fname, server, share, path, user, password)) {
if (smbc_parse_path(context, fname,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
user, sizeof(path),
password, sizeof(password),
options, sizeof(options))) {
DEBUG(4, ("no valid path\n"));
errno = EINVAL;
return NULL;
}
DEBUG(4, ("parsed path: fname='%s' server='%s' share='%s' path='%s'\n", fname, server, share, path));
DEBUG(4, ("parsed path: fname='%s' server='%s' share='%s' path='%s' options='%s'\n", fname, server, share, path, options));
/* Ensure the options are valid */
if (smbc_check_options(server, share, path, options)) {
DEBUG(4, ("unacceptable options (%s)\n", options));
errno = EINVAL;
return NULL;
}
if (user[0] == (char)0) fstrcpy(user, context->user);
@ -1686,7 +1848,8 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
dir->file = False;
dir->dir_list = dir->dir_next = dir->dir_end = NULL;
if (server[0] == (char)0) {
if (server[0] == (char)0 &&
(! *options || strcmp(options, "mb=.any") == 0)) {
struct in_addr server_ip;
if (share[0] != (char)0 || path[0] != (char)0) {
@ -1698,9 +1861,11 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
return NULL;
}
/* We have server and share and path empty ... so list the workgroups */
/* first try to get the LMB for our workgroup, and if that fails, */
/* try the DMB */
/*
* We have server and share and path empty ... so list the
* workgroups first try to get the LMB for our workgroup, and
* if that fails, try the DMB
*/
pstrcpy(workgroup, lp_workgroup());
@ -1726,7 +1891,21 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
cli_shutdown(cli);
} else {
if (!name_status_find("*", 0, 0, server_ip, server)) {
/*
* Do a name status query to find out the name of the
* master browser. We use <01><02>__MSBROWSE__<02>#01 if
* *#00 fails because a domain master browser will not
* respond to a wildcard query (or, at least, an NT4
* server acting as the domain master browser will not).
*
* We might be able to use ONLY the query on MSBROWSE, but
* that's not yet been tested with all Windows versions,
* so until it is, leave the original wildcard query as
* the first choice and fall back to MSBROWSE if the
* wildcard query fails.
*/
if (!name_status_find("*", 0, 0x1d, server_ip, server) &&
!name_status_find(MSBROWSE, 1, 0x1d, server_ip, server)) {
errno = ENOENT;
return NULL;
}
@ -1735,7 +1914,8 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
DEBUG(4, ("using workgroup %s %s\n", workgroup, server));
/*
* Get a connection to IPC$ on the server if we do not already have one
* Get a connection to IPC$ on the server if we do not already
* have one
*/
srv = smbc_server(context, server, "IPC$", workgroup, user, password);
@ -1756,6 +1936,94 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
if (!cli_NetServerEnum(&srv->cli, workgroup, SV_TYPE_DOMAIN_ENUM, list_fn,
(void *)dir)) {
DEBUG(1, ("Could not enumerate domains using '%s'\n", workgroup));
if (dir) {
SAFE_FREE(dir->fname);
SAFE_FREE(dir);
}
errno = cli_errno(&srv->cli);
return NULL;
}
} else if (server[0] == (char)0 &&
(! *options || strcmp(options, "mb=.all") == 0)) {
int i;
int count;
struct ip_service *ip_list;
struct ip_service server_addr;
struct user_auth_info u_info;
struct cli_state *cli;
if (share[0] != (char)0 || path[0] != (char)0) {
errno = EINVAL;
if (dir) {
SAFE_FREE(dir->fname);
SAFE_FREE(dir);
}
return NULL;
}
pstrcpy(u_info.username, user);
pstrcpy(u_info.password, password);
/*
* We have server and share and path empty but options
* requesting that we scan all master browsers for their list
* of workgroups/domains. This implies that we must first try
* broadcast queries to find all master browsers, and if that
* doesn't work, then try our other methods which return only
* a single master browser.
*/
if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
if (!find_master_ip(workgroup, &server_addr.ip)) {
errno = ENOENT;
return NULL;
}
ip_list = &server_addr;
count = 1;
}
for (i = 0; i < count; i++) {
DEBUG(99, ("Found master browser %s\n", inet_ntoa(ip_list[i].ip)));
cli = get_ipc_connect_master_ip(&ip_list[i], workgroup, &u_info);
fstrcpy(server, cli->desthost);
cli_shutdown(cli);
DEBUG(4, ("using workgroup %s %s\n", workgroup, server));
/*
* For each returned master browser IP address, get a
* connection to IPC$ on the server if we do not
* already have one, and determine the
* workgroups/domains that it knows about.
*/
srv = smbc_server(context, server,
"IPC$", workgroup, user, password);
if (!srv) {
if (dir) {
SAFE_FREE(dir->fname);
SAFE_FREE(dir);
}
return NULL;
}
dir->srv = srv;
dir->dir_type = SMBC_WORKGROUP;
/* Now, list the stuff ... */
if (!cli_NetServerEnum(&srv->cli, workgroup, SV_TYPE_DOMAIN_ENUM, list_unique_wg_fn,
(void *)dir)) {
if (dir) {
SAFE_FREE(dir->fname);
SAFE_FREE(dir);
@ -1766,8 +2034,11 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
}
}
else { /* Server not an empty string ... Check the rest and see what gives */
} else {
/*
* Server not an empty string ... Check the rest and see what
* gives
*/
if (share[0] == (char)0) {
if (path[0] != (char)0) { /* Should not have empty share with path */
@ -1796,7 +2067,7 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
*/
if (!name_status_find("*", 0, 0, rem_ip, buserver)) {
if (!name_status_find(server, 0, 0, rem_ip, buserver)) {
DEBUG(0, ("Could not get name of local/domain master browser for server %s\n", server));
errno = EPERM; /* FIXME, is this correct */
@ -1835,7 +2106,6 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname)
return NULL;
}
}
else {
@ -1962,7 +2232,6 @@ static int smbc_closedir_ctx(SMBCCTX *context, SMBCFILE *dir)
SAFE_FREE(dir->fname);
SAFE_FREE(dir); /* Free the space too */
}
return 0;
@ -1983,6 +2252,7 @@ struct smbc_dirent *smbc_readdir_ctx(SMBCCTX *context, SMBCFILE *dir)
!context->internal->_initialized) {
errno = EINVAL;
DEBUG(0, ("Invalid context in smbc_readdir_ctx()\n"));
return NULL;
}
@ -1990,6 +2260,7 @@ struct smbc_dirent *smbc_readdir_ctx(SMBCCTX *context, SMBCFILE *dir)
if (!dir || !DLIST_CONTAINS(context->internal->_files, dir)) {
errno = EBADF;
DEBUG(0, ("Invalid dir in smbc_readdir_ctx()\n"));
return NULL;
}
@ -1997,16 +2268,17 @@ struct smbc_dirent *smbc_readdir_ctx(SMBCCTX *context, SMBCFILE *dir)
if (dir->file != False) { /* FIXME, should be dir, perhaps */
errno = ENOTDIR;
DEBUG(0, ("Found file vs directory in smbc_readdir_ctx()\n"));
return NULL;
}
if (!dir->dir_next)
if (!dir->dir_next) {
return NULL;
}
else {
dirent = dir->dir_next->dirent;
if (!dirent) {
errno = ENOENT;
@ -2142,7 +2414,16 @@ static int smbc_mkdir_ctx(SMBCCTX *context, const char *fname, mode_t mode)
DEBUG(4, ("smbc_mkdir(%s)\n", fname));
smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
if (smbc_parse_path(context, fname,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
user, sizeof(user),
password, sizeof(password),
NULL, 0)) {
errno = EINVAL;
return -1;
}
if (user[0] == (char)0) fstrcpy(user, context->user);
@ -2229,7 +2510,17 @@ static int smbc_rmdir_ctx(SMBCCTX *context, const char *fname)
DEBUG(4, ("smbc_rmdir(%s)\n", fname));
smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
if (smbc_parse_path(context, fname,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
user, sizeof(user),
password, sizeof(password),
NULL, 0))
{
errno = EINVAL;
return -1;
}
if (user[0] == (char)0) fstrcpy(user, context->user);
@ -2466,7 +2757,16 @@ int smbc_chmod_ctx(SMBCCTX *context, const char *fname, mode_t newmode)
DEBUG(4, ("smbc_chmod(%s, 0%3o)\n", fname, newmode));
smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
if (smbc_parse_path(context, fname,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
user, sizeof(user),
password, sizeof(password),
NULL, 0)) {
errno = EINVAL;
return -1;
}
if (user[0] == (char)0) fstrcpy(user, context->user);
@ -2518,7 +2818,16 @@ int smbc_utimes_ctx(SMBCCTX *context, const char *fname, struct timeval *tbuf)
DEBUG(4, ("smbc_utimes(%s, [%s])\n", fname, ctime(&t)));
smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
if (smbc_parse_path(context, fname,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
user, sizeof(user),
password, sizeof(password),
NULL, 0)) {
errno = EINVAL;
return -1;
}
if (user[0] == (char)0) fstrcpy(user, context->user);
@ -3353,7 +3662,16 @@ int smbc_setxattr_ctx(SMBCCTX *context,
DEBUG(4, ("smbc_setxattr(%s, %s, %.*s)\n",
fname, name, (int) size, (char *) value));
smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
if (smbc_parse_path(context, fname,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
user, sizeof(user),
password, sizeof(password),
NULL, 0)) {
errno = EINVAL;
return -1;
}
if (user[0] == (char)0) fstrcpy(user, context->user);
@ -3485,7 +3803,16 @@ int smbc_getxattr_ctx(SMBCCTX *context,
DEBUG(4, ("smbc_getxattr(%s, %s)\n", fname, name));
smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
if (smbc_parse_path(context, fname,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
user, sizeof(user),
password, sizeof(password),
NULL, 0)) {
errno = EINVAL;
return -1;
}
if (user[0] == (char)0) fstrcpy(user, context->user);
@ -3568,7 +3895,16 @@ int smbc_removexattr_ctx(SMBCCTX *context,
DEBUG(4, ("smbc_removexattr(%s, %s)\n", fname, name));
smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
if (smbc_parse_path(context, fname,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
user, sizeof(user),
password, sizeof(password),
NULL, 0)) {
errno = EINVAL;
return -1;
}
if (user[0] == (char)0) fstrcpy(user, context->user);
@ -3700,7 +4036,16 @@ static SMBCFILE *smbc_open_print_job_ctx(SMBCCTX *context, const char *fname)
DEBUG(4, ("smbc_open_print_job_ctx(%s)\n", fname));
smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
if (smbc_parse_path(context, fname,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
user, sizeof(user),
password, sizeof(password),
NULL, 0)) {
errno = EINVAL;
return NULL;
}
/* What if the path is empty, or the file exists? */
@ -3814,7 +4159,16 @@ static int smbc_list_print_jobs_ctx(SMBCCTX *context, const char *fname, smbc_li
DEBUG(4, ("smbc_list_print_jobs(%s)\n", fname));
smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
if (smbc_parse_path(context, fname,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
user, sizeof(user),
password, sizeof(password),
NULL, 0)) {
errno = EINVAL;
return -1;
}
if (user[0] == (char)0) fstrcpy(user, context->user);
@ -3867,7 +4221,16 @@ static int smbc_unlink_print_job_ctx(SMBCCTX *context, const char *fname, int id
DEBUG(4, ("smbc_unlink_print_job(%s)\n", fname));
smbc_parse_path(context, fname, server, share, path, user, password); /*FIXME, errors*/
if (smbc_parse_path(context, fname,
server, sizeof(server),
share, sizeof(share),
path, sizeof(path),
user, sizeof(user),
password, sizeof(password),
NULL, 0)) {
errno = EINVAL;
return -1;
}
if (user[0] == (char)0) fstrcpy(user, context->user);
@ -3989,13 +4352,17 @@ int smbc_free_context(SMBCCTX * context, int shutdown_ctx)
/* First try to remove the servers the nice way. */
if (context->callbacks.purge_cached_fn(context)) {
SMBCSRV * s;
SMBCSRV * next;
DEBUG(1, ("Could not purge all servers, Nice way shutdown failed.\n"));
s = context->internal->_servers;
while (s) {
DEBUG(1, ("Forced shutdown: %p (fd=%d)\n", s, s->cli.fd));
cli_shutdown(&s->cli);
context->callbacks.remove_cached_srv_fn(context, s);
next = s->next;
DLIST_REMOVE(context->internal->_servers, s);
SAFE_FREE(s);
s = s->next;
s = next;
}
context->internal->_servers = NULL;
}