summaryrefslogtreecommitdiff
path: root/source3/libsmb/libsmb_dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb/libsmb_dir.c')
-rw-r--r--source3/libsmb/libsmb_dir.c930
1 files changed, 472 insertions, 458 deletions
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 <server> is really a server name
* or is a workgroup/domain name. If we already have
@@ -588,15 +592,16 @@ 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
* 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 */
}