diff options
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/libsmb_dir.c | 736 |
1 files changed, 368 insertions, 368 deletions
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 <http://www.gnu.org/licenses/>. */ @@ -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 <server> is really a server name * or is a workgroup/domain name. If we already have @@ -592,7 +592,7 @@ SMBC_opendir_ctx(SMBCCTX *context, * <server><1B>, or <server><20> translates. We check * to see if <server> 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 */ } |