📄 smbctool.c
字号:
while (new_end > do_list_queue_size) { do_list_queue_size *= 2; DEBUG(4,("enlarging do_list_queue to %d\n", (int)do_list_queue_size)); dlq = SMB_REALLOC(do_list_queue, do_list_queue_size); if (! dlq) { d_printf("failure enlarging do_list_queue to %d bytes\n", (int)do_list_queue_size); reset_do_list_queue(); } else { do_list_queue = dlq; memset(do_list_queue + do_list_queue_size / 2, 0, do_list_queue_size / 2); } } if (do_list_queue) { safe_strcpy_base(do_list_queue + do_list_queue_end, entry, do_list_queue, do_list_queue_size); do_list_queue_end = new_end; DEBUG(4,("added %s to do_list_queue (start=%d, end=%d)\n", entry, (int)do_list_queue_start, (int)do_list_queue_end)); }}static char *do_list_queue_head(void){ return do_list_queue + do_list_queue_start;}static void remove_do_list_queue_head(void){ if (do_list_queue_end > do_list_queue_start) { do_list_queue_start += strlen(do_list_queue_head()) + 1; adjust_do_list_queue(); DEBUG(4,("removed head of do_list_queue (start=%d, end=%d)\n", (int)do_list_queue_start, (int)do_list_queue_end)); }}static int do_list_queue_empty(void){ return (! (do_list_queue && *do_list_queue));}/**************************************************************************** A helper for tool_list.****************************************************************************/static void tool_list_helper(const char *mntpoint, struct stat *f, const char *mask, void *state){ /*if (f is a directory) { if (we want to do directories and we want to do this f) { execute the callback on f } if (recursion is set and f isn't . and it isn't ..) { make sure the name is valid construct a full path out of the name add the full path to the list } return; } if (we want to do this f) { execute the callback on f }*/}/**************************************************************************** A cli_list-like function that executes fn on each directory entry. fn operates on the returned entry name and struct stat.****************************************************************************/int tool_list( char *mask, mode_t mode, void (*fn)(char *, struct stat *), BOOL rec, BOOL dirs){ int dh; pstring dentname; pstring res; struct stat stat; struct smbc_dirent* dent; pstrcpy(res, "smb:"); pstrcat(res, service); pstrcat(res, cur_dir); if ((dh = smbc_opendir(res)) < 1) { d_printf("Error: %s opening %s\n", strerror(errno), res); return 1; } while (dent = smbc_readdir(dh)) { switch(dent->smbc_type) { case SMBC_WORKGROUP: case SMBC_SERVER: case SMBC_FILE_SHARE: case SMBC_PRINTER_SHARE: case SMBC_COMMS_SHARE: case SMBC_IPC_SHARE: break; case SMBC_DIR: if (!dirs) break; case SMBC_FILE: pstrcpy(dentname, res); pstrcat(dentname, dent->name); /*if (mask_match(dent->name, mask, False))*/ if (mask_match(dentname, mask, False)) { if (smbc_stat(dentname, &stat) < 0) { d_printf("> %s - stat error: %s\n", dent->name, strerror(errno)); } else { fn(dent->name, &stat); } } break; case SMBC_LINK: break; } } smbc_closedir(dh);}/**************************************************************************** A helper for do_list.****************************************************************************/static void do_list_helper(const char *mntpoint, file_info *f, const char *mask, void *state){ if (f->mode & aDIR) { if (do_list_dirs && do_this_one(f)) { do_list_fn(f); } if (do_list_recurse && !strequal(f->name,".") && !strequal(f->name,"..")) { pstring mask2; char *p; if (!f->name[0]) { d_printf("Empty dir name returned. Possible server misconfiguration.\n"); return; } pstrcpy(mask2, mntpoint); pstrcat(mask2, mask); p = strrchr_m(mask2,'/'); if (!p) return; p[1] = 0; pstrcat(mask2, f->name); pstrcat(mask2,"/*"); add_to_do_list_queue(mask2); } return; } if (do_this_one(f)) { do_list_fn(f); }}/**************************************************************************** A wrapper around cli_list that adds recursion.****************************************************************************/void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec, BOOL dirs){ static int in_do_list = 0; struct cli_state *targetcli; pstring targetpath; if (in_do_list && rec) { fprintf(stderr, "INTERNAL ERROR: do_list called recursively when the recursive flag is true\n"); exit(1); } in_do_list = 1; do_list_recurse = rec; do_list_dirs = dirs; do_list_fn = fn; if (rec) { init_do_list_queue(); add_to_do_list_queue(mask); while (! do_list_queue_empty()) { /* * Need to copy head so that it doesn't become * invalid inside the call to cli_list. This * would happen if the list were expanded * during the call. * Fix from E. Jay Berkenbilt (ejb@ql.org) */ pstring head; pstrcpy(head, do_list_queue_head()); /* check for dfs */ if ( !cli_resolve_path( "", cli, head, &targetcli, targetpath ) ) { d_printf("do_list: [%s] %s\n", head, cli_errstr(cli)); remove_do_list_queue_head(); continue; } cli_list(targetcli, targetpath, attribute, do_list_helper, NULL); remove_do_list_queue_head(); if ((! do_list_queue_empty()) && (fn == display_finfo)) { char* next_file = do_list_queue_head(); char* save_ch = 0; if ((strlen(next_file) >= 2) && (next_file[strlen(next_file) - 1] == '*') && (next_file[strlen(next_file) - 2] == '/')) { save_ch = next_file + strlen(next_file) - 2; *save_ch = '\0'; } d_printf("\n%s\n",next_file); if (save_ch) { *save_ch = '/'; } } } } else { /* check for dfs */ if ( cli_resolve_path( "", cli, mask, &targetcli, targetpath ) ) { if (cli_list(targetcli, targetpath, attribute, do_list_helper, NULL) == -1) d_printf("%s listing %s\n", cli_errstr(targetcli), targetpath); } else d_printf("do_list: [%s] %s\n", mask, cli_errstr(cli)); } in_do_list = 0; reset_do_list_queue();}/**************************************************************************** Get a directory listing.****************************************************************************/static int cmd_dir(void){ mode_t mode = S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO; pstring mask; pstring buf; char *p=buf; pstrcpy(mask, "smb:"); pstrcat(mask, service); pstrcat(mask, cur_dir); if (next_token_nr(NULL,buf,NULL,sizeof(buf))) pstrcat(mask,buf); else pstrcat(mask,"*"); tool_list(mask, mode, display_stat, recurse, True); return 0;}/**************************************************************************** Get a directory listing.****************************************************************************/static int cmd_du(void){ uint16 attribute = aDIR | aSYSTEM | aHIDDEN; pstring mask; pstring buf; char *p=buf; int rc; dir_total = 0; pstrcpy(mask,cur_dir); if(mask[strlen(mask)-1]!='/') pstrcat(mask,"/"); if (next_token_nr(NULL,buf,NULL,sizeof(buf))) { dos_format(p); if (*p == '/') pstrcpy(mask,p); else pstrcat(mask,p); } else { pstrcat(mask,"*"); } do_list(mask, attribute, do_du, recurse, True); rc = do_dskattr(); d_printf("Total number of bytes: %.0f\n", dir_total); return rc;}/**************************************************************************** Get a file from rname to lname****************************************************************************/static int do_get(char *rname, char *lname, BOOL reget){ int handle = 0, fnum; BOOL newhandle = False; char *data; struct timeval tp_start; int read_size = io_bufsize; /*uint16 attr;*/ struct stat stat; off_t start = 0; off_t nread = 0; int rc = 0; if (lowercase) { strlower_m(lname); } GetTimeOfDay(&tp_start); fnum = smbc_open(rname, O_RDONLY, 0666); if (fnum < 0) { d_printf("%s opening remote file %s\n", strerror(errno), rname); return 1; } if(!strcmp(lname,"-")) { handle = fileno(stdout); } else { if (reget) { handle = sys_open(lname, O_WRONLY|O_CREAT, 0644); if (handle >= 0) { start = sys_lseek(handle, 0, SEEK_END); if (start == -1) { smbc_close(fnum); d_printf("Error seeking local file\n"); return 1; } } } else { handle = sys_open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644); } newhandle = True; } if (handle < 0) { d_printf("Error opening local file %s\n",lname); smbc_close(fnum); return 1; } if (smbc_fstat(fnum, &stat) < 0) { d_printf("%s trying to stat remote file %s\n", strerror(errno), rname); if (newhandle) close(handle); smbc_close(fnum); return 1; } DEBUG(1,("getting file %s of size %.0f as %s ", rname, (double)stat.st_size, lname)); if(!(data = (char *)SMB_MALLOC(read_size))) { d_printf("malloc fail for size %d\n", read_size); if (newhandle) close(handle); smbc_close(fnum); return 1; } if (smbc_lseek(fnum, start, SEEK_SET) < 0) { d_printf("%s trying to lseek remote file %s\n", strerror(errno), rname); if (newhandle) close(handle); smbc_close(fnum); SAFE_FREE(data); return 1; } while (1) { int n = smbc_read(fnum, data, read_size); if (n < 0) { d_printf("%s while reading remote file %s\n", strerror(errno), rname); if (newhandle) close(handle); smbc_close(fnum); SAFE_FREE(data); return 1; } if (n == 0) break; if (writefile(handle,data, n) != n) { d_printf("Error writing local file\n"); rc = 1; break; } nread += n; } if (nread + start < stat.st_size) { DEBUG (1, ("Short read when getting file %s. Only got %ld bytes.\n", rname, (long)nread)); rc = 1; } SAFE_FREE(data); if (smbc_close(fnum) < 0) { d_printf("%s closing remote file %s\n", strerror(errno), rname); rc = 1; } if (newhandle) { close(handle); } /*if (archive_level >= 2 && (attr & aARCH)) { cli_setatr(cli, rname, attr & ~(uint16)aARCH, 0); }*/ { struct timeval tp_end; int this_time; GetTimeOfDay(&tp_end); this_time = (tp_end.tv_sec - tp_start.tv_sec)*1000 + (tp_end.tv_usec - tp_start.tv_usec)/1000; get_total_time_ms += this_time; get_total_size += nread; DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n", nread / (1.024*this_time + 1.0e-4), get_total_size / (1.024*get_total_time_ms))); } return rc;}/**************************************************************************** Get a file.****************************************************************************/static int cmd_get(void){ pstring lname; pstring rname; char *p; pstrcpy(rname, "smb:"); pstrcat(rname, service); pstrcat(rname, cur_dir); p = rname + strlen(rname); if (!next_token_nr(NULL,p,NULL,sizeof(rname)-strlen(rname))) { d_printf("get <filename>\n"); return 1; } pstrcpy(lname,p); next_token_nr(NULL,lname,NULL,sizeof(lname)); /*d_printf("lname: %s, rname: %s\n", lname, rname);*/ return do_get(rname, lname, False);}/**************************************************************************** Do an mget operation on one file.****************************************************************************/static void do_mget(char *name, struct stat *st){ pstring rname; pstring quest; pstring saved_curdir; pstring mget_mask; mode_t mode; if (strequal(name,".") || strequal(name,"..")) return; if (S_ISDIR(st->st_mode)) slprintf(quest,sizeof(pstring)-1, "Get directory %s%s? ", cur_dir, name); else slprintf(quest,sizeof(pstring)-1, "Get file %s%s? ", cur_dir, name); if (prompt && !yesno(quest)) return; if (!S_ISDIR(st->st_mode)) { pstrcpy(rname,"smb:"); pstrcat(rname,service); pstrcat(rname,cur_dir); pstrcat(rname,name); do_get(rname,name, False); return; } /* handle directories */ /* TODO: clean this code up for recursive calls */ pstrcpy(saved_curdir,cur_dir); pstrcat(cur_dir,name); pstrcat(cur_dir,"/"); unix_format(name); if (lowercase) strlower_m(name); if (!directory_exist(name,NULL) && mkdir(name,0777) != 0) { d_printf("failed to create directory %s\n",name); pstrcpy(cur_dir,saved_curdir); return; } if (chdir(name) != 0) { d_printf("failed to chdir to directory %s\n",name); pstrcpy(cur_dir,saved_curdir); return; } pstrcpy(mget_mask,"smb:"); pstrcat(mget_mask,service); pstrcat(mget_mask,cur_dir); pstrcat(mget_mask,"*"); /*d_printf("Calling with mask: %s\n", mget_mask);*/ tool_list(mget_mask, mode, do_mget, recurse, recurse);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -