📄 smbctool.c
字号:
/* Unix SMB/CIFS implementation. SMB client Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Simo Sorce 2001-2002 Copyright (C) Jelmer Vernooij 2003 Copyright (C) Gerald (Jerry) Carter 2004 Copyright (C) Kalim Moghul 2005 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 (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, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "includes.h"#include "libsmbclient.h"#include "client/client_proto.h"#ifndef REGISTER#define REGISTER 0#endifextern BOOL AllowDebugChange;extern BOOL override_logfile;extern char tar_type;extern BOOL in_client;static int port = 0;pstring cur_dir = "/";static pstring service;static pstring desthost;static pstring username;static pstring workgroup;static pstring calling_name;static BOOL grepable=False;static char *cmdstr = NULL;static int io_bufsize = 64512;static int name_type = 0x20;extern int max_protocol;static int process_tok(pstring tok);static int cmd_help(void);/* 30 second timeout on most commands */#define CLIENT_TIMEOUT (30*1000)#define SHORT_TIMEOUT (5*1000)/* value for unused fid field in trans2 secondary request */#define FID_UNUSED (0xFFFF)time_t newer_than = 0;static int archive_level = 0;static BOOL translation = False;static BOOL have_ip;/* clitar bits insert */extern int blocksize;extern BOOL tar_inc;extern BOOL tar_reset;/* clitar bits end */ static BOOL prompt = True;static BOOL recurse = False;BOOL lowercase = False;static struct in_addr dest_ip;#define SEPARATORS " \t\n\r"static BOOL abort_mget = True;static pstring fileselection = "";extern file_info def_finfo;/* timing globals */SMB_BIG_UINT get_total_size = 0;unsigned int get_total_time_ms = 0;static SMB_BIG_UINT put_total_size = 0;static unsigned int put_total_time_ms = 0;/* totals globals */static double dir_total;/* root cli_state connection */struct cli_state *cli;/**************************************************************************** Authentication callback function for libsmbclient ****************************************************************************/static voidget_auth_data_fn(const char * pServer, const char * pShare, char * pWorkgroup, int maxLenWorkgroup, char * pUsername, int maxLenUsername, char * pPassword, int maxLenPassword){ char temp[sizeof(fstring)]; static char authUsername[sizeof(fstring)]; static char authWorkgroup[sizeof(fstring)]; static char authPassword[sizeof(fstring)]; static char authSet = 0; if (authSet) { strncpy(pWorkgroup, authWorkgroup, maxLenWorkgroup - 1); strncpy(pUsername, authUsername, maxLenUsername - 1); strncpy(pPassword, authPassword, maxLenPassword - 1); } else { d_printf("Workgroup: %s\n", workgroup); strncpy(pWorkgroup, workgroup, maxLenWorkgroup - 1); strncpy(authWorkgroup, workgroup, maxLenWorkgroup - 1); d_printf("Username: %s\n", username); strncpy(pUsername, username, maxLenUsername - 1); strncpy(authUsername, username, maxLenUsername - 1); if (cmdline_auth_info.got_pass) { strncpy(pPassword, cmdline_auth_info.password, maxLenPassword - 1); strncpy(authPassword, cmdline_auth_info.password, maxLenPassword - 1); } else { char *pass = getpass("Password: "); if (pass) fstrcpy(temp, pass); if (temp[strlen(temp) - 1] == '\n') /* A new line? */ { temp[strlen(temp) - 1] = '\0'; } if (temp[0] != '\0') { strncpy(pPassword, temp, maxLenPassword - 1); strncpy(authPassword, pPassword, maxLenPassword - 1); } } pstrcpy(cmdline_auth_info.username, authUsername); pstrcpy(cmdline_auth_info.password, authPassword); cmdline_auth_info.got_pass = True; set_global_myworkgroup(authWorkgroup); cli_cm_set_credentials(&cmdline_auth_info); authSet = 1; }}/******************************************************************* Return a string representing an attribute for a file.********************************************************************/fstring *mode_t_string(mode_t mode){ static fstring attrstr; attrstr[0] = 0; S_ISDIR(mode) ? fstrcat(attrstr, "d") : fstrcat(attrstr, "-"); (mode & S_IRUSR) ? fstrcat(attrstr, "r") : fstrcat(attrstr, "-"); (mode & S_IWUSR) ? fstrcat(attrstr, "w") : fstrcat(attrstr, "-"); (mode & S_IXUSR) ? fstrcat(attrstr, "x") : fstrcat(attrstr, "-"); (mode & S_IRGRP) ? fstrcat(attrstr, "r") : fstrcat(attrstr, "-"); (mode & S_IWGRP) ? fstrcat(attrstr, "w") : fstrcat(attrstr, "-"); (mode & S_IXGRP) ? fstrcat(attrstr, "x") : fstrcat(attrstr, "-"); (mode & S_IROTH) ? fstrcat(attrstr, "r") : fstrcat(attrstr, "-"); (mode & S_IWOTH) ? fstrcat(attrstr, "w") : fstrcat(attrstr, "-"); (mode & S_IXOTH) ? fstrcat(attrstr, "x") : fstrcat(attrstr, "-"); return(&attrstr);}/**************************************************************************** Write to a local file with CR/LF->LF translation if appropriate. Return the number taken from the buffer. This may not equal the number written.****************************************************************************/static int writefile(int f, char *b, int n){ int i; if (!translation) { return write(f,b,n); } i = 0; while (i < n) { if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n') { b++;i++; } if (write(f, b, 1) != 1) { break; } b++; i++; } return(i);}/**************************************************************************** Read from a file with LF->CR/LF translation if appropriate. Return the number read. read approx n bytes.****************************************************************************/static int readfile(char *b, int n, XFILE *f){ int i; int c; if (!translation) return x_fread(b,1,n,f); i = 0; while (i < (n - 1) && (i < BUFFER_SIZE)) { if ((c = x_getc(f)) == EOF) { break; } if (c == '\n') { /* change all LFs to CR/LF */ b[i++] = '\r'; } b[i++] = c; } return(i);} /**************************************************************************** Send a message.****************************************************************************/static void send_message(void){ int total_len = 0; int grp_id; if (!cli_message_start(cli, desthost, username, &grp_id)) { d_printf("message start: %s\n", cli_errstr(cli)); return; } d_printf("Connected. Type your message, ending it with a Control-D\n"); while (!feof(stdin) && total_len < 1600) { int maxlen = MIN(1600 - total_len,127); pstring msg; int l=0; int c; ZERO_ARRAY(msg); for (l=0;l<maxlen && (c=fgetc(stdin))!=EOF;l++) { if (c == '\n') msg[l++] = '\r'; msg[l] = c; } if (!cli_message_text(cli, msg, l, grp_id)) { d_printf("SMBsendtxt failed (%s)\n",cli_errstr(cli)); return; } total_len += l; } if (total_len >= 1600) d_printf("the message was truncated to 1600 bytes\n"); else d_printf("sent %d bytes\n",total_len); if (!cli_message_end(cli, grp_id)) { d_printf("SMBsendend failed (%s)\n",cli_errstr(cli)); return; } }/**************************************************************************** Check the space on a device.****************************************************************************/static int do_dskattr(void){ int total, bsize, avail; struct cli_state *targetcli; pstring targetpath; if ( !cli_resolve_path( "", cli, cur_dir, &targetcli, targetpath ) ) { d_printf("Error in dskattr: %s\n", cli_errstr(cli)); return 1; } if (!cli_dskattr(targetcli, &bsize, &total, &avail)) { d_printf("Error in dskattr: %s\n",cli_errstr(targetcli)); return 1; } d_printf("\n\t\t%d blocks of size %d. %d blocks available\n", total, bsize, avail); return 0;}/**************************************************************************** Show cd/pwd.****************************************************************************/static int cmd_pwd(void){ d_printf("Current directory is %s",service); d_printf("%s\n",cur_dir); return 0;}/**************************************************************************** Change directory - inner section.****************************************************************************/static int do_cd(char *newdir){ char *p = newdir; pstring saved_dir; pstring dname; pstring targetpath; struct cli_state *targetcli; SMB_STRUCT_STAT sbuf; uint32 attributes; int dh; unix_format(newdir); /* Save the current directory in case the new directory is invalid */ pstrcpy(saved_dir, cur_dir); pstrcpy(dname, p); /* first save the argument */ if (*p == '/') pstrcpy(cur_dir,dname); else pstrcat(cur_dir,dname); if (*(cur_dir+strlen(cur_dir)-1) != '/') { pstrcat(cur_dir, "/"); } all_string_sub(cur_dir, "/./", "/", 0); /* Format the directory in a libmsmbclient friendly way */ unix_clean_name(cur_dir); all_string_sub(cur_dir, "/./", "/", 0); pstrcpy(targetpath, "smb:"); pstrcat(targetpath, service); pstrcat(targetpath, cur_dir); unix_format(targetpath); dh = smbc_opendir(targetpath); if (dh < 0) { d_printf("%s changing to directory %s\n", strerror(errno), cur_dir); pstrcpy(cur_dir, saved_dir); return 1; } smbc_closedir(dh); return 0;}/**************************************************************************** Change directory.****************************************************************************/static int cmd_cd(void){ pstring buf; int rc = 0; if (next_token_nr(NULL,buf,NULL,sizeof(buf))) rc = do_cd(buf); else d_printf("Current directory is %s\n",cur_dir); return rc;}/******************************************************************* Decide if a file should be operated on.********************************************************************/static BOOL do_this_one(file_info *finfo){ if (finfo->mode & aDIR) return(True); if (*fileselection && !mask_match(finfo->name,fileselection,False)) { DEBUG(3,("mask_match %s failed\n", finfo->name)); return False; } if (newer_than && finfo->mtime < newer_than) { DEBUG(3,("newer_than %s failed\n", finfo->name)); return(False); } if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH)) { DEBUG(3,("archive %s failed\n", finfo->name)); return(False); } return(True);}/**************************************************************************** Display info about a file.****************************************************************************/static void display_finfo(file_info *finfo){ if (do_this_one(finfo)) { time_t t = finfo->mtime; /* the time is assumed to be passed as GMT */ d_printf(" %-30s%7.7s %8.0f %s", finfo->name, attrib_string(finfo->mode), (double)finfo->size, asctime(localtime(&t))); dir_total += finfo->size; }}/**************************************************************************** Display info about a file.****************************************************************************/static void display_stat(char *name, struct stat *st){ time_t t = st->st_mtime; pstring time_str; pstrcpy(time_str, asctime(localtime(&t))); time_str[strlen(time_str)-1] = 0; d_printf("> %-30s", name); d_printf("%10.10s %8.0f %s\n", *mode_t_string(st->st_mode), (double)st->st_size, time_str);}/**************************************************************************** Accumulate size of a file.****************************************************************************/static void do_du(file_info *finfo){ if (do_this_one(finfo)) { dir_total += finfo->size; }}static BOOL do_list_recurse;static BOOL do_list_dirs;static char *do_list_queue = 0;static long do_list_queue_size = 0;static long do_list_queue_start = 0;static long do_list_queue_end = 0;static void (*do_list_fn)(file_info *);static void (*tool_list_fn)(char *, struct stat *);/**************************************************************************** Functions for do_list_queue.****************************************************************************//* * The do_list_queue is a NUL-separated list of strings stored in a * char*. Since this is a FIFO, we keep track of the beginning and * ending locations of the data in the queue. When we overflow, we * double the size of the char*. When the start of the data passes * the midpoint, we move everything back. This is logically more * complex than a linked list, but easier from a memory management * angle. In any memory error condition, do_list_queue is reset. * Functions check to ensure that do_list_queue is non-NULL before * accessing it. */static void reset_do_list_queue(void){ SAFE_FREE(do_list_queue); do_list_queue_size = 0; do_list_queue_start = 0; do_list_queue_end = 0;}static void init_do_list_queue(void){ reset_do_list_queue(); do_list_queue_size = 1024; do_list_queue = SMB_MALLOC(do_list_queue_size); if (do_list_queue == 0) { d_printf("malloc fail for size %d\n", (int)do_list_queue_size); reset_do_list_queue(); } else { memset(do_list_queue, 0, do_list_queue_size); }}static void adjust_do_list_queue(void){ /* * 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)) { DEBUG(4,("do_list_queue is empty\n")); do_list_queue_start = do_list_queue_end = 0; *do_list_queue = '\0'; } else if (do_list_queue_start > (do_list_queue_size / 2)) { DEBUG(4,("sliding do_list_queue backward\n")); memmove(do_list_queue, do_list_queue + do_list_queue_start, do_list_queue_end - do_list_queue_start); do_list_queue_end -= do_list_queue_start; do_list_queue_start = 0; }}static void add_to_do_list_queue(const char* entry){ char *dlq; long new_end = do_list_queue_end + ((long)strlen(entry)) + 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -