From 257b7b09298f7cb983b2f31b87fc5e46e0f62f0c Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Thu, 28 Feb 2008 11:23:20 -0500 Subject: Initial revamp of the libsmbclient interface. The libsmbclient interface has suffered from difficulty of improvement and feature enrichment without causing ABI breakage. Although there were a number of issues, the primary ones were: (a) the user of the library would manually manipulate the context structure members, meaning that nothing in the context structure could change other than adding stuff at the end; (b) there were three methods of setting options: setting bits in a flags field within the context structure, setting explicit options variables within an options structure in the context structure, and by calling the smbc_option_set() function; (c) the authentication callback did not traditionally provide enough information to the callee which required adding an option for a callback with a different signature, and now there are requests for even more information at the callback, requiring yet a third signature and option to set it (if we implement that feature). This commit provides a reorganization of the code which fixes (a) and (b). The context structure is now entirely opaque, and there are setter and getter functions for manipulating it. This makes maintaining ABI consistency much, much easier. Additionally, the options setting/getting has been unified into a single mechanism using smbc_option_set() and smbc_option_get(). Yet to be completed is a refactoring of the authentication callback (c). The test programs in examples/libsmbclient have been modified (if necessary; some applications require no changes at all) for the new API and a few have been minimally tested. Derrell (This used to be commit d4b4bae8ded824d06ad5ab0e219f71187ee5c771) --- source3/libsmb/libsmb_dir.c | 1928 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1928 insertions(+) create mode 100644 source3/libsmb/libsmb_dir.c (limited to 'source3/libsmb/libsmb_dir.c') diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c new file mode 100644 index 0000000000..9cb3351433 --- /dev/null +++ b/source3/libsmb/libsmb_dir.c @@ -0,0 +1,1928 @@ +/* + 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-2008 + Copyright (C) Jeremy Allison 2007, 2008 + + 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 3 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, see . +*/ + +#include "includes.h" +#include "libsmbclient.h" +#include "libsmb_internal.h" + + +/* + * Routine to open a directory + * We accept the URL syntax explained in SMBC_parse_path(), above. + */ + +static void +remove_dir(SMBCFILE *dir) +{ + struct smbc_dir_list *d,*f; + + d = dir->dir_list; + while (d) { + + f = d; d = d->next; + + SAFE_FREE(f->dirent); + SAFE_FREE(f); + + } + + dir->dir_list = dir->dir_end = dir->dir_next = NULL; + +} + +static int +add_dirent(SMBCFILE *dir, + const char *name, + const char *comment, + uint32 type) +{ + struct smbc_dirent *dirent; + int size; + int name_length = (name == NULL ? 0 : strlen(name)); + int comment_len = (comment == NULL ? 0 : strlen(comment)); + + /* + * Allocate space for the dirent, which must be increased by the + * size of the name and the comment and 1 each for the null terminator. + */ + + size = sizeof(struct smbc_dirent) + name_length + comment_len + 2; + + dirent = (struct smbc_dirent *)SMB_MALLOC(size); + + if (!dirent) { + + dir->dir_error = ENOMEM; + return -1; + + } + + ZERO_STRUCTP(dirent); + + if (dir->dir_list == NULL) { + + dir->dir_list = SMB_MALLOC_P(struct smbc_dir_list); + if (!dir->dir_list) { + + SAFE_FREE(dirent); + dir->dir_error = ENOMEM; + return -1; + + } + ZERO_STRUCTP(dir->dir_list); + + dir->dir_end = dir->dir_next = dir->dir_list; + } + else { + + dir->dir_end->next = SMB_MALLOC_P(struct smbc_dir_list); + + if (!dir->dir_end->next) { + + SAFE_FREE(dirent); + dir->dir_error = ENOMEM; + return -1; + + } + ZERO_STRUCTP(dir->dir_end->next); + + dir->dir_end = dir->dir_end->next; + } + + dir->dir_end->next = NULL; + dir->dir_end->dirent = dirent; + + dirent->smbc_type = type; + dirent->namelen = name_length; + dirent->commentlen = comment_len; + dirent->dirlen = size; + + /* + * dirent->namelen + 1 includes the null (no null termination needed) + * Ditto for dirent->commentlen. + * The space for the two null bytes was allocated. + */ + strncpy(dirent->name, (name?name:""), dirent->namelen + 1); + dirent->comment = (char *)(&dirent->name + dirent->namelen + 1); + strncpy(dirent->comment, (comment?comment:""), dirent->commentlen + 1); + + return 0; + +} + +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 do_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 (! do_remove && + strcmp(dir_list->dirent->name, dirent->name) == 0) { + /* Duplicate. End end of list need to be removed. */ + do_remove = 1; + } + + if (do_remove && dir_list->next == dir->dir_end) { + /* Found the end of the list. Remove it. */ + dir->dir_end = dir_list; + free(dir_list->next); + free(dirent); + dir_list->next = NULL; + break; + } + } +} + +static void +list_fn(const char *name, + uint32 type, + const char *comment, + void *state) +{ + SMBCFILE *dir = (SMBCFILE *)state; + int dirent_type; + + /* + * We need to process the type a little ... + * + * Disk share = 0x00000000 + * Print share = 0x00000001 + * Comms share = 0x00000002 (obsolete?) + * IPC$ share = 0x00000003 + * + * administrative shares: + * ADMIN$, IPC$, C$, D$, E$ ... are type |= 0x80000000 + */ + + if (dir->dir_type == SMBC_FILE_SHARE) { + switch (type) { + case 0 | 0x80000000: + case 0: + dirent_type = SMBC_FILE_SHARE; + break; + + case 1: + dirent_type = SMBC_PRINTER_SHARE; + break; + + case 2: + dirent_type = SMBC_COMMS_SHARE; + break; + + case 3 | 0x80000000: + case 3: + dirent_type = SMBC_IPC_SHARE; + break; + + default: + dirent_type = SMBC_FILE_SHARE; /* FIXME, error? */ + break; + } + } + else { + 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 */ + + } +} + +static void +dir_list_fn(const char *mnt, + file_info *finfo, + const char *mask, + void *state) +{ + + if (add_dirent((SMBCFILE *)state, finfo->name, "", + (finfo->mode&aDIR?SMBC_DIR:SMBC_FILE)) < 0) { + + /* Handle an error ... */ + + /* FIXME: Add some code ... */ + + } + +} + +static int +net_share_enum_rpc(struct cli_state *cli, + void (*fn)(const char *name, + uint32 type, + const char *comment, + void *state), + void *state) +{ + int i; + WERROR result; + ENUM_HND enum_hnd; + uint32 info_level = 1; + uint32 preferred_len = 0xffffffff; + uint32 type; + SRV_SHARE_INFO_CTR ctr; + fstring name = ""; + fstring comment = ""; + struct rpc_pipe_client *pipe_hnd; + NTSTATUS nt_status; + + /* Open the server service pipe */ + pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &nt_status); + if (!pipe_hnd) { + DEBUG(1, ("net_share_enum_rpc pipe open fail!\n")); + return -1; + } + + /* Issue the NetShareEnum RPC call and retrieve the response */ + init_enum_hnd(&enum_hnd, 0); + result = rpccli_srvsvc_net_share_enum(pipe_hnd, + talloc_tos(), + info_level, + &ctr, + preferred_len, + &enum_hnd); + + /* Was it successful? */ + if (!W_ERROR_IS_OK(result) || ctr.num_entries == 0) { + /* Nope. Go clean up. */ + goto done; + } + + /* For each returned entry... */ + for (i = 0; i < ctr.num_entries; i++) { + + /* pull out the share name */ + rpcstr_pull_unistr2_fstring( + name, &ctr.share.info1[i].info_1_str.uni_netname); + + /* pull out the share's comment */ + rpcstr_pull_unistr2_fstring( + comment, &ctr.share.info1[i].info_1_str.uni_remark); + + /* Get the type value */ + type = ctr.share.info1[i].info_1.type; + + /* Add this share to the list */ + (*fn)(name, type, comment, state); + } + +done: + /* Close the server service pipe */ + cli_rpc_pipe_close(pipe_hnd); + + /* Tell 'em if it worked */ + return W_ERROR_IS_OK(result) ? 0 : -1; +} + + +/* + * Verify that the options specified in a URL are valid + */ +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; + + /* Currently, we don't support any options. */ + return -1; +} + + +SMBCFILE * +SMBC_opendir_ctx(SMBCCTX *context, + const char *fname) +{ + int saved_errno; + char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *options = NULL; + char *workgroup = NULL; + char *path = NULL; + uint16 mode; + char *p = NULL; + SMBCSRV *srv = NULL; + SMBCFILE *dir = NULL; + struct sockaddr_storage rem_ss; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + DEBUG(4, ("no valid context\n")); + errno = EINVAL + 8192; + TALLOC_FREE(frame); + return NULL; + + } + + if (!fname) { + DEBUG(4, ("no valid fname\n")); + errno = EINVAL + 8193; + TALLOC_FREE(frame); + return NULL; + } + + if (SMBC_parse_path(frame, + context, + fname, + &workgroup, + &server, + &share, + &path, + &user, + &password, + &options)) { + DEBUG(4, ("no valid path\n")); + errno = EINVAL + 8194; + TALLOC_FREE(frame); + return NULL; + } + + 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 + 8195; + TALLOC_FREE(frame); + return NULL; + } + + if (!user || user[0] == (char)0) { + user = talloc_strdup(frame, context->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + return NULL; + } + } + + dir = SMB_MALLOC_P(SMBCFILE); + + if (!dir) { + errno = ENOMEM; + TALLOC_FREE(frame); + return NULL; + } + + ZERO_STRUCTP(dir); + + dir->cli_fd = 0; + dir->fname = SMB_STRDUP(fname); + dir->srv = NULL; + dir->offset = 0; + dir->file = False; + dir->dir_list = dir->dir_next = dir->dir_end = NULL; + + if (server[0] == (char)0) { + + int i; + int count; + int max_lmb_count; + struct ip_service *ip_list; + struct ip_service server_addr; + struct user_auth_info u_info; + + if (share[0] != (char)0 || path[0] != (char)0) { + + errno = EINVAL + 8196; + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + } + + /* Determine how many local master browsers to query */ + max_lmb_count = (context->browse_max_lmb_count == 0 + ? INT_MAX + : context->browse_max_lmb_count); + + memset(&u_info, '\0', sizeof(u_info)); + u_info.username = talloc_strdup(frame,user); + u_info.password = talloc_strdup(frame,password); + if (!u_info.username || !u_info.password) { + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + } + + /* + * 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. + */ + + ip_list = NULL; + if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list, + &count))) + { + + SAFE_FREE(ip_list); + + if (!find_master_ip(workgroup, &server_addr.ss)) { + + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + errno = ENOENT; + TALLOC_FREE(frame); + return NULL; + } + + ip_list = (struct ip_service *)memdup( + &server_addr, sizeof(server_addr)); + if (ip_list == NULL) { + errno = ENOMEM; + TALLOC_FREE(frame); + return NULL; + } + count = 1; + } + + for (i = 0; i < count && i < max_lmb_count; i++) { + char addr[INET6_ADDRSTRLEN]; + char *wg_ptr = NULL; + struct cli_state *cli = NULL; + + print_sockaddr(addr, sizeof(addr), &ip_list[i].ss); + DEBUG(99, ("Found master browser %d of %d: %s\n", + i+1, MAX(count, max_lmb_count), + addr)); + + cli = get_ipc_connect_master_ip(talloc_tos(), + &ip_list[i], + &u_info, + &wg_ptr); + /* cli == NULL is the master browser refused to talk or + could not be found */ + if (!cli) { + continue; + } + + workgroup = talloc_strdup(frame, wg_ptr); + server = talloc_strdup(frame, cli->desthost); + + cli_shutdown(cli); + + if (!workgroup || !server) { + errno = ENOMEM; + TALLOC_FREE(frame); + return NULL; + } + + 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(frame, context, True, server, "IPC$", + &workgroup, &user, &password); + if (!srv) { + continue; + } + + 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)) { + continue; + } + } + + SAFE_FREE(ip_list); + } else { + /* + * Server not an empty string ... Check the rest and see what + * gives + */ + if (*share == '\0') { + if (*path != '\0') { + + /* Should not have empty share with path */ + errno = EINVAL + 8197; + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + + } + + /* + * We don't know if is really a server name + * or is a workgroup/domain name. If we already have + * a server structure for it, we'll use it. + * Otherwise, check to see if <1D>, + * <1B>, or <20> translates. We check + * to see if is an IP address first. + */ + + /* + * See if we have an existing server. Do not + * establish a connection if one does not already + * exist. + */ + srv = SMBC_server(frame, context, False, server, "IPC$", + &workgroup, &user, &password); + + /* + * If no existing server and not an IP addr, look for + * LMB or DMB + */ + if (!srv && + !is_ipaddress(server) && + (resolve_name(server, &rem_ss, 0x1d) || /* LMB */ + resolve_name(server, &rem_ss, 0x1b) )) { /* DMB */ + + fstring buserver; + + dir->dir_type = SMBC_SERVER; + + /* + * Get the backup list ... + */ + if (!name_status_find(server, 0, 0, + &rem_ss, buserver)) { + + DEBUG(0, ("Could not get name of " + "local/domain master browser " + "for server %s\n", server)); + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + errno = EPERM; + TALLOC_FREE(frame); + return NULL; + + } + + /* + * Get a connection to IPC$ on the server if + * we do not already have one + */ + srv = SMBC_server(frame, context, True, + buserver, "IPC$", + &workgroup, &user, &password); + if (!srv) { + DEBUG(0, ("got no contact to IPC$\n")); + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + + } + + dir->srv = srv; + + /* Now, list the servers ... */ + if (!cli_NetServerEnum(srv->cli, server, + 0x0000FFFE, list_fn, + (void *)dir)) { + + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + } + } else if (srv || + (resolve_name(server, &rem_ss, 0x20))) { + + /* If we hadn't found the server, get one now */ + if (!srv) { + srv = SMBC_server(frame, context, True, + server, "IPC$", + &workgroup, + &user, &password); + } + + if (!srv) { + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + + } + + dir->dir_type = SMBC_FILE_SHARE; + dir->srv = srv; + + /* List the shares ... */ + + if (net_share_enum_rpc( + srv->cli, + list_fn, + (void *) dir) < 0 && + cli_RNetShareEnum( + srv->cli, + list_fn, + (void *)dir) < 0) { + + errno = cli_errno(srv->cli); + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + + } + } else { + /* Neither the workgroup nor server exists */ + errno = ECONNREFUSED; + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + } + + } + else { + /* + * The server and share are specified ... work from + * there ... + */ + char *targetpath; + struct cli_state *targetcli; + + /* We connect to the server and list the directory */ + dir->dir_type = SMBC_FILE_SHARE; + + srv = SMBC_server(frame, context, True, server, share, + &workgroup, &user, &password); + + if (!srv) { + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + } + + dir->srv = srv; + + /* Now, list the files ... */ + + p = path + strlen(path); + path = talloc_asprintf_append(path, "\\*"); + if (!path) { + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + } + + if (!cli_resolve_path(frame, "", srv->cli, path, + &targetcli, &targetpath)) { + d_printf("Could not resolve %s\n", path); + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + TALLOC_FREE(frame); + return NULL; + } + + if (cli_list(targetcli, targetpath, + aDIR | aSYSTEM | aHIDDEN, + dir_list_fn, (void *)dir) < 0) { + + if (dir) { + SAFE_FREE(dir->fname); + SAFE_FREE(dir); + } + saved_errno = SMBC_errno(context, targetcli); + + if (saved_errno == EINVAL) { + /* + * See if they asked to opendir something + * other than a directory. If so, the + * converted error value we got would have + * been EINVAL rather than ENOTDIR. + */ + *p = '\0'; /* restore original path */ + + if (SMBC_getatr(context, srv, path, + &mode, NULL, + NULL, NULL, NULL, NULL, + NULL) && + ! IS_DOS_DIR(mode)) { + + /* It is. Correct the error value */ + saved_errno = ENOTDIR; + } + } + + /* + * If there was an error and the server is no + * good any more... + */ + if (cli_is_error(targetcli) && + (context->server.check_server_fn)(context, srv)) { + + /* ... then remove it. */ + if ((context->server.remove_unused_server_fn)(context, + srv)) { + /* + * We could not remove the + * server completely, remove + * it from the cache so we + * will not get it again. It + * will be removed when the + * last file/dir is closed. + */ + (context->cache.remove_cached_server_fn)(context, srv); + } + } + + errno = saved_errno; + TALLOC_FREE(frame); + return NULL; + } + } + + } + + DLIST_ADD(context->files, dir); + TALLOC_FREE(frame); + return dir; + +} + +/* + * Routine to close a directory + */ + +int +SMBC_closedir_ctx(SMBCCTX *context, + SMBCFILE *dir) +{ + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!dir || !SMBC_dlist_contains(context->files, dir)) { + errno = EBADF; + TALLOC_FREE(frame); + return -1; + } + + remove_dir(dir); /* Clean it up */ + + DLIST_REMOVE(context->files, dir); + + if (dir) { + + SAFE_FREE(dir->fname); + SAFE_FREE(dir); /* Free the space too */ + } + + TALLOC_FREE(frame); + return 0; + +} + +static void +smbc_readdir_internal(SMBCCTX * context, + struct smbc_dirent *dest, + struct smbc_dirent *src, + int max_namebuf_len) +{ + if (context->urlencode_readdir_entries) { + + /* url-encode the name. get back remaining buffer space */ + max_namebuf_len = + SMBC_urlencode(dest->name, src->name, max_namebuf_len); + + /* We now know the name length */ + dest->namelen = strlen(dest->name); + + /* Save the pointer to the beginning of the comment */ + dest->comment = dest->name + dest->namelen + 1; + + /* Copy the comment */ + strncpy(dest->comment, src->comment, max_namebuf_len - 1); + dest->comment[max_namebuf_len - 1] = '\0'; + + /* Save other fields */ + dest->smbc_type = src->smbc_type; + dest->commentlen = strlen(dest->comment); + dest->dirlen = ((dest->comment + dest->commentlen + 1) - + (char *) dest); + } else { + + /* No encoding. Just copy the entry as is. */ + memcpy(dest, src, src->dirlen); + dest->comment = (char *)(&dest->name + src->namelen + 1); + } + +} + +/* + * Routine to get a directory entry + */ + +struct smbc_dirent * +SMBC_readdir_ctx(SMBCCTX *context, + SMBCFILE *dir) +{ + int maxlen; + struct smbc_dirent *dirp, *dirent; + TALLOC_CTX *frame = talloc_stackframe(); + + /* Check that all is ok first ... */ + + if (!context || !context->initialized) { + + errno = EINVAL; + DEBUG(0, ("Invalid context in SMBC_readdir_ctx()\n")); + TALLOC_FREE(frame); + return NULL; + + } + + if (!dir || !SMBC_dlist_contains(context->files, dir)) { + + errno = EBADF; + DEBUG(0, ("Invalid dir in SMBC_readdir_ctx()\n")); + TALLOC_FREE(frame); + return NULL; + + } + + if (dir->file != False) { /* FIXME, should be dir, perhaps */ + + errno = ENOTDIR; + DEBUG(0, ("Found file vs directory in SMBC_readdir_ctx()\n")); + TALLOC_FREE(frame); + return NULL; + + } + + if (!dir->dir_next) { + TALLOC_FREE(frame); + return NULL; + } + + dirent = dir->dir_next->dirent; + if (!dirent) { + + errno = ENOENT; + TALLOC_FREE(frame); + return NULL; + + } + + dirp = (struct smbc_dirent *)context->dirent; + maxlen = (sizeof(context->dirent) - + sizeof(struct smbc_dirent)); + + smbc_readdir_internal(context, dirp, dirent, maxlen); + + dir->dir_next = dir->dir_next->next; + + TALLOC_FREE(frame); + return dirp; +} + +/* + * Routine to get directory entries + */ + +int +SMBC_getdents_ctx(SMBCCTX *context, + SMBCFILE *dir, + struct smbc_dirent *dirp, + int count) +{ + int rem = count; + int reqd; + int maxlen; + char *ndir = (char *)dirp; + struct smbc_dir_list *dirlist; + TALLOC_CTX *frame = talloc_stackframe(); + + /* Check that all is ok first ... */ + + if (!context || !context->initialized) { + + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + + } + + if (!dir || !SMBC_dlist_contains(context->files, dir)) { + + errno = EBADF; + TALLOC_FREE(frame); + return -1; + + } + + if (dir->file != False) { /* FIXME, should be dir, perhaps */ + + errno = ENOTDIR; + TALLOC_FREE(frame); + return -1; + + } + + /* + * Now, retrieve the number of entries that will fit in what was passed + * We have to figure out if the info is in the list, or we need to + * send a request to the server to get the info. + */ + + while ((dirlist = dir->dir_next)) { + struct smbc_dirent *dirent; + + if (!dirlist->dirent) { + + errno = ENOENT; /* Bad error */ + TALLOC_FREE(frame); + return -1; + + } + + /* Do urlencoding of next entry, if so selected */ + dirent = (struct smbc_dirent *)context->dirent; + maxlen = (sizeof(context->dirent) - + sizeof(struct smbc_dirent)); + smbc_readdir_internal(context, dirent, dirlist->dirent, maxlen); + + reqd = dirent->dirlen; + + if (rem < reqd) { + + if (rem < count) { /* We managed to copy something */ + + errno = 0; + TALLOC_FREE(frame); + return count - rem; + + } + else { /* Nothing copied ... */ + + errno = EINVAL; /* Not enough space ... */ + TALLOC_FREE(frame); + return -1; + + } + + } + + memcpy(ndir, dirent, reqd); /* Copy the data in ... */ + + ((struct smbc_dirent *)ndir)->comment = + (char *)(&((struct smbc_dirent *)ndir)->name + + dirent->namelen + + 1); + + ndir += reqd; + + rem -= reqd; + + dir->dir_next = dirlist = dirlist -> next; + } + + TALLOC_FREE(frame); + + if (rem == count) + return 0; + else + return count - rem; + +} + +/* + * Routine to create a directory ... + */ + +int +SMBC_mkdir_ctx(SMBCCTX *context, + const char *fname, + mode_t mode) +{ + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!fname) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + DEBUG(4, ("smbc_mkdir(%s)\n", fname)); + + if (SMBC_parse_path(frame, + context, + fname, + &workgroup, + &server, + &share, + &path, + &user, + &password, + NULL)) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!user || user[0] == (char)0) { + user = talloc_strdup(frame, context->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + return -1; + } + } + + srv = SMBC_server(frame, context, True, + server, share, &workgroup, &user, &password); + + if (!srv) { + + TALLOC_FREE(frame); + return -1; /* errno set by SMBC_server */ + + } + + /*d_printf(">>>mkdir: resolving %s\n", path);*/ + if (!cli_resolve_path(frame, "", srv->cli, path, + &targetcli, &targetpath)) { + d_printf("Could not resolve %s\n", path); + TALLOC_FREE(frame); + return -1; + } + /*d_printf(">>>mkdir: resolved path as %s\n", targetpath);*/ + + if (!cli_mkdir(targetcli, targetpath)) { + + errno = SMBC_errno(context, targetcli); + TALLOC_FREE(frame); + return -1; + + } + + TALLOC_FREE(frame); + return 0; + +} + +/* + * Our list function simply checks to see if a directory is not empty + */ + +static int smbc_rmdir_dirempty = True; + +static void +rmdir_list_fn(const char *mnt, + file_info *finfo, + const char *mask, + void *state) +{ + if (strncmp(finfo->name, ".", 1) != 0 && + strncmp(finfo->name, "..", 2) != 0) { + smbc_rmdir_dirempty = False; + } +} + +/* + * Routine to remove a directory + */ + +int +SMBC_rmdir_ctx(SMBCCTX *context, + const char *fname) +{ + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!fname) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + DEBUG(4, ("smbc_rmdir(%s)\n", fname)); + + if (SMBC_parse_path(frame, + context, + fname, + &workgroup, + &server, + &share, + &path, + &user, + &password, + NULL)) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!user || user[0] == (char)0) { + user = talloc_strdup(frame, context->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + return -1; + } + } + + srv = SMBC_server(frame, context, True, + server, share, &workgroup, &user, &password); + + if (!srv) { + + TALLOC_FREE(frame); + return -1; /* errno set by SMBC_server */ + + } + + /*d_printf(">>>rmdir: resolving %s\n", path);*/ + if (!cli_resolve_path(frame, "", srv->cli, path, + &targetcli, &targetpath)) { + d_printf("Could not resolve %s\n", path); + TALLOC_FREE(frame); + return -1; + } + /*d_printf(">>>rmdir: resolved path as %s\n", targetpath);*/ + + + if (!cli_rmdir(targetcli, targetpath)) { + + errno = SMBC_errno(context, targetcli); + + if (errno == EACCES) { /* Check if the dir empty or not */ + + /* Local storage to avoid buffer overflows */ + char *lpath; + + smbc_rmdir_dirempty = True; /* Make this so ... */ + + lpath = talloc_asprintf(frame, "%s\\*", + targetpath); + if (!lpath) { + errno = ENOMEM; + TALLOC_FREE(frame); + return -1; + } + + if (cli_list(targetcli, lpath, + aDIR | aSYSTEM | aHIDDEN, + rmdir_list_fn, NULL) < 0) { + + /* Fix errno to ignore latest error ... */ + DEBUG(5, ("smbc_rmdir: " + "cli_list returned an error: %d\n", + SMBC_errno(context, targetcli))); + errno = EACCES; + + } + + if (smbc_rmdir_dirempty) + errno = EACCES; + else + errno = ENOTEMPTY; + + } + + TALLOC_FREE(frame); + return -1; + + } + + TALLOC_FREE(frame); + return 0; + +} + +/* + * Routine to return the current directory position + */ + +off_t +SMBC_telldir_ctx(SMBCCTX *context, + SMBCFILE *dir) +{ + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + + } + + if (!dir || !SMBC_dlist_contains(context->files, dir)) { + + errno = EBADF; + TALLOC_FREE(frame); + return -1; + + } + + if (dir->file != False) { /* FIXME, should be dir, perhaps */ + + errno = ENOTDIR; + TALLOC_FREE(frame); + return -1; + + } + + /* See if we're already at the end. */ + if (dir->dir_next == NULL) { + /* We are. */ + TALLOC_FREE(frame); + return -1; + } + + /* + * We return the pointer here as the offset + */ + TALLOC_FREE(frame); + return (off_t)(long)dir->dir_next->dirent; +} + +/* + * A routine to run down the list and see if the entry is OK + */ + +static struct smbc_dir_list * +check_dir_ent(struct smbc_dir_list *list, + struct smbc_dirent *dirent) +{ + + /* Run down the list looking for what we want */ + + if (dirent) { + + struct smbc_dir_list *tmp = list; + + while (tmp) { + + if (tmp->dirent == dirent) + return tmp; + + tmp = tmp->next; + + } + + } + + return NULL; /* Not found, or an error */ + +} + + +/* + * Routine to seek on a directory + */ + +int +SMBC_lseekdir_ctx(SMBCCTX *context, + SMBCFILE *dir, + off_t offset) +{ + long int l_offset = offset; /* Handle problems of size */ + struct smbc_dirent *dirent = (struct smbc_dirent *)l_offset; + struct smbc_dir_list *list_ent = (struct smbc_dir_list *)NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + + } + + if (dir->file != False) { /* FIXME, should be dir, perhaps */ + + errno = ENOTDIR; + TALLOC_FREE(frame); + return -1; + + } + + /* Now, check what we were passed and see if it is OK ... */ + + if (dirent == NULL) { /* Seek to the begining of the list */ + + dir->dir_next = dir->dir_list; + TALLOC_FREE(frame); + return 0; + + } + + if (offset == -1) { /* Seek to the end of the list */ + dir->dir_next = NULL; + TALLOC_FREE(frame); + return 0; + } + + /* Now, run down the list and make sure that the entry is OK */ + /* This may need to be changed if we change the format of the list */ + + if ((list_ent = check_dir_ent(dir->dir_list, dirent)) == NULL) { + errno = EINVAL; /* Bad entry */ + TALLOC_FREE(frame); + return -1; + } + + dir->dir_next = list_ent; + + TALLOC_FREE(frame); + return 0; +} + +/* + * Routine to fstat a dir + */ + +int +SMBC_fstatdir_ctx(SMBCCTX *context, + SMBCFILE *dir, + struct stat *st) +{ + + if (!context || !context->initialized) { + + errno = EINVAL; + return -1; + } + + /* No code yet ... */ + return 0; +} + +int +SMBC_chmod_ctx(SMBCCTX *context, + const char *fname, + mode_t newmode) +{ + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; + uint16 mode; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + + errno = EINVAL; /* Best I can think of ... */ + TALLOC_FREE(frame); + return -1; + } + + if (!fname) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + DEBUG(4, ("smbc_chmod(%s, 0%3o)\n", fname, newmode)); + + if (SMBC_parse_path(frame, + context, + fname, + &workgroup, + &server, + &share, + &path, + &user, + &password, + NULL)) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!user || user[0] == (char)0) { + user = talloc_strdup(frame, context->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + return -1; + } + } + + srv = SMBC_server(frame, context, True, + server, share, &workgroup, &user, &password); + + if (!srv) { + TALLOC_FREE(frame); + return -1; /* errno set by SMBC_server */ + } + + mode = 0; + + if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY; + if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH; + if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM; + if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN; + + if (!cli_setatr(srv->cli, path, mode, 0)) { + errno = SMBC_errno(context, srv->cli); + TALLOC_FREE(frame); + return -1; + } + + TALLOC_FREE(frame); + return 0; +} + +int +SMBC_utimes_ctx(SMBCCTX *context, + const char *fname, + struct timeval *tbuf) +{ + SMBCSRV *srv = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; + char *path = NULL; + time_t access_time; + time_t write_time; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + + errno = EINVAL; /* Best I can think of ... */ + TALLOC_FREE(frame); + return -1; + } + + if (!fname) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (tbuf == NULL) { + access_time = write_time = time(NULL); + } else { + access_time = tbuf[0].tv_sec; + write_time = tbuf[1].tv_sec; + } + + if (DEBUGLVL(4)) { + char *p; + char atimebuf[32]; + char mtimebuf[32]; + + strncpy(atimebuf, ctime(&access_time), sizeof(atimebuf) - 1); + atimebuf[sizeof(atimebuf) - 1] = '\0'; + if ((p = strchr(atimebuf, '\n')) != NULL) { + *p = '\0'; + } + + strncpy(mtimebuf, ctime(&write_time), sizeof(mtimebuf) - 1); + mtimebuf[sizeof(mtimebuf) - 1] = '\0'; + if ((p = strchr(mtimebuf, '\n')) != NULL) { + *p = '\0'; + } + + dbgtext("smbc_utimes(%s, atime = %s mtime = %s)\n", + fname, atimebuf, mtimebuf); + } + + if (SMBC_parse_path(frame, + context, + fname, + &workgroup, + &server, + &share, + &path, + &user, + &password, + NULL)) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!user || user[0] == (char)0) { + user = talloc_strdup(frame, context->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + return -1; + } + } + + srv = SMBC_server(frame, context, True, + server, share, &workgroup, &user, &password); + + if (!srv) { + TALLOC_FREE(frame); + return -1; /* errno set by SMBC_server */ + } + + if (!SMBC_setatr(context, srv, path, + 0, access_time, write_time, 0, 0)) { + TALLOC_FREE(frame); + return -1; /* errno set by SMBC_setatr */ + } + + TALLOC_FREE(frame); + return 0; +} + +/* + * Routine to unlink() a file + */ + +int +SMBC_unlink_ctx(SMBCCTX *context, + const char *fname) +{ + char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *workgroup = NULL; + char *path = NULL; + char *targetpath = NULL; + struct cli_state *targetcli = NULL; + SMBCSRV *srv = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!context || !context->initialized) { + + errno = EINVAL; /* Best I can think of ... */ + TALLOC_FREE(frame); + return -1; + + } + + if (!fname) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + + } + + if (SMBC_parse_path(frame, + context, + fname, + &workgroup, + &server, + &share, + &path, + &user, + &password, + NULL)) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!user || user[0] == (char)0) { + user = talloc_strdup(frame, context->user); + if (!user) { + errno = ENOMEM; + TALLOC_FREE(frame); + return -1; + } + } + + srv = SMBC_server(frame, context, True, + server, share, &workgroup, &user, &password); + + if (!srv) { + TALLOC_FREE(frame); + return -1; /* SMBC_server sets errno */ + + } + + /*d_printf(">>>unlink: resolving %s\n", path);*/ + if (!cli_resolve_path(frame, "", srv->cli, path, + &targetcli, &targetpath)) { + d_printf("Could not resolve %s\n", path); + TALLOC_FREE(frame); + return -1; + } + /*d_printf(">>>unlink: resolved path as %s\n", targetpath);*/ + + if (!cli_unlink(targetcli, targetpath)) { + + errno = SMBC_errno(context, targetcli); + + if (errno == EACCES) { /* Check if the file is a directory */ + + int saverr = errno; + SMB_OFF_T size = 0; + uint16 mode = 0; + struct timespec write_time_ts; + struct timespec access_time_ts; + struct timespec change_time_ts; + SMB_INO_T ino = 0; + + if (!SMBC_getatr(context, srv, path, &mode, &size, + NULL, + &access_time_ts, + &write_time_ts, + &change_time_ts, + &ino)) { + + /* Hmmm, bad error ... What? */ + + errno = SMBC_errno(context, targetcli); + TALLOC_FREE(frame); + return -1; + + } + else { + + if (IS_DOS_DIR(mode)) + errno = EISDIR; + else + errno = saverr; /* Restore this */ + + } + } + + TALLOC_FREE(frame); + return -1; + + } + + TALLOC_FREE(frame); + return 0; /* Success ... */ + +} + +/* + * Routine to rename() a file + */ + +int +SMBC_rename_ctx(SMBCCTX *ocontext, + const char *oname, + SMBCCTX *ncontext, + const char *nname) +{ + char *server1 = NULL; + char *share1 = NULL; + char *server2 = NULL; + char *share2 = NULL; + char *user1 = NULL; + char *user2 = NULL; + char *password1 = NULL; + char *password2 = NULL; + char *workgroup = NULL; + char *path1 = NULL; + char *path2 = NULL; + char *targetpath1 = NULL; + char *targetpath2 = NULL; + struct cli_state *targetcli1 = NULL; + struct cli_state *targetcli2 = NULL; + SMBCSRV *srv = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!ocontext || !ncontext || + !ocontext->initialized || + !ncontext->initialized) { + + errno = EINVAL; /* Best I can think of ... */ + TALLOC_FREE(frame); + return -1; + } + + if (!oname || !nname) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + DEBUG(4, ("smbc_rename(%s,%s)\n", oname, nname)); + + if (SMBC_parse_path(frame, + ocontext, + oname, + &workgroup, + &server1, + &share1, + &path1, + &user1, + &password1, + NULL)) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!user1 || user1[0] == (char)0) { + user1 = talloc_strdup(frame, ocontext->user); + if (!user1) { + errno = ENOMEM; + TALLOC_FREE(frame); + return -1; + } + } + + if (SMBC_parse_path(frame, + ncontext, + nname, + NULL, + &server2, + &share2, + &path2, + &user2, + &password2, + NULL)) { + errno = EINVAL; + TALLOC_FREE(frame); + return -1; + } + + if (!user2 || user2[0] == (char)0) { + user2 = talloc_strdup(frame, ncontext->user); + if (!user2) { + errno = ENOMEM; + TALLOC_FREE(frame); + return -1; + } + } + + if (strcmp(server1, server2) || strcmp(share1, share2) || + strcmp(user1, user2)) { + /* Can't rename across file systems, or users?? */ + errno = EXDEV; + TALLOC_FREE(frame); + return -1; + } + + srv = SMBC_server(frame, ocontext, True, + server1, share1, &workgroup, &user1, &password1); + if (!srv) { + TALLOC_FREE(frame); + return -1; + + } + + /*d_printf(">>>rename: resolving %s\n", path1);*/ + if (!cli_resolve_path(frame, "", srv->cli, path1, + &targetcli1, &targetpath1)) { + d_printf("Could not resolve %s\n", path1); + TALLOC_FREE(frame); + return -1; + } + /*d_printf(">>>rename: resolved path as %s\n", targetpath1);*/ + /*d_printf(">>>rename: resolving %s\n", path2);*/ + if (!cli_resolve_path(frame, "", srv->cli, path2, + &targetcli2, &targetpath2)) { + d_printf("Could not resolve %s\n", path2); + TALLOC_FREE(frame); + return -1; + } + /*d_printf(">>>rename: resolved path as %s\n", targetpath2);*/ + + if (strcmp(targetcli1->desthost, targetcli2->desthost) || + strcmp(targetcli1->share, targetcli2->share)) + { + /* can't rename across file systems */ + errno = EXDEV; + TALLOC_FREE(frame); + return -1; + } + + if (!cli_rename(targetcli1, targetpath1, targetpath2)) { + int eno = SMBC_errno(ocontext, targetcli1); + + if (eno != EEXIST || + !cli_unlink(targetcli1, targetpath2) || + !cli_rename(targetcli1, targetpath1, targetpath2)) { + + errno = eno; + TALLOC_FREE(frame); + return -1; + + } + } + + TALLOC_FREE(frame); + return 0; /* Success */ +} + -- cgit From 4ba42cbe0f6bbd25848786e1a87c06aca79b98ea Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Fri, 29 Feb 2008 13:34:35 -0500 Subject: Modified revamp of the libsmbclient interface. Given the tacit (if that) approval by some people, and clear disapproval by others for my proposed clean-up and reorganization of libsmbclient, I've come up with a slightly different approach. This commit changes back to the original libsmbclient.h SMBCCTX structure which will maintain ABI compatibility. I retain, here, the setter and getter functions which all new code should use. Older programs already compiled should continue to work fine. Older programs being recompiled will encounter compile-time errors (intentionally!) so that the code can be corrected to use the setter/getter interfaces. Although this doesn't clean up the interface in the way I had wanted, the code reorganization and requirement for new programs to use the setters and getters allows future progress to be made on libsmbclient without further muddying up the interface, while retaining the ABI compatibility that was the big issue causing disapproval. I hope that this compromise is adequate. Derrell (This used to be commit 56429a3d60b2a48963342f6340b3c01469a892c6) --- source3/libsmb/libsmb_dir.c | 70 ++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 35 deletions(-) (limited to 'source3/libsmb/libsmb_dir.c') diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 9cb3351433..25020762a2 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -356,7 +356,7 @@ SMBC_opendir_ctx(SMBCCTX *context, struct sockaddr_storage rem_ss; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { DEBUG(4, ("no valid context\n")); errno = EINVAL + 8192; TALLOC_FREE(frame); @@ -400,7 +400,7 @@ SMBC_opendir_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -446,9 +446,9 @@ SMBC_opendir_ctx(SMBCCTX *context, } /* Determine how many local master browsers to query */ - max_lmb_count = (context->browse_max_lmb_count == 0 + max_lmb_count = (context->internal->browse_max_lmb_count == 0 ? INT_MAX - : context->browse_max_lmb_count); + : context->internal->browse_max_lmb_count); memset(&u_info, '\0', sizeof(u_info)); u_info.username = talloc_strdup(frame,user); @@ -826,7 +826,7 @@ SMBC_opendir_ctx(SMBCCTX *context, } - DLIST_ADD(context->files, dir); + DLIST_ADD(context->internal->files, dir); TALLOC_FREE(frame); return dir; @@ -842,13 +842,13 @@ SMBC_closedir_ctx(SMBCCTX *context, { TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - if (!dir || !SMBC_dlist_contains(context->files, dir)) { + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { errno = EBADF; TALLOC_FREE(frame); return -1; @@ -856,7 +856,7 @@ SMBC_closedir_ctx(SMBCCTX *context, remove_dir(dir); /* Clean it up */ - DLIST_REMOVE(context->files, dir); + DLIST_REMOVE(context->internal->files, dir); if (dir) { @@ -875,7 +875,7 @@ smbc_readdir_internal(SMBCCTX * context, struct smbc_dirent *src, int max_namebuf_len) { - if (context->urlencode_readdir_entries) { + if (context->internal->urlencode_readdir_entries) { /* url-encode the name. get back remaining buffer space */ max_namebuf_len = @@ -919,7 +919,7 @@ SMBC_readdir_ctx(SMBCCTX *context, /* Check that all is ok first ... */ - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; DEBUG(0, ("Invalid context in SMBC_readdir_ctx()\n")); @@ -928,7 +928,7 @@ SMBC_readdir_ctx(SMBCCTX *context, } - if (!dir || !SMBC_dlist_contains(context->files, dir)) { + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { errno = EBADF; DEBUG(0, ("Invalid dir in SMBC_readdir_ctx()\n")); @@ -960,8 +960,8 @@ SMBC_readdir_ctx(SMBCCTX *context, } - dirp = (struct smbc_dirent *)context->dirent; - maxlen = (sizeof(context->dirent) - + dirp = (struct smbc_dirent *)context->internal->dirent; + maxlen = (sizeof(context->internal->dirent) - sizeof(struct smbc_dirent)); smbc_readdir_internal(context, dirp, dirent, maxlen); @@ -991,7 +991,7 @@ SMBC_getdents_ctx(SMBCCTX *context, /* Check that all is ok first ... */ - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); @@ -999,7 +999,7 @@ SMBC_getdents_ctx(SMBCCTX *context, } - if (!dir || !SMBC_dlist_contains(context->files, dir)) { + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { errno = EBADF; TALLOC_FREE(frame); @@ -1033,8 +1033,8 @@ SMBC_getdents_ctx(SMBCCTX *context, } /* Do urlencoding of next entry, if so selected */ - dirent = (struct smbc_dirent *)context->dirent; - maxlen = (sizeof(context->dirent) - + dirent = (struct smbc_dirent *)context->internal->dirent; + maxlen = (sizeof(context->internal->dirent) - sizeof(struct smbc_dirent)); smbc_readdir_internal(context, dirent, dirlist->dirent, maxlen); @@ -1102,7 +1102,7 @@ SMBC_mkdir_ctx(SMBCCTX *context, struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; @@ -1132,7 +1132,7 @@ SMBC_mkdir_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1209,7 +1209,7 @@ SMBC_rmdir_ctx(SMBCCTX *context, struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; @@ -1239,7 +1239,7 @@ SMBC_rmdir_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1325,7 +1325,7 @@ SMBC_telldir_ctx(SMBCCTX *context, { TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); @@ -1333,7 +1333,7 @@ SMBC_telldir_ctx(SMBCCTX *context, } - if (!dir || !SMBC_dlist_contains(context->files, dir)) { + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { errno = EBADF; TALLOC_FREE(frame); @@ -1408,7 +1408,7 @@ SMBC_lseekdir_ctx(SMBCCTX *context, struct smbc_dir_list *list_ent = (struct smbc_dir_list *)NULL; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); @@ -1465,7 +1465,7 @@ SMBC_fstatdir_ctx(SMBCCTX *context, struct stat *st) { - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; return -1; @@ -1490,7 +1490,7 @@ SMBC_chmod_ctx(SMBCCTX *context, uint16 mode; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); @@ -1521,7 +1521,7 @@ SMBC_chmod_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1570,7 +1570,7 @@ SMBC_utimes_ctx(SMBCCTX *context, time_t write_time; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); @@ -1627,7 +1627,7 @@ SMBC_utimes_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1668,7 +1668,7 @@ SMBC_unlink_ctx(SMBCCTX *context, SMBCSRV *srv = NULL; TALLOC_CTX *frame = talloc_stackframe(); - if (!context || !context->initialized) { + if (!context || !context->internal->initialized) { errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); @@ -1699,7 +1699,7 @@ SMBC_unlink_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->user); + user = talloc_strdup(frame, context->config.user); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1802,8 +1802,8 @@ SMBC_rename_ctx(SMBCCTX *ocontext, TALLOC_CTX *frame = talloc_stackframe(); if (!ocontext || !ncontext || - !ocontext->initialized || - !ncontext->initialized) { + !ocontext->internal->initialized || + !ncontext->internal->initialized) { errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); @@ -1834,7 +1834,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext, } if (!user1 || user1[0] == (char)0) { - user1 = talloc_strdup(frame, ocontext->user); + user1 = talloc_strdup(frame, ocontext->config.user); if (!user1) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1858,7 +1858,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext, } if (!user2 || user2[0] == (char)0) { - user2 = talloc_strdup(frame, ncontext->user); + user2 = talloc_strdup(frame, ncontext->config.user); if (!user2) { errno = ENOMEM; TALLOC_FREE(frame); -- cgit From 223940d9a887c5b98a5c873797302a6a9407ad7f Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Sat, 1 Mar 2008 20:44:21 -0500 Subject: Additional revamped libsmbclient documentation - Ensured that all public functions have documentation in libsmbclient.h - Reformatted for "proper" indentation - Re-added temporarily-disabled alternate authentication function capability Derrell (This used to be commit 64b7150d92849a1e1e2416b9dcc12fae8d6bea99) --- source3/libsmb/libsmb_dir.c | 930 ++++++++++++++++++++++---------------------- 1 file changed, 472 insertions(+), 458 deletions(-) (limited to 'source3/libsmb/libsmb_dir.c') diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 25020762a2..2ece2ab8ed 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -36,19 +36,19 @@ static void remove_dir(SMBCFILE *dir) { struct smbc_dir_list *d,*f; - + d = dir->dir_list; while (d) { - + f = d; d = d->next; - + SAFE_FREE(f->dirent); SAFE_FREE(f); - + } - + dir->dir_list = dir->dir_end = dir->dir_next = NULL; - + } static int @@ -61,63 +61,63 @@ add_dirent(SMBCFILE *dir, int size; int name_length = (name == NULL ? 0 : strlen(name)); int comment_len = (comment == NULL ? 0 : strlen(comment)); - + /* * Allocate space for the dirent, which must be increased by the * size of the name and the comment and 1 each for the null terminator. */ - + size = sizeof(struct smbc_dirent) + name_length + comment_len + 2; - + dirent = (struct smbc_dirent *)SMB_MALLOC(size); - + if (!dirent) { - + dir->dir_error = ENOMEM; return -1; - + } - + ZERO_STRUCTP(dirent); - + if (dir->dir_list == NULL) { - + dir->dir_list = SMB_MALLOC_P(struct smbc_dir_list); if (!dir->dir_list) { - + SAFE_FREE(dirent); dir->dir_error = ENOMEM; return -1; - + } ZERO_STRUCTP(dir->dir_list); - + dir->dir_end = dir->dir_next = dir->dir_list; } else { - + dir->dir_end->next = SMB_MALLOC_P(struct smbc_dir_list); - + if (!dir->dir_end->next) { - + SAFE_FREE(dirent); dir->dir_error = ENOMEM; return -1; - + } ZERO_STRUCTP(dir->dir_end->next); - + dir->dir_end = dir->dir_end->next; } - + dir->dir_end->next = NULL; dir->dir_end->dirent = dirent; - + dirent->smbc_type = type; dirent->namelen = name_length; dirent->commentlen = comment_len; dirent->dirlen = size; - + /* * dirent->namelen + 1 includes the null (no null termination needed) * Ditto for dirent->commentlen. @@ -126,9 +126,9 @@ add_dirent(SMBCFILE *dir, strncpy(dirent->name, (name?name:""), dirent->namelen + 1); dirent->comment = (char *)(&dirent->name + dirent->namelen + 1); strncpy(dirent->comment, (comment?comment:""), dirent->commentlen + 1); - + return 0; - + } static void @@ -142,18 +142,18 @@ list_unique_wg_fn(const char *name, struct smbc_dirent *dirent; int dirent_type; int do_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; @@ -163,7 +163,7 @@ list_unique_wg_fn(const char *name, /* Duplicate. End end of list need to be removed. */ do_remove = 1; } - + if (do_remove && dir_list->next == dir->dir_end) { /* Found the end of the list. Remove it. */ dir->dir_end = dir_list; @@ -183,7 +183,7 @@ list_fn(const char *name, { SMBCFILE *dir = (SMBCFILE *)state; int dirent_type; - + /* * We need to process the type a little ... * @@ -195,27 +195,27 @@ list_fn(const char *name, * administrative shares: * ADMIN$, IPC$, C$, D$, E$ ... are type |= 0x80000000 */ - + if (dir->dir_type == SMBC_FILE_SHARE) { switch (type) { case 0 | 0x80000000: case 0: dirent_type = SMBC_FILE_SHARE; break; - + case 1: dirent_type = SMBC_PRINTER_SHARE; break; - + case 2: dirent_type = SMBC_COMMS_SHARE; break; - + case 3 | 0x80000000: case 3: dirent_type = SMBC_IPC_SHARE; break; - + default: dirent_type = SMBC_FILE_SHARE; /* FIXME, error? */ break; @@ -224,12 +224,12 @@ list_fn(const char *name, else { 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 */ - + } } @@ -239,16 +239,16 @@ dir_list_fn(const char *mnt, const char *mask, void *state) { - + if (add_dirent((SMBCFILE *)state, finfo->name, "", (finfo->mode&aDIR?SMBC_DIR:SMBC_FILE)) < 0) { - + /* Handle an error ... */ - + /* FIXME: Add some code ... */ - + } - + } static int @@ -270,14 +270,14 @@ net_share_enum_rpc(struct cli_state *cli, fstring comment = ""; struct rpc_pipe_client *pipe_hnd; NTSTATUS nt_status; - + /* Open the server service pipe */ pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &nt_status); if (!pipe_hnd) { DEBUG(1, ("net_share_enum_rpc pipe open fail!\n")); return -1; } - + /* Issue the NetShareEnum RPC call and retrieve the response */ init_enum_hnd(&enum_hnd, 0); result = rpccli_srvsvc_net_share_enum(pipe_hnd, @@ -286,35 +286,35 @@ net_share_enum_rpc(struct cli_state *cli, &ctr, preferred_len, &enum_hnd); - + /* Was it successful? */ if (!W_ERROR_IS_OK(result) || ctr.num_entries == 0) { /* Nope. Go clean up. */ goto done; } - + /* For each returned entry... */ for (i = 0; i < ctr.num_entries; i++) { - + /* pull out the share name */ rpcstr_pull_unistr2_fstring( name, &ctr.share.info1[i].info_1_str.uni_netname); - + /* pull out the share's comment */ rpcstr_pull_unistr2_fstring( comment, &ctr.share.info1[i].info_1_str.uni_remark); - + /* Get the type value */ type = ctr.share.info1[i].info_1.type; - + /* Add this share to the list */ (*fn)(name, type, comment, state); } - + done: /* Close the server service pipe */ cli_rpc_pipe_close(pipe_hnd); - + /* Tell 'em if it worked */ return W_ERROR_IS_OK(result) ? 0 : -1; } @@ -332,10 +332,10 @@ SMBC_check_options(char *server, 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; } @@ -346,7 +346,11 @@ SMBC_opendir_ctx(SMBCCTX *context, const char *fname) { int saved_errno; - char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *options = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *options = NULL; char *workgroup = NULL; char *path = NULL; uint16 mode; @@ -355,42 +359,42 @@ SMBC_opendir_ctx(SMBCCTX *context, SMBCFILE *dir = NULL; struct sockaddr_storage rem_ss; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { DEBUG(4, ("no valid context\n")); errno = EINVAL + 8192; TALLOC_FREE(frame); return NULL; - + } - + if (!fname) { DEBUG(4, ("no valid fname\n")); errno = EINVAL + 8193; TALLOC_FREE(frame); return NULL; } - + if (SMBC_parse_path(frame, - context, - fname, - &workgroup, - &server, - &share, - &path, - &user, - &password, - &options)) { + context, + fname, + &workgroup, + &server, + &share, + &path, + &user, + &password, + &options)) { DEBUG(4, ("no valid path\n")); errno = EINVAL + 8194; TALLOC_FREE(frame); return NULL; } - + 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)); @@ -398,7 +402,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + if (!user || user[0] == (char)0) { user = talloc_strdup(frame, context->config.user); if (!user) { @@ -407,35 +411,35 @@ SMBC_opendir_ctx(SMBCCTX *context, return NULL; } } - + dir = SMB_MALLOC_P(SMBCFILE); - + if (!dir) { errno = ENOMEM; TALLOC_FREE(frame); return NULL; } - + ZERO_STRUCTP(dir); - + dir->cli_fd = 0; dir->fname = SMB_STRDUP(fname); dir->srv = NULL; dir->offset = 0; dir->file = False; dir->dir_list = dir->dir_next = dir->dir_end = NULL; - + if (server[0] == (char)0) { - + int i; int count; int max_lmb_count; struct ip_service *ip_list; struct ip_service server_addr; struct user_auth_info u_info; - + if (share[0] != (char)0 || path[0] != (char)0) { - + errno = EINVAL + 8196; if (dir) { SAFE_FREE(dir->fname); @@ -444,12 +448,12 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + /* Determine how many local master browsers to query */ - max_lmb_count = (context->internal->browse_max_lmb_count == 0 + max_lmb_count = (context->options.browse_max_lmb_count == 0 ? INT_MAX - : context->internal->browse_max_lmb_count); - + : context->options.browse_max_lmb_count); + memset(&u_info, '\0', sizeof(u_info)); u_info.username = talloc_strdup(frame,user); u_info.password = talloc_strdup(frame,password); @@ -461,7 +465,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + /* * We have server and share and path empty but options * requesting that we scan all master browsers for their list @@ -470,16 +474,16 @@ SMBC_opendir_ctx(SMBCCTX *context, * doesn't work, then try our other methods which return only * a single master browser. */ - + ip_list = NULL; if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list, - &count))) + &count))) { - + SAFE_FREE(ip_list); - + if (!find_master_ip(workgroup, &server_addr.ss)) { - + if (dir) { SAFE_FREE(dir->fname); SAFE_FREE(dir); @@ -488,7 +492,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + ip_list = (struct ip_service *)memdup( &server_addr, sizeof(server_addr)); if (ip_list == NULL) { @@ -498,17 +502,17 @@ SMBC_opendir_ctx(SMBCCTX *context, } count = 1; } - + for (i = 0; i < count && i < max_lmb_count; i++) { char addr[INET6_ADDRSTRLEN]; char *wg_ptr = NULL; struct cli_state *cli = NULL; - + print_sockaddr(addr, sizeof(addr), &ip_list[i].ss); DEBUG(99, ("Found master browser %d of %d: %s\n", i+1, MAX(count, max_lmb_count), addr)); - + cli = get_ipc_connect_master_ip(talloc_tos(), &ip_list[i], &u_info, @@ -518,39 +522,39 @@ SMBC_opendir_ctx(SMBCCTX *context, if (!cli) { continue; } - + workgroup = talloc_strdup(frame, wg_ptr); server = talloc_strdup(frame, cli->desthost); - + cli_shutdown(cli); - + if (!workgroup || !server) { errno = ENOMEM; TALLOC_FREE(frame); return NULL; } - + 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(frame, context, True, server, "IPC$", &workgroup, &user, &password); if (!srv) { continue; } - + dir->srv = srv; dir->dir_type = SMBC_WORKGROUP; - + /* Now, list the stuff ... */ - + if (!cli_NetServerEnum(srv->cli, workgroup, SV_TYPE_DOMAIN_ENUM, @@ -559,7 +563,7 @@ SMBC_opendir_ctx(SMBCCTX *context, continue; } } - + SAFE_FREE(ip_list); } else { /* @@ -568,7 +572,7 @@ SMBC_opendir_ctx(SMBCCTX *context, */ if (*share == '\0') { if (*path != '\0') { - + /* Should not have empty share with path */ errno = EINVAL + 8197; if (dir) { @@ -577,9 +581,9 @@ SMBC_opendir_ctx(SMBCCTX *context, } TALLOC_FREE(frame); return NULL; - + } - + /* * We don't know if is really a server name * or is a workgroup/domain name. If we already have @@ -588,15 +592,16 @@ SMBC_opendir_ctx(SMBCCTX *context, * <1B>, or <20> translates. We check * to see if is an IP address first. */ - + /* * See if we have an existing server. Do not * establish a connection if one does not already * exist. */ - srv = SMBC_server(frame, context, False, server, "IPC$", + srv = SMBC_server(frame, context, False, + server, "IPC$", &workgroup, &user, &password); - + /* * If no existing server and not an IP addr, look for * LMB or DMB @@ -605,20 +610,20 @@ SMBC_opendir_ctx(SMBCCTX *context, !is_ipaddress(server) && (resolve_name(server, &rem_ss, 0x1d) || /* LMB */ resolve_name(server, &rem_ss, 0x1b) )) { /* DMB */ - + fstring buserver; - + dir->dir_type = SMBC_SERVER; - + /* * Get the backup list ... */ if (!name_status_find(server, 0, 0, &rem_ss, buserver)) { - - DEBUG(0, ("Could not get name of " - "local/domain master browser " - "for server %s\n", server)); + + DEBUG(0,("Could not get name of " + "local/domain master browser " + "for server %s\n", server)); if (dir) { SAFE_FREE(dir->fname); SAFE_FREE(dir); @@ -626,16 +631,17 @@ SMBC_opendir_ctx(SMBCCTX *context, errno = EPERM; TALLOC_FREE(frame); return NULL; - + } - + /* * Get a connection to IPC$ on the server if * we do not already have one */ srv = SMBC_server(frame, context, True, buserver, "IPC$", - &workgroup, &user, &password); + &workgroup, + &user, &password); if (!srv) { DEBUG(0, ("got no contact to IPC$\n")); if (dir) { @@ -644,16 +650,16 @@ SMBC_opendir_ctx(SMBCCTX *context, } TALLOC_FREE(frame); return NULL; - + } - + dir->srv = srv; - + /* Now, list the servers ... */ if (!cli_NetServerEnum(srv->cli, server, 0x0000FFFE, list_fn, (void *)dir)) { - + if (dir) { SAFE_FREE(dir->fname); SAFE_FREE(dir); @@ -663,15 +669,17 @@ SMBC_opendir_ctx(SMBCCTX *context, } } else if (srv || (resolve_name(server, &rem_ss, 0x20))) { - - /* If we hadn't found the server, get one now */ + + /* + * If we hadn't found the server, get one now + */ if (!srv) { srv = SMBC_server(frame, context, True, server, "IPC$", &workgroup, &user, &password); } - + if (!srv) { if (dir) { SAFE_FREE(dir->fname); @@ -679,14 +687,14 @@ SMBC_opendir_ctx(SMBCCTX *context, } TALLOC_FREE(frame); return NULL; - + } - + dir->dir_type = SMBC_FILE_SHARE; dir->srv = srv; - + /* List the shares ... */ - + if (net_share_enum_rpc( srv->cli, list_fn, @@ -695,7 +703,7 @@ SMBC_opendir_ctx(SMBCCTX *context, srv->cli, list_fn, (void *)dir) < 0) { - + errno = cli_errno(srv->cli); if (dir) { SAFE_FREE(dir->fname); @@ -703,7 +711,7 @@ SMBC_opendir_ctx(SMBCCTX *context, } TALLOC_FREE(frame); return NULL; - + } } else { /* Neither the workgroup nor server exists */ @@ -715,7 +723,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + } else { /* @@ -724,13 +732,13 @@ SMBC_opendir_ctx(SMBCCTX *context, */ char *targetpath; struct cli_state *targetcli; - + /* We connect to the server and list the directory */ dir->dir_type = SMBC_FILE_SHARE; - + srv = SMBC_server(frame, context, True, server, share, &workgroup, &user, &password); - + if (!srv) { if (dir) { SAFE_FREE(dir->fname); @@ -739,11 +747,11 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + dir->srv = srv; - + /* Now, list the files ... */ - + p = path + strlen(path); path = talloc_asprintf_append(path, "\\*"); if (!path) { @@ -754,7 +762,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + if (!cli_resolve_path(frame, "", srv->cli, path, &targetcli, &targetpath)) { d_printf("Could not resolve %s\n", path); @@ -765,47 +773,48 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + if (cli_list(targetcli, targetpath, aDIR | aSYSTEM | aHIDDEN, dir_list_fn, (void *)dir) < 0) { - + if (dir) { SAFE_FREE(dir->fname); SAFE_FREE(dir); } saved_errno = SMBC_errno(context, targetcli); - + if (saved_errno == EINVAL) { - /* - * See if they asked to opendir something - * other than a directory. If so, the - * converted error value we got would have - * been EINVAL rather than ENOTDIR. - */ - *p = '\0'; /* restore original path */ - - if (SMBC_getatr(context, srv, path, - &mode, NULL, - NULL, NULL, NULL, NULL, - NULL) && - ! IS_DOS_DIR(mode)) { - - /* It is. Correct the error value */ - saved_errno = ENOTDIR; - } + /* + * See if they asked to opendir + * something other than a directory. + * If so, the converted error value we + * got would have been EINVAL rather + * than ENOTDIR. + */ + *p = '\0'; /* restore original path */ + + if (SMBC_getatr(context, srv, path, + &mode, NULL, + NULL, NULL, NULL, NULL, + NULL) && + ! IS_DOS_DIR(mode)) { + + /* It is. Correct the error value */ + saved_errno = ENOTDIR; + } } - + /* * If there was an error and the server is no * good any more... */ if (cli_is_error(targetcli) && (context->server.check_server_fn)(context, srv)) { - + /* ... then remove it. */ if ((context->server.remove_unused_server_fn)(context, - srv)) { + srv)) { /* * We could not remove the * server completely, remove @@ -817,19 +826,19 @@ SMBC_opendir_ctx(SMBCCTX *context, (context->cache.remove_cached_server_fn)(context, srv); } } - + errno = saved_errno; TALLOC_FREE(frame); return NULL; } } - + } - + DLIST_ADD(context->internal->files, dir); TALLOC_FREE(frame); return dir; - + } /* @@ -841,32 +850,32 @@ SMBC_closedir_ctx(SMBCCTX *context, SMBCFILE *dir) { TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { errno = EBADF; TALLOC_FREE(frame); return -1; } - + remove_dir(dir); /* Clean it up */ - + DLIST_REMOVE(context->internal->files, dir); - + if (dir) { - + SAFE_FREE(dir->fname); SAFE_FREE(dir); /* Free the space too */ } - + TALLOC_FREE(frame); return 0; - + } static void @@ -875,29 +884,29 @@ smbc_readdir_internal(SMBCCTX * context, struct smbc_dirent *src, int max_namebuf_len) { - if (context->internal->urlencode_readdir_entries) { - + if (context->options.urlencode_readdir_entries) { + /* url-encode the name. get back remaining buffer space */ max_namebuf_len = SMBC_urlencode(dest->name, src->name, max_namebuf_len); - + /* We now know the name length */ dest->namelen = strlen(dest->name); - + /* Save the pointer to the beginning of the comment */ dest->comment = dest->name + dest->namelen + 1; - + /* Copy the comment */ strncpy(dest->comment, src->comment, max_namebuf_len - 1); dest->comment[max_namebuf_len - 1] = '\0'; - + /* Save other fields */ dest->smbc_type = src->smbc_type; dest->commentlen = strlen(dest->comment); dest->dirlen = ((dest->comment + dest->commentlen + 1) - (char *) dest); } else { - + /* No encoding. Just copy the entry as is. */ memcpy(dest, src, src->dirlen); dest->comment = (char *)(&dest->name + src->namelen + 1); @@ -916,58 +925,58 @@ SMBC_readdir_ctx(SMBCCTX *context, int maxlen; struct smbc_dirent *dirp, *dirent; TALLOC_CTX *frame = talloc_stackframe(); - + /* Check that all is ok first ... */ - + if (!context || !context->internal->initialized) { - + errno = EINVAL; DEBUG(0, ("Invalid context in SMBC_readdir_ctx()\n")); TALLOC_FREE(frame); return NULL; - + } - + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { - + errno = EBADF; DEBUG(0, ("Invalid dir in SMBC_readdir_ctx()\n")); TALLOC_FREE(frame); return NULL; - + } - + if (dir->file != False) { /* FIXME, should be dir, perhaps */ - + errno = ENOTDIR; DEBUG(0, ("Found file vs directory in SMBC_readdir_ctx()\n")); TALLOC_FREE(frame); return NULL; - + } - + if (!dir->dir_next) { TALLOC_FREE(frame); return NULL; } - + dirent = dir->dir_next->dirent; if (!dirent) { - + errno = ENOENT; TALLOC_FREE(frame); return NULL; - + } - + dirp = (struct smbc_dirent *)context->internal->dirent; maxlen = (sizeof(context->internal->dirent) - sizeof(struct smbc_dirent)); - + smbc_readdir_internal(context, dirp, dirent, maxlen); - + dir->dir_next = dir->dir_next->next; - + TALLOC_FREE(frame); return dirp; } @@ -988,98 +997,99 @@ SMBC_getdents_ctx(SMBCCTX *context, char *ndir = (char *)dirp; struct smbc_dir_list *dirlist; TALLOC_CTX *frame = talloc_stackframe(); - + /* Check that all is ok first ... */ - + if (!context || !context->internal->initialized) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; - + } - + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { - + errno = EBADF; TALLOC_FREE(frame); return -1; - + } - + if (dir->file != False) { /* FIXME, should be dir, perhaps */ - + errno = ENOTDIR; TALLOC_FREE(frame); return -1; - + } - + /* * Now, retrieve the number of entries that will fit in what was passed * We have to figure out if the info is in the list, or we need to * send a request to the server to get the info. */ - + while ((dirlist = dir->dir_next)) { struct smbc_dirent *dirent; - + if (!dirlist->dirent) { - + errno = ENOENT; /* Bad error */ TALLOC_FREE(frame); return -1; - + } - + /* Do urlencoding of next entry, if so selected */ dirent = (struct smbc_dirent *)context->internal->dirent; maxlen = (sizeof(context->internal->dirent) - sizeof(struct smbc_dirent)); - smbc_readdir_internal(context, dirent, dirlist->dirent, maxlen); - + smbc_readdir_internal(context, dirent, + dirlist->dirent, maxlen); + reqd = dirent->dirlen; - + if (rem < reqd) { - + if (rem < count) { /* We managed to copy something */ - + errno = 0; TALLOC_FREE(frame); return count - rem; - + } else { /* Nothing copied ... */ - + errno = EINVAL; /* Not enough space ... */ TALLOC_FREE(frame); return -1; - + } - + } - + memcpy(ndir, dirent, reqd); /* Copy the data in ... */ - + ((struct smbc_dirent *)ndir)->comment = (char *)(&((struct smbc_dirent *)ndir)->name + dirent->namelen + 1); - + ndir += reqd; - + rem -= reqd; - + dir->dir_next = dirlist = dirlist -> next; } - + TALLOC_FREE(frame); - + if (rem == count) return 0; else return count - rem; - + } /* @@ -1101,36 +1111,36 @@ SMBC_mkdir_ctx(SMBCCTX *context, char *targetpath = NULL; struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!fname) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + DEBUG(4, ("smbc_mkdir(%s)\n", fname)); - + if (SMBC_parse_path(frame, - context, - fname, - &workgroup, - &server, - &share, - &path, - &user, - &password, - NULL)) { + context, + fname, + &workgroup, + &server, + &share, + &path, + &user, + &password, + NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!user || user[0] == (char)0) { user = talloc_strdup(frame, context->config.user); if (!user) { @@ -1139,37 +1149,37 @@ SMBC_mkdir_ctx(SMBCCTX *context, return -1; } } - + srv = SMBC_server(frame, context, True, server, share, &workgroup, &user, &password); - + if (!srv) { - + TALLOC_FREE(frame); return -1; /* errno set by SMBC_server */ - + } - + /*d_printf(">>>mkdir: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", srv->cli, path, - &targetcli, &targetpath)) { + &targetcli, &targetpath)) { d_printf("Could not resolve %s\n", path); TALLOC_FREE(frame); return -1; } /*d_printf(">>>mkdir: resolved path as %s\n", targetpath);*/ - + if (!cli_mkdir(targetcli, targetpath)) { - + errno = SMBC_errno(context, targetcli); TALLOC_FREE(frame); return -1; - + } - + TALLOC_FREE(frame); return 0; - + } /* @@ -1208,36 +1218,36 @@ SMBC_rmdir_ctx(SMBCCTX *context, char *targetpath = NULL; struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!fname) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + DEBUG(4, ("smbc_rmdir(%s)\n", fname)); - + if (SMBC_parse_path(frame, - context, - fname, - &workgroup, - &server, - &share, - &path, - &user, - &password, - NULL)) { + context, + fname, + &workgroup, + &server, + &share, + &path, + &user, + &password, + NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!user || user[0] == (char)0) { user = talloc_strdup(frame, context->config.user); if (!user) { @@ -1246,38 +1256,38 @@ SMBC_rmdir_ctx(SMBCCTX *context, return -1; } } - + srv = SMBC_server(frame, context, True, server, share, &workgroup, &user, &password); - + if (!srv) { - + TALLOC_FREE(frame); return -1; /* errno set by SMBC_server */ - + } - + /*d_printf(">>>rmdir: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", srv->cli, path, - &targetcli, &targetpath)) { + &targetcli, &targetpath)) { d_printf("Could not resolve %s\n", path); TALLOC_FREE(frame); return -1; } /*d_printf(">>>rmdir: resolved path as %s\n", targetpath);*/ - - + + if (!cli_rmdir(targetcli, targetpath)) { - + errno = SMBC_errno(context, targetcli); - + if (errno == EACCES) { /* Check if the dir empty or not */ - + /* Local storage to avoid buffer overflows */ char *lpath; - + smbc_rmdir_dirempty = True; /* Make this so ... */ - + lpath = talloc_asprintf(frame, "%s\\*", targetpath); if (!lpath) { @@ -1285,34 +1295,34 @@ SMBC_rmdir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return -1; } - + if (cli_list(targetcli, lpath, aDIR | aSYSTEM | aHIDDEN, rmdir_list_fn, NULL) < 0) { - + /* Fix errno to ignore latest error ... */ DEBUG(5, ("smbc_rmdir: " "cli_list returned an error: %d\n", SMBC_errno(context, targetcli))); errno = EACCES; - + } - + if (smbc_rmdir_dirempty) errno = EACCES; else errno = ENOTEMPTY; - + } - + TALLOC_FREE(frame); return -1; - + } - + TALLOC_FREE(frame); return 0; - + } /* @@ -1324,38 +1334,38 @@ SMBC_telldir_ctx(SMBCCTX *context, SMBCFILE *dir) { TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; - + } - + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { - + errno = EBADF; TALLOC_FREE(frame); return -1; - + } - + if (dir->file != False) { /* FIXME, should be dir, perhaps */ - + errno = ENOTDIR; TALLOC_FREE(frame); return -1; - + } - + /* See if we're already at the end. */ if (dir->dir_next == NULL) { /* We are. */ TALLOC_FREE(frame); return -1; } - + /* * We return the pointer here as the offset */ @@ -1369,28 +1379,28 @@ SMBC_telldir_ctx(SMBCCTX *context, static struct smbc_dir_list * check_dir_ent(struct smbc_dir_list *list, - struct smbc_dirent *dirent) + struct smbc_dirent *dirent) { - + /* Run down the list looking for what we want */ - + if (dirent) { - + struct smbc_dir_list *tmp = list; - + while (tmp) { - + if (tmp->dirent == dirent) return tmp; - + tmp = tmp->next; - + } - + } - + return NULL; /* Not found, or an error */ - + } @@ -1407,50 +1417,50 @@ SMBC_lseekdir_ctx(SMBCCTX *context, struct smbc_dirent *dirent = (struct smbc_dirent *)l_offset; struct smbc_dir_list *list_ent = (struct smbc_dir_list *)NULL; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; - + } - + if (dir->file != False) { /* FIXME, should be dir, perhaps */ - + errno = ENOTDIR; TALLOC_FREE(frame); return -1; - + } - + /* Now, check what we were passed and see if it is OK ... */ - + if (dirent == NULL) { /* Seek to the begining of the list */ - + dir->dir_next = dir->dir_list; TALLOC_FREE(frame); return 0; - + } - + if (offset == -1) { /* Seek to the end of the list */ dir->dir_next = NULL; TALLOC_FREE(frame); return 0; } - + /* Now, run down the list and make sure that the entry is OK */ /* This may need to be changed if we change the format of the list */ - + if ((list_ent = check_dir_ent(dir->dir_list, dirent)) == NULL) { errno = EINVAL; /* Bad entry */ TALLOC_FREE(frame); return -1; } - + dir->dir_next = list_ent; - + TALLOC_FREE(frame); return 0; } @@ -1464,13 +1474,13 @@ SMBC_fstatdir_ctx(SMBCCTX *context, SMBCFILE *dir, struct stat *st) { - + if (!context || !context->internal->initialized) { - + errno = EINVAL; return -1; } - + /* No code yet ... */ return 0; } @@ -1489,37 +1499,37 @@ SMBC_chmod_ctx(SMBCCTX *context, char *path = NULL; uint16 mode; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); return -1; } - + if (!fname) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + DEBUG(4, ("smbc_chmod(%s, 0%3o)\n", fname, newmode)); - + if (SMBC_parse_path(frame, - context, - fname, - &workgroup, - &server, - &share, - &path, - &user, - &password, - NULL)) { + context, + fname, + &workgroup, + &server, + &share, + &path, + &user, + &password, + NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!user || user[0] == (char)0) { user = talloc_strdup(frame, context->config.user); if (!user) { @@ -1528,28 +1538,28 @@ SMBC_chmod_ctx(SMBCCTX *context, return -1; } } - + srv = SMBC_server(frame, context, True, server, share, &workgroup, &user, &password); - + if (!srv) { TALLOC_FREE(frame); return -1; /* errno set by SMBC_server */ } - + mode = 0; - + if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY; if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH; if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM; if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN; - + if (!cli_setatr(srv->cli, path, mode, 0)) { errno = SMBC_errno(context, srv->cli); TALLOC_FREE(frame); return -1; } - + TALLOC_FREE(frame); return 0; } @@ -1569,63 +1579,63 @@ SMBC_utimes_ctx(SMBCCTX *context, time_t access_time; time_t write_time; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); return -1; } - + if (!fname) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (tbuf == NULL) { access_time = write_time = time(NULL); } else { access_time = tbuf[0].tv_sec; write_time = tbuf[1].tv_sec; } - + if (DEBUGLVL(4)) { char *p; char atimebuf[32]; char mtimebuf[32]; - + strncpy(atimebuf, ctime(&access_time), sizeof(atimebuf) - 1); atimebuf[sizeof(atimebuf) - 1] = '\0'; if ((p = strchr(atimebuf, '\n')) != NULL) { *p = '\0'; } - + strncpy(mtimebuf, ctime(&write_time), sizeof(mtimebuf) - 1); mtimebuf[sizeof(mtimebuf) - 1] = '\0'; if ((p = strchr(mtimebuf, '\n')) != NULL) { *p = '\0'; } - + dbgtext("smbc_utimes(%s, atime = %s mtime = %s)\n", fname, atimebuf, mtimebuf); } - + if (SMBC_parse_path(frame, - context, - fname, - &workgroup, - &server, - &share, - &path, - &user, - &password, - NULL)) { + context, + fname, + &workgroup, + &server, + &share, + &path, + &user, + &password, + NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!user || user[0] == (char)0) { user = talloc_strdup(frame, context->config.user); if (!user) { @@ -1634,21 +1644,21 @@ SMBC_utimes_ctx(SMBCCTX *context, return -1; } } - + srv = SMBC_server(frame, context, True, server, share, &workgroup, &user, &password); - + if (!srv) { TALLOC_FREE(frame); return -1; /* errno set by SMBC_server */ } - + if (!SMBC_setatr(context, srv, path, 0, access_time, write_time, 0, 0)) { TALLOC_FREE(frame); return -1; /* errno set by SMBC_setatr */ } - + TALLOC_FREE(frame); return 0; } @@ -1661,43 +1671,47 @@ int SMBC_unlink_ctx(SMBCCTX *context, const char *fname) { - char *server = NULL, *share = NULL, *user = NULL, *password = NULL, *workgroup = NULL; + char *server = NULL; + char *share = NULL; + char *user = NULL; + char *password = NULL; + char *workgroup = NULL; char *path = NULL; char *targetpath = NULL; struct cli_state *targetcli = NULL; SMBCSRV *srv = NULL; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); return -1; - + } - + if (!fname) { errno = EINVAL; TALLOC_FREE(frame); return -1; - + } - + if (SMBC_parse_path(frame, - context, - fname, - &workgroup, - &server, - &share, - &path, - &user, - &password, - NULL)) { + context, + fname, + &workgroup, + &server, + &share, + &path, + &user, + &password, + NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!user || user[0] == (char)0) { user = talloc_strdup(frame, context->config.user); if (!user) { @@ -1706,31 +1720,31 @@ SMBC_unlink_ctx(SMBCCTX *context, return -1; } } - + srv = SMBC_server(frame, context, True, server, share, &workgroup, &user, &password); - + if (!srv) { TALLOC_FREE(frame); return -1; /* SMBC_server sets errno */ - + } - + /*d_printf(">>>unlink: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", srv->cli, path, - &targetcli, &targetpath)) { + &targetcli, &targetpath)) { d_printf("Could not resolve %s\n", path); TALLOC_FREE(frame); return -1; } /*d_printf(">>>unlink: resolved path as %s\n", targetpath);*/ - + if (!cli_unlink(targetcli, targetpath)) { - + errno = SMBC_errno(context, targetcli); - + if (errno == EACCES) { /* Check if the file is a directory */ - + int saverr = errno; SMB_OFF_T size = 0; uint16 mode = 0; @@ -1738,39 +1752,39 @@ SMBC_unlink_ctx(SMBCCTX *context, struct timespec access_time_ts; struct timespec change_time_ts; SMB_INO_T ino = 0; - + if (!SMBC_getatr(context, srv, path, &mode, &size, NULL, &access_time_ts, &write_time_ts, &change_time_ts, &ino)) { - + /* Hmmm, bad error ... What? */ - + errno = SMBC_errno(context, targetcli); TALLOC_FREE(frame); return -1; - + } else { - + if (IS_DOS_DIR(mode)) errno = EISDIR; else errno = saverr; /* Restore this */ - + } } - + TALLOC_FREE(frame); return -1; - + } - + TALLOC_FREE(frame); return 0; /* Success ... */ - + } /* @@ -1800,39 +1814,39 @@ SMBC_rename_ctx(SMBCCTX *ocontext, struct cli_state *targetcli2 = NULL; SMBCSRV *srv = NULL; TALLOC_CTX *frame = talloc_stackframe(); - + if (!ocontext || !ncontext || !ocontext->internal->initialized || !ncontext->internal->initialized) { - + errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); return -1; } - + if (!oname || !nname) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + DEBUG(4, ("smbc_rename(%s,%s)\n", oname, nname)); - + if (SMBC_parse_path(frame, - ocontext, - oname, - &workgroup, - &server1, - &share1, - &path1, - &user1, - &password1, - NULL)) { + ocontext, + oname, + &workgroup, + &server1, + &share1, + &path1, + &user1, + &password1, + NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!user1 || user1[0] == (char)0) { user1 = talloc_strdup(frame, ocontext->config.user); if (!user1) { @@ -1841,22 +1855,22 @@ SMBC_rename_ctx(SMBCCTX *ocontext, return -1; } } - + if (SMBC_parse_path(frame, - ncontext, - nname, - NULL, - &server2, - &share2, - &path2, - &user2, - &password2, - NULL)) { + ncontext, + nname, + NULL, + &server2, + &share2, + &path2, + &user2, + &password2, + NULL)) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!user2 || user2[0] == (char)0) { user2 = talloc_strdup(frame, ncontext->config.user); if (!user2) { @@ -1865,7 +1879,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext, return -1; } } - + if (strcmp(server1, server2) || strcmp(share1, share2) || strcmp(user1, user2)) { /* Can't rename across file systems, or users?? */ @@ -1873,18 +1887,18 @@ SMBC_rename_ctx(SMBCCTX *ocontext, TALLOC_FREE(frame); return -1; } - + srv = SMBC_server(frame, ocontext, True, server1, share1, &workgroup, &user1, &password1); if (!srv) { TALLOC_FREE(frame); return -1; - + } - + /*d_printf(">>>rename: resolving %s\n", path1);*/ if (!cli_resolve_path(frame, "", srv->cli, path1, - &targetcli1, &targetpath1)) { + &targetcli1, &targetpath1)) { d_printf("Could not resolve %s\n", path1); TALLOC_FREE(frame); return -1; @@ -1892,13 +1906,13 @@ SMBC_rename_ctx(SMBCCTX *ocontext, /*d_printf(">>>rename: resolved path as %s\n", targetpath1);*/ /*d_printf(">>>rename: resolving %s\n", path2);*/ if (!cli_resolve_path(frame, "", srv->cli, path2, - &targetcli2, &targetpath2)) { + &targetcli2, &targetpath2)) { d_printf("Could not resolve %s\n", path2); TALLOC_FREE(frame); return -1; } /*d_printf(">>>rename: resolved path as %s\n", targetpath2);*/ - + if (strcmp(targetcli1->desthost, targetcli2->desthost) || strcmp(targetcli1->share, targetcli2->share)) { @@ -1907,21 +1921,21 @@ SMBC_rename_ctx(SMBCCTX *ocontext, TALLOC_FREE(frame); return -1; } - + if (!cli_rename(targetcli1, targetpath1, targetpath2)) { int eno = SMBC_errno(ocontext, targetcli1); - + if (eno != EEXIST || !cli_unlink(targetcli1, targetpath2) || !cli_rename(targetcli1, targetpath1, targetpath2)) { - + errno = eno; TALLOC_FREE(frame); return -1; - + } } - + TALLOC_FREE(frame); return 0; /* Success */ } -- cgit From 1363ee9d65965704f716965c6cbcfc0693ca2401 Mon Sep 17 00:00:00 2001 From: Derrell Lipman Date: Mon, 3 Mar 2008 18:13:33 -0500 Subject: Continued revamping of libsmbclient. - James suggested using gcc's "deprecated" attribute to mark the context structure fields to generate warnings. This creates a scenario with the best of all worlds. I'm able to move to an organization that more easily allows future enhancements, while avoiding any mandatory changes by applications. Thanks, James! - Updated WHATSNEW.txt so that it accurately reflects the current state of affairs. Derrell (This used to be commit a67f96fbe9683b46c2149f7cb439d13f7f0e6ecd) --- source3/libsmb/libsmb_dir.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'source3/libsmb/libsmb_dir.c') diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 2ece2ab8ed..1486097d51 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -404,7 +404,7 @@ SMBC_opendir_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -450,9 +450,9 @@ SMBC_opendir_ctx(SMBCCTX *context, } /* Determine how many local master browsers to query */ - max_lmb_count = (context->options.browse_max_lmb_count == 0 + max_lmb_count = (smbc_getOptionBrowseMaxLmbCount(context) == 0 ? INT_MAX - : context->options.browse_max_lmb_count); + : smbc_getOptionBrowseMaxLmbCount(context)); memset(&u_info, '\0', sizeof(u_info)); u_info.username = talloc_strdup(frame,user); @@ -810,11 +810,11 @@ SMBC_opendir_ctx(SMBCCTX *context, * good any more... */ if (cli_is_error(targetcli) && - (context->server.check_server_fn)(context, srv)) { + smbc_getFunctionCheckServer(context)(context, srv)) { /* ... then remove it. */ - if ((context->server.remove_unused_server_fn)(context, - srv)) { + if (smbc_getFunctionRemoveUnusedServer(context)(context, + srv)) { /* * We could not remove the * server completely, remove @@ -823,7 +823,7 @@ SMBC_opendir_ctx(SMBCCTX *context, * will be removed when the * last file/dir is closed. */ - (context->cache.remove_cached_server_fn)(context, srv); + smbc_getFunctionRemoveCachedServer(context)(context, srv); } } @@ -884,7 +884,7 @@ smbc_readdir_internal(SMBCCTX * context, struct smbc_dirent *src, int max_namebuf_len) { - if (context->options.urlencode_readdir_entries) { + if (smbc_getOptionUrlEncodeReaddirEntries(context)) { /* url-encode the name. get back remaining buffer space */ max_namebuf_len = @@ -1142,7 +1142,7 @@ SMBC_mkdir_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1249,7 +1249,7 @@ SMBC_rmdir_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1531,7 +1531,7 @@ SMBC_chmod_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1637,7 +1637,7 @@ SMBC_utimes_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1713,7 +1713,7 @@ SMBC_unlink_ctx(SMBCCTX *context, } if (!user || user[0] == (char)0) { - user = talloc_strdup(frame, context->config.user); + user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1848,7 +1848,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext, } if (!user1 || user1[0] == (char)0) { - user1 = talloc_strdup(frame, ocontext->config.user); + user1 = talloc_strdup(frame, smbc_getUser(ocontext)); if (!user1) { errno = ENOMEM; TALLOC_FREE(frame); @@ -1872,7 +1872,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext, } if (!user2 || user2[0] == (char)0) { - user2 = talloc_strdup(frame, ncontext->config.user); + user2 = talloc_strdup(frame, smbc_getUser(ncontext)); if (!user2) { errno = ENOMEM; TALLOC_FREE(frame); -- cgit From d185fb48fb5a05f9ed83c7c0b9dff7f2bbcae732 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 7 Mar 2008 17:37:07 +0100 Subject: Remove insane amount of whitespace. Guenther (This used to be commit 8216310e9f0d7dcccfe761a184a014b7b2ce03c5) --- source3/libsmb/libsmb_dir.c | 736 ++++++++++++++++++++++---------------------- 1 file changed, 368 insertions(+), 368 deletions(-) (limited to 'source3/libsmb/libsmb_dir.c') diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 1486097d51..45db914d18 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -1,23 +1,23 @@ -/* +/* 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) Tom Jansen (Ninja ISD) 2002 Copyright (C) Derrell Lipman 2003-2008 Copyright (C) Jeremy Allison 2007, 2008 - + 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 3 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, see . */ @@ -36,19 +36,19 @@ static void remove_dir(SMBCFILE *dir) { struct smbc_dir_list *d,*f; - + d = dir->dir_list; while (d) { - + f = d; d = d->next; - + SAFE_FREE(f->dirent); SAFE_FREE(f); - + } - + dir->dir_list = dir->dir_end = dir->dir_next = NULL; - + } static int @@ -61,63 +61,63 @@ add_dirent(SMBCFILE *dir, int size; int name_length = (name == NULL ? 0 : strlen(name)); int comment_len = (comment == NULL ? 0 : strlen(comment)); - + /* - * Allocate space for the dirent, which must be increased by the + * Allocate space for the dirent, which must be increased by the * size of the name and the comment and 1 each for the null terminator. */ - + size = sizeof(struct smbc_dirent) + name_length + comment_len + 2; - + dirent = (struct smbc_dirent *)SMB_MALLOC(size); - + if (!dirent) { - + dir->dir_error = ENOMEM; return -1; - + } - + ZERO_STRUCTP(dirent); - + if (dir->dir_list == NULL) { - + dir->dir_list = SMB_MALLOC_P(struct smbc_dir_list); if (!dir->dir_list) { - + SAFE_FREE(dirent); dir->dir_error = ENOMEM; return -1; - + } ZERO_STRUCTP(dir->dir_list); - + dir->dir_end = dir->dir_next = dir->dir_list; } else { - + dir->dir_end->next = SMB_MALLOC_P(struct smbc_dir_list); - + if (!dir->dir_end->next) { - + SAFE_FREE(dirent); dir->dir_error = ENOMEM; return -1; - + } ZERO_STRUCTP(dir->dir_end->next); - + dir->dir_end = dir->dir_end->next; } - + dir->dir_end->next = NULL; dir->dir_end->dirent = dirent; - + dirent->smbc_type = type; dirent->namelen = name_length; dirent->commentlen = comment_len; dirent->dirlen = size; - + /* * dirent->namelen + 1 includes the null (no null termination needed) * Ditto for dirent->commentlen. @@ -126,9 +126,9 @@ add_dirent(SMBCFILE *dir, strncpy(dirent->name, (name?name:""), dirent->namelen + 1); dirent->comment = (char *)(&dirent->name + dirent->namelen + 1); strncpy(dirent->comment, (comment?comment:""), dirent->commentlen + 1); - + return 0; - + } static void @@ -142,18 +142,18 @@ list_unique_wg_fn(const char *name, struct smbc_dirent *dirent; int dirent_type; int do_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; @@ -163,7 +163,7 @@ list_unique_wg_fn(const char *name, /* Duplicate. End end of list need to be removed. */ do_remove = 1; } - + if (do_remove && dir_list->next == dir->dir_end) { /* Found the end of the list. Remove it. */ dir->dir_end = dir_list; @@ -183,7 +183,7 @@ list_fn(const char *name, { SMBCFILE *dir = (SMBCFILE *)state; int dirent_type; - + /* * We need to process the type a little ... * @@ -195,27 +195,27 @@ list_fn(const char *name, * administrative shares: * ADMIN$, IPC$, C$, D$, E$ ... are type |= 0x80000000 */ - + if (dir->dir_type == SMBC_FILE_SHARE) { switch (type) { case 0 | 0x80000000: case 0: dirent_type = SMBC_FILE_SHARE; break; - + case 1: dirent_type = SMBC_PRINTER_SHARE; break; - + case 2: dirent_type = SMBC_COMMS_SHARE; break; - + case 3 | 0x80000000: case 3: dirent_type = SMBC_IPC_SHARE; break; - + default: dirent_type = SMBC_FILE_SHARE; /* FIXME, error? */ break; @@ -224,12 +224,12 @@ list_fn(const char *name, else { 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 */ - + } } @@ -239,16 +239,16 @@ dir_list_fn(const char *mnt, const char *mask, void *state) { - - if (add_dirent((SMBCFILE *)state, finfo->name, "", + + if (add_dirent((SMBCFILE *)state, finfo->name, "", (finfo->mode&aDIR?SMBC_DIR:SMBC_FILE)) < 0) { - + /* Handle an error ... */ - + /* FIXME: Add some code ... */ - - } - + + } + } static int @@ -270,14 +270,14 @@ net_share_enum_rpc(struct cli_state *cli, fstring comment = ""; struct rpc_pipe_client *pipe_hnd; NTSTATUS nt_status; - + /* Open the server service pipe */ pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &nt_status); if (!pipe_hnd) { DEBUG(1, ("net_share_enum_rpc pipe open fail!\n")); return -1; } - + /* Issue the NetShareEnum RPC call and retrieve the response */ init_enum_hnd(&enum_hnd, 0); result = rpccli_srvsvc_net_share_enum(pipe_hnd, @@ -286,35 +286,35 @@ net_share_enum_rpc(struct cli_state *cli, &ctr, preferred_len, &enum_hnd); - + /* Was it successful? */ if (!W_ERROR_IS_OK(result) || ctr.num_entries == 0) { /* Nope. Go clean up. */ goto done; } - + /* For each returned entry... */ for (i = 0; i < ctr.num_entries; i++) { - + /* pull out the share name */ rpcstr_pull_unistr2_fstring( name, &ctr.share.info1[i].info_1_str.uni_netname); - + /* pull out the share's comment */ rpcstr_pull_unistr2_fstring( comment, &ctr.share.info1[i].info_1_str.uni_remark); - + /* Get the type value */ type = ctr.share.info1[i].info_1.type; - + /* Add this share to the list */ (*fn)(name, type, comment, state); } - + done: /* Close the server service pipe */ cli_rpc_pipe_close(pipe_hnd); - + /* Tell 'em if it worked */ return W_ERROR_IS_OK(result) ? 0 : -1; } @@ -332,10 +332,10 @@ SMBC_check_options(char *server, 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; } @@ -359,22 +359,22 @@ SMBC_opendir_ctx(SMBCCTX *context, SMBCFILE *dir = NULL; struct sockaddr_storage rem_ss; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { DEBUG(4, ("no valid context\n")); errno = EINVAL + 8192; TALLOC_FREE(frame); return NULL; - + } - + if (!fname) { DEBUG(4, ("no valid fname\n")); errno = EINVAL + 8193; TALLOC_FREE(frame); return NULL; } - + if (SMBC_parse_path(frame, context, fname, @@ -390,11 +390,11 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + 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)); @@ -402,7 +402,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + if (!user || user[0] == (char)0) { user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { @@ -411,35 +411,35 @@ SMBC_opendir_ctx(SMBCCTX *context, return NULL; } } - + dir = SMB_MALLOC_P(SMBCFILE); - + if (!dir) { errno = ENOMEM; TALLOC_FREE(frame); return NULL; } - + ZERO_STRUCTP(dir); - + dir->cli_fd = 0; dir->fname = SMB_STRDUP(fname); dir->srv = NULL; dir->offset = 0; dir->file = False; dir->dir_list = dir->dir_next = dir->dir_end = NULL; - + if (server[0] == (char)0) { - + int i; int count; int max_lmb_count; struct ip_service *ip_list; struct ip_service server_addr; struct user_auth_info u_info; - + if (share[0] != (char)0 || path[0] != (char)0) { - + errno = EINVAL + 8196; if (dir) { SAFE_FREE(dir->fname); @@ -448,12 +448,12 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + /* Determine how many local master browsers to query */ max_lmb_count = (smbc_getOptionBrowseMaxLmbCount(context) == 0 ? INT_MAX : smbc_getOptionBrowseMaxLmbCount(context)); - + memset(&u_info, '\0', sizeof(u_info)); u_info.username = talloc_strdup(frame,user); u_info.password = talloc_strdup(frame,password); @@ -465,7 +465,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + /* * We have server and share and path empty but options * requesting that we scan all master browsers for their list @@ -474,16 +474,16 @@ SMBC_opendir_ctx(SMBCCTX *context, * doesn't work, then try our other methods which return only * a single master browser. */ - + ip_list = NULL; if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list, &count))) { - + SAFE_FREE(ip_list); - + if (!find_master_ip(workgroup, &server_addr.ss)) { - + if (dir) { SAFE_FREE(dir->fname); SAFE_FREE(dir); @@ -492,7 +492,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + ip_list = (struct ip_service *)memdup( &server_addr, sizeof(server_addr)); if (ip_list == NULL) { @@ -502,17 +502,17 @@ SMBC_opendir_ctx(SMBCCTX *context, } count = 1; } - + for (i = 0; i < count && i < max_lmb_count; i++) { char addr[INET6_ADDRSTRLEN]; char *wg_ptr = NULL; struct cli_state *cli = NULL; - + print_sockaddr(addr, sizeof(addr), &ip_list[i].ss); DEBUG(99, ("Found master browser %d of %d: %s\n", i+1, MAX(count, max_lmb_count), addr)); - + cli = get_ipc_connect_master_ip(talloc_tos(), &ip_list[i], &u_info, @@ -522,39 +522,39 @@ SMBC_opendir_ctx(SMBCCTX *context, if (!cli) { continue; } - + workgroup = talloc_strdup(frame, wg_ptr); server = talloc_strdup(frame, cli->desthost); - + cli_shutdown(cli); - + if (!workgroup || !server) { errno = ENOMEM; TALLOC_FREE(frame); return NULL; } - + 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(frame, context, True, server, "IPC$", &workgroup, &user, &password); if (!srv) { continue; } - + dir->srv = srv; dir->dir_type = SMBC_WORKGROUP; - + /* Now, list the stuff ... */ - + if (!cli_NetServerEnum(srv->cli, workgroup, SV_TYPE_DOMAIN_ENUM, @@ -563,7 +563,7 @@ SMBC_opendir_ctx(SMBCCTX *context, continue; } } - + SAFE_FREE(ip_list); } else { /* @@ -572,7 +572,7 @@ SMBC_opendir_ctx(SMBCCTX *context, */ if (*share == '\0') { if (*path != '\0') { - + /* Should not have empty share with path */ errno = EINVAL + 8197; if (dir) { @@ -581,9 +581,9 @@ SMBC_opendir_ctx(SMBCCTX *context, } TALLOC_FREE(frame); return NULL; - + } - + /* * We don't know if is really a server name * or is a workgroup/domain name. If we already have @@ -592,7 +592,7 @@ SMBC_opendir_ctx(SMBCCTX *context, * <1B>, or <20> translates. We check * to see if is an IP address first. */ - + /* * See if we have an existing server. Do not * establish a connection if one does not already @@ -601,7 +601,7 @@ SMBC_opendir_ctx(SMBCCTX *context, srv = SMBC_server(frame, context, False, server, "IPC$", &workgroup, &user, &password); - + /* * If no existing server and not an IP addr, look for * LMB or DMB @@ -610,17 +610,17 @@ SMBC_opendir_ctx(SMBCCTX *context, !is_ipaddress(server) && (resolve_name(server, &rem_ss, 0x1d) || /* LMB */ resolve_name(server, &rem_ss, 0x1b) )) { /* DMB */ - + fstring buserver; - + dir->dir_type = SMBC_SERVER; - + /* * Get the backup list ... */ if (!name_status_find(server, 0, 0, &rem_ss, buserver)) { - + DEBUG(0,("Could not get name of " "local/domain master browser " "for server %s\n", server)); @@ -631,9 +631,9 @@ SMBC_opendir_ctx(SMBCCTX *context, errno = EPERM; TALLOC_FREE(frame); return NULL; - + } - + /* * Get a connection to IPC$ on the server if * we do not already have one @@ -650,16 +650,16 @@ SMBC_opendir_ctx(SMBCCTX *context, } TALLOC_FREE(frame); return NULL; - + } - + dir->srv = srv; - + /* Now, list the servers ... */ if (!cli_NetServerEnum(srv->cli, server, 0x0000FFFE, list_fn, (void *)dir)) { - + if (dir) { SAFE_FREE(dir->fname); SAFE_FREE(dir); @@ -669,7 +669,7 @@ SMBC_opendir_ctx(SMBCCTX *context, } } else if (srv || (resolve_name(server, &rem_ss, 0x20))) { - + /* * If we hadn't found the server, get one now */ @@ -679,7 +679,7 @@ SMBC_opendir_ctx(SMBCCTX *context, &workgroup, &user, &password); } - + if (!srv) { if (dir) { SAFE_FREE(dir->fname); @@ -687,14 +687,14 @@ SMBC_opendir_ctx(SMBCCTX *context, } TALLOC_FREE(frame); return NULL; - + } - + dir->dir_type = SMBC_FILE_SHARE; dir->srv = srv; - + /* List the shares ... */ - + if (net_share_enum_rpc( srv->cli, list_fn, @@ -703,7 +703,7 @@ SMBC_opendir_ctx(SMBCCTX *context, srv->cli, list_fn, (void *)dir) < 0) { - + errno = cli_errno(srv->cli); if (dir) { SAFE_FREE(dir->fname); @@ -711,7 +711,7 @@ SMBC_opendir_ctx(SMBCCTX *context, } TALLOC_FREE(frame); return NULL; - + } } else { /* Neither the workgroup nor server exists */ @@ -723,7 +723,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + } else { /* @@ -732,13 +732,13 @@ SMBC_opendir_ctx(SMBCCTX *context, */ char *targetpath; struct cli_state *targetcli; - + /* We connect to the server and list the directory */ dir->dir_type = SMBC_FILE_SHARE; - + srv = SMBC_server(frame, context, True, server, share, &workgroup, &user, &password); - + if (!srv) { if (dir) { SAFE_FREE(dir->fname); @@ -747,11 +747,11 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + dir->srv = srv; - + /* Now, list the files ... */ - + p = path + strlen(path); path = talloc_asprintf_append(path, "\\*"); if (!path) { @@ -762,7 +762,7 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + if (!cli_resolve_path(frame, "", srv->cli, path, &targetcli, &targetpath)) { d_printf("Could not resolve %s\n", path); @@ -773,17 +773,17 @@ SMBC_opendir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return NULL; } - + if (cli_list(targetcli, targetpath, aDIR | aSYSTEM | aHIDDEN, dir_list_fn, (void *)dir) < 0) { - + if (dir) { SAFE_FREE(dir->fname); SAFE_FREE(dir); } saved_errno = SMBC_errno(context, targetcli); - + if (saved_errno == EINVAL) { /* * See if they asked to opendir @@ -793,28 +793,28 @@ SMBC_opendir_ctx(SMBCCTX *context, * than ENOTDIR. */ *p = '\0'; /* restore original path */ - + if (SMBC_getatr(context, srv, path, &mode, NULL, NULL, NULL, NULL, NULL, NULL) && ! IS_DOS_DIR(mode)) { - + /* It is. Correct the error value */ saved_errno = ENOTDIR; } } - + /* * If there was an error and the server is no * good any more... */ if (cli_is_error(targetcli) && smbc_getFunctionCheckServer(context)(context, srv)) { - + /* ... then remove it. */ if (smbc_getFunctionRemoveUnusedServer(context)(context, - srv)) { + srv)) { /* * We could not remove the * server completely, remove @@ -826,19 +826,19 @@ SMBC_opendir_ctx(SMBCCTX *context, smbc_getFunctionRemoveCachedServer(context)(context, srv); } } - + errno = saved_errno; TALLOC_FREE(frame); return NULL; } } - + } - + DLIST_ADD(context->internal->files, dir); TALLOC_FREE(frame); return dir; - + } /* @@ -850,32 +850,32 @@ SMBC_closedir_ctx(SMBCCTX *context, SMBCFILE *dir) { TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { errno = EBADF; TALLOC_FREE(frame); return -1; } - + remove_dir(dir); /* Clean it up */ - + DLIST_REMOVE(context->internal->files, dir); - + if (dir) { - + SAFE_FREE(dir->fname); SAFE_FREE(dir); /* Free the space too */ } - + TALLOC_FREE(frame); return 0; - + } static void @@ -885,33 +885,33 @@ smbc_readdir_internal(SMBCCTX * context, int max_namebuf_len) { if (smbc_getOptionUrlEncodeReaddirEntries(context)) { - + /* url-encode the name. get back remaining buffer space */ max_namebuf_len = SMBC_urlencode(dest->name, src->name, max_namebuf_len); - + /* We now know the name length */ dest->namelen = strlen(dest->name); - + /* Save the pointer to the beginning of the comment */ dest->comment = dest->name + dest->namelen + 1; - + /* Copy the comment */ strncpy(dest->comment, src->comment, max_namebuf_len - 1); dest->comment[max_namebuf_len - 1] = '\0'; - + /* Save other fields */ dest->smbc_type = src->smbc_type; dest->commentlen = strlen(dest->comment); dest->dirlen = ((dest->comment + dest->commentlen + 1) - (char *) dest); } else { - + /* No encoding. Just copy the entry as is. */ memcpy(dest, src, src->dirlen); dest->comment = (char *)(&dest->name + src->namelen + 1); } - + } /* @@ -925,58 +925,58 @@ SMBC_readdir_ctx(SMBCCTX *context, int maxlen; struct smbc_dirent *dirp, *dirent; TALLOC_CTX *frame = talloc_stackframe(); - + /* Check that all is ok first ... */ - + if (!context || !context->internal->initialized) { - + errno = EINVAL; DEBUG(0, ("Invalid context in SMBC_readdir_ctx()\n")); TALLOC_FREE(frame); return NULL; - + } - + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { - + errno = EBADF; DEBUG(0, ("Invalid dir in SMBC_readdir_ctx()\n")); TALLOC_FREE(frame); return NULL; - + } - + if (dir->file != False) { /* FIXME, should be dir, perhaps */ - + errno = ENOTDIR; DEBUG(0, ("Found file vs directory in SMBC_readdir_ctx()\n")); TALLOC_FREE(frame); return NULL; - + } - + if (!dir->dir_next) { TALLOC_FREE(frame); return NULL; } - + dirent = dir->dir_next->dirent; if (!dirent) { - + errno = ENOENT; TALLOC_FREE(frame); return NULL; - + } - + dirp = (struct smbc_dirent *)context->internal->dirent; maxlen = (sizeof(context->internal->dirent) - sizeof(struct smbc_dirent)); - + smbc_readdir_internal(context, dirp, dirent, maxlen); - + dir->dir_next = dir->dir_next->next; - + TALLOC_FREE(frame); return dirp; } @@ -997,99 +997,99 @@ SMBC_getdents_ctx(SMBCCTX *context, char *ndir = (char *)dirp; struct smbc_dir_list *dirlist; TALLOC_CTX *frame = talloc_stackframe(); - + /* Check that all is ok first ... */ - + if (!context || !context->internal->initialized) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; - + } - + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { - + errno = EBADF; TALLOC_FREE(frame); return -1; - + } - + if (dir->file != False) { /* FIXME, should be dir, perhaps */ - + errno = ENOTDIR; TALLOC_FREE(frame); return -1; - + } - - /* + + /* * Now, retrieve the number of entries that will fit in what was passed - * We have to figure out if the info is in the list, or we need to + * We have to figure out if the info is in the list, or we need to * send a request to the server to get the info. */ - + while ((dirlist = dir->dir_next)) { struct smbc_dirent *dirent; - + if (!dirlist->dirent) { - + errno = ENOENT; /* Bad error */ TALLOC_FREE(frame); return -1; - + } - + /* Do urlencoding of next entry, if so selected */ dirent = (struct smbc_dirent *)context->internal->dirent; maxlen = (sizeof(context->internal->dirent) - sizeof(struct smbc_dirent)); smbc_readdir_internal(context, dirent, dirlist->dirent, maxlen); - + reqd = dirent->dirlen; - + if (rem < reqd) { - + if (rem < count) { /* We managed to copy something */ - + errno = 0; TALLOC_FREE(frame); return count - rem; - + } else { /* Nothing copied ... */ - + errno = EINVAL; /* Not enough space ... */ TALLOC_FREE(frame); return -1; - + } - + } - + memcpy(ndir, dirent, reqd); /* Copy the data in ... */ - - ((struct smbc_dirent *)ndir)->comment = + + ((struct smbc_dirent *)ndir)->comment = (char *)(&((struct smbc_dirent *)ndir)->name + dirent->namelen + 1); - + ndir += reqd; - + rem -= reqd; - + dir->dir_next = dirlist = dirlist -> next; } - + TALLOC_FREE(frame); - + if (rem == count) return 0; else return count - rem; - + } /* @@ -1111,21 +1111,21 @@ SMBC_mkdir_ctx(SMBCCTX *context, char *targetpath = NULL; struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!fname) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + DEBUG(4, ("smbc_mkdir(%s)\n", fname)); - + if (SMBC_parse_path(frame, context, fname, @@ -1140,7 +1140,7 @@ SMBC_mkdir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return -1; } - + if (!user || user[0] == (char)0) { user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { @@ -1149,17 +1149,17 @@ SMBC_mkdir_ctx(SMBCCTX *context, return -1; } } - + srv = SMBC_server(frame, context, True, server, share, &workgroup, &user, &password); - + if (!srv) { - + TALLOC_FREE(frame); return -1; /* errno set by SMBC_server */ - + } - + /*d_printf(">>>mkdir: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", srv->cli, path, &targetcli, &targetpath)) { @@ -1168,18 +1168,18 @@ SMBC_mkdir_ctx(SMBCCTX *context, return -1; } /*d_printf(">>>mkdir: resolved path as %s\n", targetpath);*/ - + if (!cli_mkdir(targetcli, targetpath)) { - + errno = SMBC_errno(context, targetcli); TALLOC_FREE(frame); return -1; - - } - + + } + TALLOC_FREE(frame); return 0; - + } /* @@ -1218,21 +1218,21 @@ SMBC_rmdir_ctx(SMBCCTX *context, char *targetpath = NULL; struct cli_state *targetcli = NULL; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (!fname) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + DEBUG(4, ("smbc_rmdir(%s)\n", fname)); - + if (SMBC_parse_path(frame, context, fname, @@ -1247,7 +1247,7 @@ SMBC_rmdir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return -1; } - + if (!user || user[0] == (char)0) { user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { @@ -1256,17 +1256,17 @@ SMBC_rmdir_ctx(SMBCCTX *context, return -1; } } - + srv = SMBC_server(frame, context, True, server, share, &workgroup, &user, &password); - + if (!srv) { - + TALLOC_FREE(frame); return -1; /* errno set by SMBC_server */ - + } - + /*d_printf(">>>rmdir: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", srv->cli, path, &targetcli, &targetpath)) { @@ -1275,19 +1275,19 @@ SMBC_rmdir_ctx(SMBCCTX *context, return -1; } /*d_printf(">>>rmdir: resolved path as %s\n", targetpath);*/ - - + + if (!cli_rmdir(targetcli, targetpath)) { - + errno = SMBC_errno(context, targetcli); - + if (errno == EACCES) { /* Check if the dir empty or not */ - + /* Local storage to avoid buffer overflows */ char *lpath; - + smbc_rmdir_dirempty = True; /* Make this so ... */ - + lpath = talloc_asprintf(frame, "%s\\*", targetpath); if (!lpath) { @@ -1295,34 +1295,34 @@ SMBC_rmdir_ctx(SMBCCTX *context, TALLOC_FREE(frame); return -1; } - + if (cli_list(targetcli, lpath, aDIR | aSYSTEM | aHIDDEN, rmdir_list_fn, NULL) < 0) { - + /* Fix errno to ignore latest error ... */ DEBUG(5, ("smbc_rmdir: " "cli_list returned an error: %d\n", SMBC_errno(context, targetcli))); errno = EACCES; - + } - + if (smbc_rmdir_dirempty) errno = EACCES; else errno = ENOTEMPTY; - + } - + TALLOC_FREE(frame); return -1; - - } - + + } + TALLOC_FREE(frame); return 0; - + } /* @@ -1334,38 +1334,38 @@ SMBC_telldir_ctx(SMBCCTX *context, SMBCFILE *dir) { TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; - + } - + if (!dir || !SMBC_dlist_contains(context->internal->files, dir)) { - + errno = EBADF; TALLOC_FREE(frame); return -1; - + } - + if (dir->file != False) { /* FIXME, should be dir, perhaps */ - + errno = ENOTDIR; TALLOC_FREE(frame); return -1; - + } - + /* See if we're already at the end. */ if (dir->dir_next == NULL) { /* We are. */ TALLOC_FREE(frame); return -1; } - + /* * We return the pointer here as the offset */ @@ -1378,29 +1378,29 @@ SMBC_telldir_ctx(SMBCCTX *context, */ static struct smbc_dir_list * -check_dir_ent(struct smbc_dir_list *list, +check_dir_ent(struct smbc_dir_list *list, struct smbc_dirent *dirent) { - + /* Run down the list looking for what we want */ - + if (dirent) { - + struct smbc_dir_list *tmp = list; - + while (tmp) { - + if (tmp->dirent == dirent) return tmp; - + tmp = tmp->next; - + } - + } - + return NULL; /* Not found, or an error */ - + } @@ -1417,50 +1417,50 @@ SMBC_lseekdir_ctx(SMBCCTX *context, struct smbc_dirent *dirent = (struct smbc_dirent *)l_offset; struct smbc_dir_list *list_ent = (struct smbc_dir_list *)NULL; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; TALLOC_FREE(frame); return -1; - + } - + if (dir->file != False) { /* FIXME, should be dir, perhaps */ - + errno = ENOTDIR; TALLOC_FREE(frame); return -1; - + } - + /* Now, check what we were passed and see if it is OK ... */ - + if (dirent == NULL) { /* Seek to the begining of the list */ - + dir->dir_next = dir->dir_list; TALLOC_FREE(frame); return 0; - + } - + if (offset == -1) { /* Seek to the end of the list */ dir->dir_next = NULL; TALLOC_FREE(frame); return 0; } - + /* Now, run down the list and make sure that the entry is OK */ /* This may need to be changed if we change the format of the list */ - + if ((list_ent = check_dir_ent(dir->dir_list, dirent)) == NULL) { errno = EINVAL; /* Bad entry */ TALLOC_FREE(frame); return -1; } - + dir->dir_next = list_ent; - + TALLOC_FREE(frame); return 0; } @@ -1474,13 +1474,13 @@ SMBC_fstatdir_ctx(SMBCCTX *context, SMBCFILE *dir, struct stat *st) { - + if (!context || !context->internal->initialized) { - + errno = EINVAL; return -1; } - + /* No code yet ... */ return 0; } @@ -1499,22 +1499,22 @@ SMBC_chmod_ctx(SMBCCTX *context, char *path = NULL; uint16 mode; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); return -1; } - + if (!fname) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + DEBUG(4, ("smbc_chmod(%s, 0%3o)\n", fname, newmode)); - + if (SMBC_parse_path(frame, context, fname, @@ -1529,7 +1529,7 @@ SMBC_chmod_ctx(SMBCCTX *context, TALLOC_FREE(frame); return -1; } - + if (!user || user[0] == (char)0) { user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { @@ -1538,28 +1538,28 @@ SMBC_chmod_ctx(SMBCCTX *context, return -1; } } - + srv = SMBC_server(frame, context, True, server, share, &workgroup, &user, &password); - + if (!srv) { TALLOC_FREE(frame); return -1; /* errno set by SMBC_server */ } - + mode = 0; - + if (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= aRONLY; if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= aARCH; if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= aSYSTEM; if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= aHIDDEN; - + if (!cli_setatr(srv->cli, path, mode, 0)) { errno = SMBC_errno(context, srv->cli); TALLOC_FREE(frame); return -1; } - + TALLOC_FREE(frame); return 0; } @@ -1579,48 +1579,48 @@ SMBC_utimes_ctx(SMBCCTX *context, time_t access_time; time_t write_time; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); return -1; } - + if (!fname) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + if (tbuf == NULL) { access_time = write_time = time(NULL); } else { access_time = tbuf[0].tv_sec; write_time = tbuf[1].tv_sec; } - + if (DEBUGLVL(4)) { char *p; char atimebuf[32]; char mtimebuf[32]; - + strncpy(atimebuf, ctime(&access_time), sizeof(atimebuf) - 1); atimebuf[sizeof(atimebuf) - 1] = '\0'; if ((p = strchr(atimebuf, '\n')) != NULL) { *p = '\0'; } - + strncpy(mtimebuf, ctime(&write_time), sizeof(mtimebuf) - 1); mtimebuf[sizeof(mtimebuf) - 1] = '\0'; if ((p = strchr(mtimebuf, '\n')) != NULL) { *p = '\0'; } - + dbgtext("smbc_utimes(%s, atime = %s mtime = %s)\n", fname, atimebuf, mtimebuf); } - + if (SMBC_parse_path(frame, context, fname, @@ -1635,7 +1635,7 @@ SMBC_utimes_ctx(SMBCCTX *context, TALLOC_FREE(frame); return -1; } - + if (!user || user[0] == (char)0) { user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { @@ -1644,21 +1644,21 @@ SMBC_utimes_ctx(SMBCCTX *context, return -1; } } - + srv = SMBC_server(frame, context, True, server, share, &workgroup, &user, &password); - + if (!srv) { TALLOC_FREE(frame); return -1; /* errno set by SMBC_server */ } - + if (!SMBC_setatr(context, srv, path, 0, access_time, write_time, 0, 0)) { TALLOC_FREE(frame); return -1; /* errno set by SMBC_setatr */ } - + TALLOC_FREE(frame); return 0; } @@ -1681,22 +1681,22 @@ SMBC_unlink_ctx(SMBCCTX *context, struct cli_state *targetcli = NULL; SMBCSRV *srv = NULL; TALLOC_CTX *frame = talloc_stackframe(); - + if (!context || !context->internal->initialized) { - + errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); return -1; - + } - + if (!fname) { errno = EINVAL; TALLOC_FREE(frame); return -1; - + } - + if (SMBC_parse_path(frame, context, fname, @@ -1711,7 +1711,7 @@ SMBC_unlink_ctx(SMBCCTX *context, TALLOC_FREE(frame); return -1; } - + if (!user || user[0] == (char)0) { user = talloc_strdup(frame, smbc_getUser(context)); if (!user) { @@ -1720,16 +1720,16 @@ SMBC_unlink_ctx(SMBCCTX *context, return -1; } } - + srv = SMBC_server(frame, context, True, server, share, &workgroup, &user, &password); - + if (!srv) { TALLOC_FREE(frame); return -1; /* SMBC_server sets errno */ - + } - + /*d_printf(">>>unlink: resolving %s\n", path);*/ if (!cli_resolve_path(frame, "", srv->cli, path, &targetcli, &targetpath)) { @@ -1738,13 +1738,13 @@ SMBC_unlink_ctx(SMBCCTX *context, return -1; } /*d_printf(">>>unlink: resolved path as %s\n", targetpath);*/ - + if (!cli_unlink(targetcli, targetpath)) { - + errno = SMBC_errno(context, targetcli); - + if (errno == EACCES) { /* Check if the file is a directory */ - + int saverr = errno; SMB_OFF_T size = 0; uint16 mode = 0; @@ -1752,39 +1752,39 @@ SMBC_unlink_ctx(SMBCCTX *context, struct timespec access_time_ts; struct timespec change_time_ts; SMB_INO_T ino = 0; - + if (!SMBC_getatr(context, srv, path, &mode, &size, NULL, &access_time_ts, &write_time_ts, &change_time_ts, &ino)) { - + /* Hmmm, bad error ... What? */ - + errno = SMBC_errno(context, targetcli); TALLOC_FREE(frame); return -1; - + } else { - + if (IS_DOS_DIR(mode)) errno = EISDIR; else errno = saverr; /* Restore this */ - + } } - + TALLOC_FREE(frame); return -1; - + } - + TALLOC_FREE(frame); return 0; /* Success ... */ - + } /* @@ -1793,7 +1793,7 @@ SMBC_unlink_ctx(SMBCCTX *context, int SMBC_rename_ctx(SMBCCTX *ocontext, - const char *oname, + const char *oname, SMBCCTX *ncontext, const char *nname) { @@ -1814,24 +1814,24 @@ SMBC_rename_ctx(SMBCCTX *ocontext, struct cli_state *targetcli2 = NULL; SMBCSRV *srv = NULL; TALLOC_CTX *frame = talloc_stackframe(); - + if (!ocontext || !ncontext || !ocontext->internal->initialized || !ncontext->internal->initialized) { - + errno = EINVAL; /* Best I can think of ... */ TALLOC_FREE(frame); return -1; } - + if (!oname || !nname) { errno = EINVAL; TALLOC_FREE(frame); return -1; } - + DEBUG(4, ("smbc_rename(%s,%s)\n", oname, nname)); - + if (SMBC_parse_path(frame, ocontext, oname, @@ -1846,7 +1846,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext, TALLOC_FREE(frame); return -1; } - + if (!user1 || user1[0] == (char)0) { user1 = talloc_strdup(frame, smbc_getUser(ocontext)); if (!user1) { @@ -1855,7 +1855,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext, return -1; } } - + if (SMBC_parse_path(frame, ncontext, nname, @@ -1870,7 +1870,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext, TALLOC_FREE(frame); return -1; } - + if (!user2 || user2[0] == (char)0) { user2 = talloc_strdup(frame, smbc_getUser(ncontext)); if (!user2) { @@ -1879,7 +1879,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext, return -1; } } - + if (strcmp(server1, server2) || strcmp(share1, share2) || strcmp(user1, user2)) { /* Can't rename across file systems, or users?? */ @@ -1887,15 +1887,15 @@ SMBC_rename_ctx(SMBCCTX *ocontext, TALLOC_FREE(frame); return -1; } - + srv = SMBC_server(frame, ocontext, True, server1, share1, &workgroup, &user1, &password1); if (!srv) { TALLOC_FREE(frame); return -1; - + } - + /*d_printf(">>>rename: resolving %s\n", path1);*/ if (!cli_resolve_path(frame, "", srv->cli, path1, &targetcli1, &targetpath1)) { @@ -1912,7 +1912,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext, return -1; } /*d_printf(">>>rename: resolved path as %s\n", targetpath2);*/ - + if (strcmp(targetcli1->desthost, targetcli2->desthost) || strcmp(targetcli1->share, targetcli2->share)) { @@ -1921,21 +1921,21 @@ SMBC_rename_ctx(SMBCCTX *ocontext, TALLOC_FREE(frame); return -1; } - + if (!cli_rename(targetcli1, targetpath1, targetpath2)) { int eno = SMBC_errno(ocontext, targetcli1); - + if (eno != EEXIST || !cli_unlink(targetcli1, targetpath2) || !cli_rename(targetcli1, targetpath1, targetpath2)) { - + errno = eno; TALLOC_FREE(frame); return -1; - + } } - + TALLOC_FREE(frame); return 0; /* Success */ } -- cgit From a6fa0ca3219db5d849ad835fc994cb158c87e02a Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Mon, 10 Mar 2008 04:58:43 +0100 Subject: Use rpccli_srvsvc_NetShareEnumAll in libsmbclient. Guenther (This used to be commit 6aad05f3f12fd6b3276486f60c10f5b3fd3fa17c) --- source3/libsmb/libsmb_dir.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'source3/libsmb/libsmb_dir.c') diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 45db914d18..f836989004 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -261,15 +261,16 @@ net_share_enum_rpc(struct cli_state *cli, { int i; WERROR result; - ENUM_HND enum_hnd; - uint32 info_level = 1; uint32 preferred_len = 0xffffffff; uint32 type; - SRV_SHARE_INFO_CTR ctr; + struct srvsvc_NetShareInfoCtr info_ctr; + struct srvsvc_NetShareCtr1 ctr1; fstring name = ""; fstring comment = ""; struct rpc_pipe_client *pipe_hnd; NTSTATUS nt_status; + uint32_t resume_handle = 0; + uint32_t total_entries = 0; /* Open the server service pipe */ pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &nt_status); @@ -278,34 +279,39 @@ net_share_enum_rpc(struct cli_state *cli, return -1; } + ZERO_STRUCT(info_ctr); + ZERO_STRUCT(ctr1); + + info_ctr.level = 1; + info_ctr.ctr.ctr1 = &ctr1; + /* Issue the NetShareEnum RPC call and retrieve the response */ - init_enum_hnd(&enum_hnd, 0); - result = rpccli_srvsvc_net_share_enum(pipe_hnd, - talloc_tos(), - info_level, - &ctr, - preferred_len, - &enum_hnd); + nt_status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, talloc_tos(), + pipe_hnd->cli->desthost, + &info_ctr, + preferred_len, + &total_entries, + &resume_handle, + &result); /* Was it successful? */ - if (!W_ERROR_IS_OK(result) || ctr.num_entries == 0) { + if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result) || + total_entries == 0) { /* Nope. Go clean up. */ goto done; } /* For each returned entry... */ - for (i = 0; i < ctr.num_entries; i++) { + for (i = 0; i < total_entries; i++) { /* pull out the share name */ - rpcstr_pull_unistr2_fstring( - name, &ctr.share.info1[i].info_1_str.uni_netname); + fstrcpy(name, info_ctr.ctr.ctr1->array[i].name); /* pull out the share's comment */ - rpcstr_pull_unistr2_fstring( - comment, &ctr.share.info1[i].info_1_str.uni_remark); + fstrcpy(comment, info_ctr.ctr.ctr1->array[i].comment); /* Get the type value */ - type = ctr.share.info1[i].info_1.type; + type = info_ctr.ctr.ctr1->array[i].type; /* Add this share to the list */ (*fn)(name, type, comment, state); -- cgit From 2a2188591b5ed922d09dc723adcf10f8b8f5e5a0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Apr 2008 21:56:43 +0200 Subject: Add "desthost" to rpc_pipe_client This reduces the dependency on cli_state (This used to be commit 783afab9c891dd7bcb78895b2a639b6f3a0edf5b) --- source3/libsmb/libsmb_dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/libsmb_dir.c') diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index f836989004..612a8772c0 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -287,7 +287,7 @@ net_share_enum_rpc(struct cli_state *cli, /* Issue the NetShareEnum RPC call and retrieve the response */ nt_status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, talloc_tos(), - pipe_hnd->cli->desthost, + pipe_hnd->desthost, &info_ctr, preferred_len, &total_entries, -- cgit From e73e8297f5484b6c7f525917679414c09a145cf0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Apr 2008 13:51:46 +0200 Subject: Replace cli_rpc_pipe_close by a talloc destructor on rpc_pipe_struct (This used to be commit 99fc3283c4ecc791f5a242bd1983b4352ce3e6cf) --- source3/libsmb/libsmb_dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/libsmb/libsmb_dir.c') diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index 612a8772c0..aea4f103b6 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -319,7 +319,7 @@ net_share_enum_rpc(struct cli_state *cli, done: /* Close the server service pipe */ - cli_rpc_pipe_close(pipe_hnd); + TALLOC_FREE(pipe_hnd); /* Tell 'em if it worked */ return W_ERROR_IS_OK(result) ? 0 : -1; -- cgit From 1335da2a7cc639310e5d389e8e8dbe67c4e7ca25 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jul 2008 11:04:31 +0200 Subject: Refactoring: Change calling conventions for cli_rpc_pipe_open_noauth Pass in ndr_syntax_id instead of pipe_idx, return NTSTATUS (This used to be commit 9abc9dc4dc13bd3e42f98eff64eacf24b51f5779) --- source3/libsmb/libsmb_dir.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/libsmb/libsmb_dir.c') diff --git a/source3/libsmb/libsmb_dir.c b/source3/libsmb/libsmb_dir.c index aea4f103b6..aa313f2c05 100644 --- a/source3/libsmb/libsmb_dir.c +++ b/source3/libsmb/libsmb_dir.c @@ -273,8 +273,9 @@ net_share_enum_rpc(struct cli_state *cli, uint32_t total_entries = 0; /* Open the server service pipe */ - pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SRVSVC, &nt_status); - if (!pipe_hnd) { + nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id, + &pipe_hnd); + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("net_share_enum_rpc pipe open fail!\n")); return -1; } -- cgit