r23792: convert Samba4 to GPLv3
[samba.git] / source4 / client / client.c
index f4e85a4ea6f00d2dfdabfe1c696a51cd3029ac72..2882e625969cc35f124893a4f94ac8bc81ceabd8 100644 (file)
@@ -8,7 +8,7 @@
    
    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 2 of the License, or
+   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,
    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, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "version.h"
 #include "libcli/libcli.h"
 #include "lib/cmdline/popt_common.h"
-#include "librpc/gen_ndr/ndr_srvsvc.h"
+#include "librpc/gen_ndr/ndr_srvsvc_c.h"
 #include "librpc/gen_ndr/ndr_lsa.h"
+#include "librpc/gen_ndr/ndr_security.h"
 #include "libcli/raw/libcliraw.h"
+#include "libcli/util/clilsa.h"
 #include "system/dir.h"
 #include "system/filesys.h"
-#include "dlinklist.h"
+#include "lib/util/dlinklist.h"
 #include "system/readline.h"
+#include "auth/credentials/credentials.h"
 #include "auth/gensec/gensec.h"
 #include "system/time.h" /* needed by some systems for asctime() */
+#include "libcli/resolve/resolve.h"
+#include "libcli/security/security.h"
+#include "lib/smbreadline/smbreadline.h"
+#include "librpc/gen_ndr/ndr_nbt.h"
 
 static int io_bufsize = 64512;
 
@@ -74,8 +80,6 @@ void dos_clean_name(char *s)
        /* remove any double slashes */
        all_string_sub(s, "\\\\", "\\", 0);
 
