tdb_fetch_compat: use instead of tdb_fetch.
[kai/samba.git] / source3 / libsmb / libsmb_dir.c
index 6d3da1cd7798f09222b3376150af9c017db470c7..ea75dbf26494d6a1fe9c81020dffd66cfabb93cd 100644 (file)
 */
 
 #include "includes.h"
+#include "libsmb/libsmb.h"
+#include "popt_common.h"
 #include "libsmbclient.h"
 #include "libsmb_internal.h"
-#include "../librpc/gen_ndr/cli_srvsvc.h"
+#include "rpc_client/cli_pipe.h"
+#include "../librpc/gen_ndr/ndr_srvsvc_c.h"
+#include "libsmb/nmblib.h"
 
 /*
  * Routine to open a directory
@@ -146,9 +150,10 @@ list_unique_wg_fn(const char *name,
        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 */
+               /* Change cli_NetServerEnum to take a fn
+                  returning NTSTATUS... JRA. */
        }
 
         /* Point to the one just added */
@@ -226,14 +231,14 @@ list_fn(const char *name,
         }
 
        if (add_dirent(dir, name, comment, dirent_type) < 0) {
-
                /* An error occurred, what do we do? */
                /* FIXME: Add some code here */
-
+               /* Change cli_NetServerEnum to take a fn
+                  returning NTSTATUS... JRA. */
        }
 }
 
-static void
+static NTSTATUS
 dir_list_fn(const char *mnt,
             struct file_info *finfo,
             const char *mask,
@@ -241,14 +246,11 @@ dir_list_fn(const char *mnt,
 {
 
        if (add_dirent((SMBCFILE *)state, finfo->name, "",
-                      (finfo->mode&aDIR?SMBC_DIR:SMBC_FILE)) < 0) {
-
-               /* Handle an error ... */
-
-               /* FIXME: Add some code ... */
-
+                      (finfo->mode&FILE_ATTRIBUTE_DIRECTORY?SMBC_DIR:SMBC_FILE)) < 0) {
+               SMBCFILE *dir = (SMBCFILE *)state;
+               return map_nt_error_from_unix(dir->dir_error);
        }
-
+       return NT_STATUS_OK;
 }
 
 static int
@@ -271,6 +273,7 @@ net_share_enum_rpc(struct cli_state *cli,
         NTSTATUS nt_status;
        uint32_t resume_handle = 0;
        uint32_t total_entries = 0;
+       struct dcerpc_binding_handle *b;
 
         /* Open the server service pipe */
         nt_status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id,
@@ -286,8 +289,10 @@ net_share_enum_rpc(struct cli_state *cli,
        info_ctr.level = 1;
        info_ctr.ctr.ctr1 = &ctr1;
 
+       b = pipe_hnd->binding_handle;
+
         /* Issue the NetShareEnum RPC call and retrieve the response */
-       nt_status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, talloc_tos(),
+       nt_status = dcerpc_srvsvc_NetShareEnumAll(b, talloc_tos(),
                                                  pipe_hnd->desthost,
                                                  &info_ctr,
                                                  preferred_len,
@@ -296,12 +301,23 @@ net_share_enum_rpc(struct cli_state *cli,
                                                  &result);
 
         /* Was it successful? */
-       if (!NT_STATUS_IS_OK(nt_status) || !W_ERROR_IS_OK(result) ||
-           total_entries == 0) {
+       if (!NT_STATUS_IS_OK(nt_status)) {
+                /*  Nope.  Go clean up. */
+               result = ntstatus_to_werror(nt_status);
+               goto done;
+       }
+
+       if (!W_ERROR_IS_OK(result)) {
                 /*  Nope.  Go clean up. */
                goto done;
         }
 
+       if (total_entries == 0) {
+                /*  Nope.  Go clean up. */
+               result = WERR_GENERAL_FAILURE;
+               goto done;
+       }
+
         /* For each returned entry... */
         for (i = 0; i < info_ctr.ctr.ctr1->count; i++) {
 
@@ -369,16 +385,16 @@ SMBC_opendir_ctx(SMBCCTX *context,
 
        if (!context || !context->internal->initialized) {
                DEBUG(4, ("no valid context\n"));
-               errno = EINVAL + 8192;
                TALLOC_FREE(frame);
+               errno = EINVAL + 8192;
                return NULL;
 
        }
 
        if (!fname) {
                DEBUG(4, ("no valid fname\n"));
-               errno = EINVAL + 8193;
                TALLOC_FREE(frame);
+               errno = EINVAL + 8193;
                return NULL;
        }
 
@@ -393,8 +409,8 @@ SMBC_opendir_ctx(SMBCCTX *context,
                             &password,
                             &options)) {
                DEBUG(4, ("no valid path\n"));
-               errno = EINVAL + 8194;
                TALLOC_FREE(frame);
+               errno = EINVAL + 8194;
                return NULL;
        }
 
@@ -405,16 +421,16 @@ SMBC_opendir_ctx(SMBCCTX *context,
         /* 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);
+                errno = EINVAL + 8195;
                 return NULL;
         }
 
        if (!user || user[0] == (char)0) {
                user = talloc_strdup(frame, smbc_getUser(context));
                if (!user) {
-                       errno = ENOMEM;
                        TALLOC_FREE(frame);
+                       errno = ENOMEM;
                        return NULL;
                }
        }
@@ -422,8 +438,8 @@ SMBC_opendir_ctx(SMBCCTX *context,
        dir = SMB_MALLOC_P(SMBCFILE);
 
        if (!dir) {
-               errno = ENOMEM;
                TALLOC_FREE(frame);
+               errno = ENOMEM;
                return NULL;
        }
 
@@ -441,18 +457,19 @@ SMBC_opendir_ctx(SMBCCTX *context,
                 int i;
                 int count;
                 int max_lmb_count;
-                struct ip_service *ip_list;
-                struct ip_service server_addr;
+                struct sockaddr_storage *ip_list;
+                struct sockaddr_storage server_addr;
                 struct user_auth_info u_info;
+               NTSTATUS status;
 
                if (share[0] != (char)0 || path[0] != (char)0) {
 
-                       errno = EINVAL + 8196;
                        if (dir) {
                                SAFE_FREE(dir->fname);
                                SAFE_FREE(dir);
                        }
                        TALLOC_FREE(frame);
+                       errno = EINVAL + 8196;
                        return NULL;
                }
 
@@ -483,28 +500,34 @@ SMBC_opendir_ctx(SMBCCTX *context,
                  */
 
                 ip_list = NULL;
-                if (!NT_STATUS_IS_OK(name_resolve_bcast(MSBROWSE, 1, &ip_list,
-                                                        &count)))
+               status = name_resolve_bcast(MSBROWSE, 1, talloc_tos(),
+                                           &ip_list, &count);
+                if (!NT_STATUS_IS_OK(status))
                {
 
-                        SAFE_FREE(ip_list);
+                        TALLOC_FREE(ip_list);
 
-                        if (!find_master_ip(workgroup, &server_addr.ss)) {
+                        if (!find_master_ip(workgroup, &server_addr)) {
 
                                if (dir) {
                                        SAFE_FREE(dir->fname);
                                        SAFE_FREE(dir);
                                }
-                                errno = ENOENT;
                                TALLOC_FREE(frame);
+                                errno = ENOENT;
                                 return NULL;
                         }
 
-                       ip_list = (struct ip_service *)memdup(
-                               &server_addr, sizeof(server_addr));
+                       ip_list = (struct sockaddr_storage *)talloc_memdup(
+                               talloc_tos(), &server_addr,
+                               sizeof(server_addr));
                        if (ip_list == NULL) {
-                               errno = ENOMEM;
+                               if (dir) {
+                                       SAFE_FREE(dir->fname);
+                                       SAFE_FREE(dir);
+                               }
                                TALLOC_FREE(frame);
+                               errno = ENOMEM;
                                return NULL;
                        }
                         count = 1;
@@ -515,7 +538,7 @@ SMBC_opendir_ctx(SMBCCTX *context,
                        char *wg_ptr = NULL;
                        struct cli_state *cli = NULL;
 
-                       print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
+                       print_sockaddr(addr, sizeof(addr), &ip_list[i]);
                         DEBUG(99, ("Found master browser %d of %d: %s\n",
                                    i+1, MAX(count, max_lmb_count),
                                    addr));
@@ -536,8 +559,12 @@ SMBC_opendir_ctx(SMBCCTX *context,
                         cli_shutdown(cli);
 
                        if (!workgroup || !server) {
-                               errno = ENOMEM;
+                               if (dir) {
+                                       SAFE_FREE(dir->fname);
+                                       SAFE_FREE(dir);
+                               }
                                TALLOC_FREE(frame);
+                               errno = ENOMEM;
                                return NULL;
                        }
 
@@ -571,7 +598,7 @@ SMBC_opendir_ctx(SMBCCTX *context,
                         }
                 }
 
-                SAFE_FREE(ip_list);
+                TALLOC_FREE(ip_list);
         } else {
                 /*
                  * Server not an empty string ... Check the rest and see what
@@ -581,12 +608,12 @@ SMBC_opendir_ctx(SMBCCTX *context,
                        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);
+                               errno = EINVAL + 8197;
                                return NULL;
 
                        }
@@ -644,8 +671,8 @@ SMBC_opendir_ctx(SMBCCTX *context,
                                                SAFE_FREE(dir->fname);
                                                SAFE_FREE(dir);
                                        }
-                                       errno = EPERM;
                                        TALLOC_FREE(frame);
+                                       errno = EPERM;
                                        return NULL;
 
                                }
@@ -793,7 +820,7 @@ SMBC_opendir_ctx(SMBCCTX *context,
                        }
 
                        status = cli_list(targetcli, targetpath,
-                                         aDIR | aSYSTEM | aHIDDEN,
+                                         FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
                                          dir_list_fn, (void *)dir);
                        if (!NT_STATUS_IS_OK(status)) {
                                if (dir) {
@@ -845,8 +872,8 @@ SMBC_opendir_ctx(SMBCCTX *context,
                                         }
                                 }
 
-                                errno = saved_errno;
                                TALLOC_FREE(frame);
+                                errno = saved_errno;
                                return NULL;
                        }
                }
@@ -1049,6 +1076,7 @@ SMBC_getdents_ctx(SMBCCTX *context,
 
        while ((dirlist = dir->dir_next)) {
                struct smbc_dirent *dirent;
+               struct smbc_dirent *currentEntry = (struct smbc_dirent *)ndir;
 
                if (!dirlist->dirent) {
 
@@ -1085,17 +1113,23 @@ SMBC_getdents_ctx(SMBCCTX *context,
 
                }
 
-               memcpy(ndir, dirent, reqd); /* Copy the data in ... */
+               memcpy(currentEntry, dirent, reqd); /* Copy the data in ... */
 
-               ((struct smbc_dirent *)ndir)->comment =
-                       (char *)(&((struct smbc_dirent *)ndir)->name +
-                                 dirent->namelen +
-                                 1);
+               currentEntry->comment = &currentEntry->name[0] +
+                                               dirent->namelen + 1;
 
                ndir += reqd;
-
                rem -= reqd;
 
+               /* Try and align the struct for the next entry
+                  on a valid pointer boundary by appending zeros */
+               while((rem > 0) && ((unsigned long long)ndir & (sizeof(void*) - 1))) {
+                       *ndir = '\0';
+                       rem--;
+                       ndir++;
+                       currentEntry->dirlen++;
+               }
+
                dir->dir_next = dirlist = dirlist -> next;
        }
 
@@ -1203,7 +1237,7 @@ SMBC_mkdir_ctx(SMBCCTX *context,
  * Our list function simply checks to see if a directory is not empty
  */
 
-static void
+static NTSTATUS
 rmdir_list_fn(const char *mnt,
               struct file_info *finfo,
               const char *mask,
@@ -1214,6 +1248,7 @@ rmdir_list_fn(const char *mnt,
                bool *smbc_rmdir_dirempty = (bool *)state;
                *smbc_rmdir_dirempty = false;
         }
+       return NT_STATUS_OK;
 }
 
 /*
@@ -1314,7 +1349,7 @@ SMBC_rmdir_ctx(SMBCCTX *context,
                        }
 
                        status = cli_list(targetcli, lpath,
-                                         aDIR | aSYSTEM | aHIDDEN,
+                                         FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
                                          rmdir_list_fn,
                                          &smbc_rmdir_dirempty);
 
@@ -1580,10 +1615,10 @@ SMBC_chmod_ctx(SMBCCTX *context,
 
        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 (!(newmode & (S_IWUSR | S_IWGRP | S_IWOTH))) mode |= FILE_ATTRIBUTE_READONLY;
+       if ((newmode & S_IXUSR) && lp_map_archive(-1)) mode |= FILE_ATTRIBUTE_ARCHIVE;
+       if ((newmode & S_IXGRP) && lp_map_system(-1)) mode |= FILE_ATTRIBUTE_SYSTEM;
+       if ((newmode & S_IXOTH) && lp_map_hidden(-1)) mode |= FILE_ATTRIBUTE_HIDDEN;
 
        if (!NT_STATUS_IS_OK(cli_setatr(targetcli, targetpath, mode, 0))) {
                errno = SMBC_errno(context, targetcli);
@@ -1772,7 +1807,7 @@ SMBC_unlink_ctx(SMBCCTX *context,
        }
        /*d_printf(">>>unlink: resolved path as %s\n", targetpath);*/
 
-       if (!NT_STATUS_IS_OK(cli_unlink(targetcli, targetpath, aSYSTEM | aHIDDEN))) {
+       if (!NT_STATUS_IS_OK(cli_unlink(targetcli, targetpath, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN))) {
 
                errno = SMBC_errno(context, targetcli);
 
@@ -1978,7 +2013,7 @@ SMBC_rename_ctx(SMBCCTX *ocontext,
                int eno = SMBC_errno(ocontext, targetcli1);
 
                if (eno != EEXIST ||
-                   !NT_STATUS_IS_OK(cli_unlink(targetcli1, targetpath2, aSYSTEM | aHIDDEN)) ||
+                   !NT_STATUS_IS_OK(cli_unlink(targetcli1, targetpath2, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)) ||
                    !NT_STATUS_IS_OK(cli_rename(targetcli1, targetpath1, targetpath2))) {
 
                        errno = eno;