-       all_string_sub(s, "/", "\\", 0);
-
        while ((p = strstr(s,"\\..\\")) != NULL) {
                *p = '\0';
                if ((r = strrchr(s,'\\')) != NULL)
@@ -282,9 +286,9 @@ BOOL mask_match(struct smbcli_state *c, const char *string, const char *pattern,
        char *p2, *s2;
        BOOL ret;
 
-       if (strcmp(string,"..") == 0)
+       if (ISDOTDOT(string))
                string = ".";
-       if (strcmp(pattern,".") == 0)
+       if (ISDOT(pattern))
                return False;
        
        if (is_case_sensitive)
@@ -404,11 +408,13 @@ static void init_do_list_queue(void)
 
 static void adjust_do_list_queue(void)
 {
+       if (do_list_queue == NULL) return;
+
        /*
         * If the starting point of the queue is more than half way through,
         * move everything toward the beginning.
         */
-       if (do_list_queue && (do_list_queue_start == do_list_queue_end))
+       if (do_list_queue_start == do_list_queue_end)
        {
                DEBUG(4,("do_list_queue is empty\n"));
                do_list_queue_start = do_list_queue_end = 0;
@@ -491,8 +497,8 @@ static void do_list_helper(struct clilist_file_info *f, const char *mask, void *
                        do_list_fn(ctx, f);
                }
                if (do_list_recurse && 
-                   !strequal(f->name,".") && 
-                   !strequal(f->name,"..")) {
+                   !ISDOT(f->name) &&
+                   !ISDOTDOT(f->name)) {
                        char *mask2;
                        char *p;
 
@@ -832,7 +838,7 @@ static void do_mget(struct smbclient_context *ctx, struct clilist_file_info *fin
        char *mget_mask;
        char *saved_curdir;
 
-       if (strequal(finfo->name,".") || strequal(finfo->name,".."))
+       if (ISDOT(finfo->name) || ISDOTDOT(finfo->name))
                return;
 
        if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY)
@@ -929,7 +935,7 @@ do a mget command
 static int cmd_mget(struct smbclient_context *ctx, const char **args)
 {
        uint16_t attribute = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
-       char *mget_mask;
+       char *mget_mask = NULL;
        int i;
 
        if (ctx->recurse)
@@ -944,14 +950,15 @@ static int cmd_mget(struct smbclient_context *ctx, const char **args)
                if (mget_mask[0] != '\\')
                        mget_mask = talloc_append_string(ctx, mget_mask, "\\");
                do_list(ctx, mget_mask, attribute,do_mget,False,True);
+
+               talloc_free(mget_mask);
        }
 
-       if (!*mget_mask) {
+       if (mget_mask == NULL) {
                mget_mask = talloc_asprintf(ctx, "%s\\*", ctx->remote_cur_dir);
                do_list(ctx, mget_mask, attribute,do_mget,False,True);
+               talloc_free(mget_mask);
        }
-
-       talloc_free(mget_mask);
        
        return 0;
 }
@@ -991,7 +998,7 @@ static int cmd_quit(struct smbclient_context *ctx, const char **args)
   ****************************************************************************/
 static int cmd_mkdir(struct smbclient_context *ctx, const char **args)
 {
-       char *mask;
+       char *mask, *p;
   
        if (!args[1]) {
                if (!ctx->recurse)
@@ -1002,28 +1009,20 @@ static int cmd_mkdir(struct smbclient_context *ctx, const char **args)
        mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir,args[1]);
 
        if (ctx->recurse) {
-               int i;
-               const char **els;
-               char *parent = NULL;
                dos_clean_name(mask);
 
                trim_string(mask,".",NULL);
-
-               els = str_list_make(ctx, mask, "/\\");
-
-               for (i = 0; els[i]; i++) {
-                       parent = talloc_asprintf_append(parent, "%s\\", els[i]);
+               for (p = strtok(mask,"/\\"); p; p = strtok(p, "/\\")) {
+                       char *parent = talloc_strndup(ctx, mask, PTR_DIFF(p, mask));
                        
                        if (NT_STATUS_IS_ERR(smbcli_chkpath(ctx->cli->tree, parent))) { 
                                do_mkdir(ctx, parent);
                        }
-               }        
-
 
-               talloc_free(parent);
+                       talloc_free(parent);
+               }        
        } else {
-               if (NT_STATUS_IS_ERR(do_mkdir(ctx, mask)))
-                       return 1;
+               do_mkdir(ctx, mask);
        }
        
        return 0;
@@ -1195,16 +1194,16 @@ static int cmd_put(struct smbclient_context *ctx, const char **args)
        char *rname;
        
        if (!args[1]) {
-               d_printf("put <filename>\n");
+               d_printf("put <filename> [<remotename>]\n");
                return 1;
        }
 
-       lname = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, args[1]);
+       lname = talloc_strdup(ctx, args[1]);
   
        if (args[2])
                rname = talloc_strdup(ctx, args[2]);
        else
-               rname = talloc_strdup(ctx, lname);
+               rname = talloc_asprintf(ctx, "%s\\%s", ctx->remote_cur_dir, lname);
        
        dos_clean_name(rname);
 
@@ -1329,8 +1328,9 @@ static int file_find(struct smbclient_context *ctx, struct file_list **list, con
        if (!dir) return -1;
        
         while ((dname = readdirname(dir))) {
-               if (!strcmp("..", dname)) continue;
-               if (!strcmp(".", dname)) continue;
+               if (ISDOT(dname) || ISDOTDOT(dname)) {
+                       continue;
+               }
                
                if (asprintf(&path, "%s/%s", directory, dname) <= 0) {
                        continue;
@@ -1703,11 +1703,11 @@ static int cmd_fsinfo(struct smbclient_context *ctx, const char **args)
                         GUID_string(ctx,&fsinfo.objectid_information.out.guid));
                d_printf("\tunknown[6]:                 [%llu,%llu,%llu,%llu,%llu,%llu]\n", 
                         (unsigned long long) fsinfo.objectid_information.out.unknown[0],
+                        (unsigned long long) fsinfo.objectid_information.out.unknown[1],
                         (unsigned long long) fsinfo.objectid_information.out.unknown[2],
                         (unsigned long long) fsinfo.objectid_information.out.unknown[3],
                         (unsigned long long) fsinfo.objectid_information.out.unknown[4],
-                        (unsigned long long) fsinfo.objectid_information.out.unknown[5],
-                        (unsigned long long) fsinfo.objectid_information.out.unknown[6] );
+                        (unsigned long long) fsinfo.objectid_information.out.unknown[5] );
                break;
        case RAW_QFS_GENERIC:
                d_printf("\twrong level returned\n");
@@ -1725,6 +1725,7 @@ static int cmd_allinfo(struct smbclient_context *ctx, const char **args)
        char *fname;
        union smb_fileinfo finfo;
        NTSTATUS status;
+       int fnum;
 
        if (!args[1]) {
                d_printf("allinfo <filename>\n");
@@ -1734,7 +1735,7 @@ static int cmd_allinfo(struct smbclient_context *ctx, const char **args)
 
        /* first a ALL_INFO QPATHINFO */
        finfo.generic.level = RAW_FILEINFO_ALL_INFO;
-       finfo.generic.in.fname = fname;
+       finfo.generic.in.file.path = fname;
        status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("%s - %s\n", fname, nt_errstr(status));
@@ -1808,6 +1809,41 @@ static int cmd_allinfo(struct smbclient_context *ctx, const char **args)
                d_printf("\tcluster_shift   %ld\n", (long)finfo.compression_info.out.cluster_shift);
        }
 
+       /* shadow copies if available */
+       fnum = smbcli_open(ctx->cli->tree, fname, O_RDONLY, DENY_NONE);
+       if (fnum != -1) {
+               struct smb_shadow_copy info;
+               int i;
+               info.in.file.fnum = fnum;
+               info.in.max_data = ~0;
+               status = smb_raw_shadow_data(ctx->cli->tree, ctx, &info);
+               if (NT_STATUS_IS_OK(status)) {
+                       d_printf("\tshadow_copy: %u volumes  %u names\n",
+                                info.out.num_volumes, info.out.num_names);
+                       for (i=0;i<info.out.num_names;i++) {
+                               d_printf("\t%s\n", info.out.names[i]);
+                               finfo.generic.level = RAW_FILEINFO_ALL_INFO;
+                               finfo.generic.in.file.path = talloc_asprintf(ctx, "%s%s", 
+                                                                            info.out.names[i], fname); 
+                               status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
+                               if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND) ||
+                                   NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+                                       continue;
+                               }
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       d_printf("%s - %s\n", finfo.generic.in.file.path, 
+                                                nt_errstr(status));
+                                       return 1;
+                               }
+                               
+                               d_printf("\t\tcreate_time:    %s\n", nt_time_string(ctx, finfo.all_info.out.create_time));
+                               d_printf("\t\twrite_time:     %s\n", nt_time_string(ctx, finfo.all_info.out.write_time));
+                               d_printf("\t\tchange_time:    %s\n", nt_time_string(ctx, finfo.all_info.out.change_time));
+                               d_printf("\t\tsize:           %lu\n", (unsigned long)finfo.all_info.out.size);
+                       }
+               }
+       }
+       
        return 0;
 }
 
@@ -1828,8 +1864,8 @@ static int cmd_eainfo(struct smbclient_context *ctx, const char **args)
        }
        fname = talloc_strdup(ctx, args[1]);
 
-       finfo.generic.in.fname = fname;
        finfo.generic.level = RAW_FILEINFO_ALL_EAS;
+       finfo.generic.in.file.path = fname;
        status = smb_raw_pathinfo(ctx->cli->tree, ctx, &finfo);
        
        if (!NT_STATUS_IS_OK(status)) {
@@ -1884,8 +1920,8 @@ static int cmd_acl(struct smbclient_context *ctx, const char **args)
        }
 
        query.query_secdesc.level = RAW_FILEINFO_SEC_DESC;
-       query.query_secdesc.in.fnum = fnum;
-       query.query_secdesc.secinfo_flags = 0x7;
+       query.query_secdesc.in.file.fnum = fnum;
+       query.query_secdesc.in.secinfo_flags = 0x7;
 
        status = smb_raw_fileinfo(ctx->cli->tree, ctx, &query);
        if (!NT_STATUS_IS_OK(status)) {
@@ -2094,13 +2130,10 @@ static int cmd_rmdir(struct smbclient_context *ctx, const char **args)
                return 1;
        }
        mask = talloc_asprintf(ctx, "%s%s", ctx->remote_cur_dir, args[1]);
-       
-       dos_clean_name(mask);
 
        if (NT_STATUS_IS_ERR(smbcli_rmdir(ctx->cli->tree, mask))) {
-               d_printf("%s removing remote directory %s\n",
+               d_printf("%s removing remote directory file %s\n",
                         smbcli_errstr(ctx->cli->tree),mask);
-               return 1;
        }
        
        return 0;
@@ -2190,7 +2223,7 @@ static int cmd_chmod(struct smbclient_context *ctx, const char **args)
 
        if (NT_STATUS_IS_ERR(smbcli_unix_chmod(ctx->cli->tree, src, mode))) {
                d_printf("%s chmod file %s 0%o\n",
-                       smbcli_errstr(ctx->cli->tree), src, (uint_t)mode);
+                       smbcli_errstr(ctx->cli->tree), src, (mode_t)mode);
                return 1;
        } 
 
@@ -2391,7 +2424,7 @@ history
 ****************************************************************************/
 static int cmd_history(struct smbclient_context *ctx, const char **args)
 {
-#if defined(HAVE_LIBREADLINE)
+#if defined(HAVE_LIBREADLINE) && defined(HAVE_HISTORY_LIST)
        HIST_ENTRY **hlist;
        int i;
 
@@ -2705,8 +2738,7 @@ process a -c command string
 static int process_command_string(struct smbclient_context *ctx, const char *cmd)
 {
        const char **lines;
-       int i;
-       int rc = 0;
+       int i, rc = 0;
 
        lines = str_list_make(NULL, cmd, ";");
        for (i = 0; lines[i]; i++) {
@@ -2731,7 +2763,7 @@ static void completion_remote_filter(struct clilist_file_info *f, const char *ma
 {
        completion_remote_t *info = (completion_remote_t *)state;
 
-       if ((info->count < MAX_COMPLETIONS - 1) && (strncmp(info->text, f->name, info->len) == 0) && (strcmp(f->name, ".") != 0) && (strcmp(f->name, "..") != 0)) {
+       if ((info->count < MAX_COMPLETIONS - 1) && (strncmp(info->text, f->name, info->len) == 0) && (!ISDOT(f->name)) && (!ISDOTDOT(f->name))) {
                if ((info->dirmask[0] == 0) && !(f->attrib & FILE_ATTRIBUTE_DIRECTORY))
                        info->matches[info->count] = strdup(f->name);
                else {
@@ -2950,12 +2982,9 @@ static int process_stdin(struct smbclient_context *ctx)
 {
        int rc = 0;
        while (1) {
-               char *the_prompt;
-               char *cline;
-               
                /* display a prompt */
-               the_prompt = talloc_asprintf(ctx, "smb: %s> ", ctx->remote_cur_dir);
-               cline = smb_readline(the_prompt, readline_callback, completion_fn);
+               char *the_prompt = talloc_asprintf(ctx, "smb: %s> ", ctx->remote_cur_dir);
+               char *cline = smb_readline(the_prompt, readline_callback, completion_fn);
                talloc_free(the_prompt);
                        
                if (!cline) break;
@@ -2966,7 +2995,7 @@ static int process_stdin(struct smbclient_context *ctx)
                        continue;
                }
 
-               rc |= process_line(ctx, cline); 
+               rc |= process_command_string(ctx, cline); 
        }
 
        return rc;
@@ -2977,25 +3006,31 @@ static int process_stdin(struct smbclient_context *ctx)
 return a connection to a server
 *******************************************************/
 static struct smbclient_context *do_connect(TALLOC_CTX *mem_ctx, 
-                                      const char *server, const char *share, struct cli_credentials *cred)
+                                      const char *specified_server, const char *specified_share, struct cli_credentials *cred)
 {
        NTSTATUS status;
        struct smbclient_context *ctx = talloc_zero(mem_ctx, struct smbclient_context);
+       char *server, *share;
+
        if (!ctx) {
                return NULL;
        }
 
        rl_ctx = ctx; /* Ugly hack */
 
-       if (strncmp(share, "\\\\", 2) == 0 ||
-           strncmp(share, "//", 2) == 0) {
-               smbcli_parse_unc(share, ctx, &server, &share);
+       if (strncmp(specified_share, "\\\\", 2) == 0 ||
+           strncmp(specified_share, "//", 2) == 0) {
+               smbcli_parse_unc(specified_share, ctx, &server, &share);
+       } else {
+               share = talloc_strdup(ctx, specified_share);
+               server = talloc_strdup(ctx, specified_server);
        }
 
        ctx->remote_cur_dir = talloc_strdup(ctx, "\\");
        
        status = smbcli_full_connection(ctx, &ctx->cli, server,
-                                       share, NULL, cred, NULL);
+                                       share, NULL, cred, 
+                                       cli_credentials_get_event_context(cred));
        if (!NT_STATUS_IS_OK(status)) {
                d_printf("Connection to \\\\%s\\%s failed - %s\n", 
                         server, share, nt_errstr(status));
@@ -3056,11 +3091,11 @@ static int do_message_op(const char *desthost, const char *destip, int name_type
  int main(int argc,char *argv[])
 {
        const char *base_directory = NULL;
-       const char *dest_ip;
+       const char *dest_ip = NULL;
        int opt;
        const char *query_host = NULL;
        BOOL message = False;
-       const char *desthost;
+       const char *desthost = NULL;
 #ifdef KANJI
        const char *term_code = KANJI;
 #else
@@ -3092,7 +3127,7 @@ static int do_message_op(const char *desthost, const char *destip, int name_type
                POPT_COMMON_CONNECTION
                POPT_COMMON_CREDENTIALS
                POPT_COMMON_VERSION
-               POPT_TABLEEND
+               { NULL }
        };
        
        mem_ctx = talloc_init("client.c/main");