| 1 | /*
 | 
|---|
| 2 |    Unix SMB/CIFS implementation.
 | 
|---|
| 3 |    SMB client
 | 
|---|
| 4 |    Copyright (C) Andrew Tridgell          1994-1998
 | 
|---|
| 5 |    Copyright (C) Simo Sorce               2001-2002
 | 
|---|
| 6 |    Copyright (C) Jelmer Vernooij          2003
 | 
|---|
| 7 |    Copyright (C) Gerald (Jerry) Carter    2004
 | 
|---|
| 8 |    Copyright (C) Jeremy Allison           1994-2007
 | 
|---|
| 9 | 
 | 
|---|
| 10 |    This program is free software; you can redistribute it and/or modify
 | 
|---|
| 11 |    it under the terms of the GNU General Public License as published by
 | 
|---|
| 12 |    the Free Software Foundation; either version 3 of the License, or
 | 
|---|
| 13 |    (at your option) any later version.
 | 
|---|
| 14 | 
 | 
|---|
| 15 |    This program is distributed in the hope that it will be useful,
 | 
|---|
| 16 |    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 17 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 18 |    GNU General Public License for more details.
 | 
|---|
| 19 | 
 | 
|---|
| 20 |    You should have received a copy of the GNU General Public License
 | 
|---|
| 21 |    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
|---|
| 22 | */
 | 
|---|
| 23 | 
 | 
|---|
| 24 | #include "includes.h"
 | 
|---|
| 25 | #include "client/client_proto.h"
 | 
|---|
| 26 | #include "../librpc/gen_ndr/cli_srvsvc.h"
 | 
|---|
| 27 | 
 | 
|---|
| 28 | #ifndef REGISTER
 | 
|---|
| 29 | #define REGISTER 0
 | 
|---|
| 30 | #endif
 | 
|---|
| 31 | 
 | 
|---|
| 32 | extern int do_smb_browse(void); /* mDNS browsing */
 | 
|---|
| 33 | 
 | 
|---|
| 34 | extern bool AllowDebugChange;
 | 
|---|
| 35 | extern bool override_logfile;
 | 
|---|
| 36 | extern char tar_type;
 | 
|---|
| 37 | 
 | 
|---|
| 38 | static int port = 0;
 | 
|---|
| 39 | static char *service;
 | 
|---|
| 40 | static char *desthost;
 | 
|---|
| 41 | static char *calling_name;
 | 
|---|
| 42 | static bool grepable = false;
 | 
|---|
| 43 | static char *cmdstr = NULL;
 | 
|---|
| 44 | const char *cmd_ptr = NULL;
 | 
|---|
| 45 | 
 | 
|---|
| 46 | static int io_bufsize = 524288;
 | 
|---|
| 47 | 
 | 
|---|
| 48 | static int name_type = 0x20;
 | 
|---|
| 49 | static int max_protocol = PROTOCOL_NT1;
 | 
|---|
| 50 | 
 | 
|---|
| 51 | static int process_tok(char *tok);
 | 
|---|
| 52 | static int cmd_help(void);
 | 
|---|
| 53 | 
 | 
|---|
| 54 | #define CREATE_ACCESS_READ READ_CONTROL_ACCESS
 | 
|---|
| 55 | 
 | 
|---|
| 56 | /* 30 second timeout on most commands */
 | 
|---|
| 57 | #define CLIENT_TIMEOUT (30*1000)
 | 
|---|
| 58 | #define SHORT_TIMEOUT (5*1000)
 | 
|---|
| 59 | 
 | 
|---|
| 60 | /* value for unused fid field in trans2 secondary request */
 | 
|---|
| 61 | #define FID_UNUSED (0xFFFF)
 | 
|---|
| 62 | 
 | 
|---|
| 63 | time_t newer_than = 0;
 | 
|---|
| 64 | static int archive_level = 0;
 | 
|---|
| 65 | 
 | 
|---|
| 66 | static bool translation = false;
 | 
|---|
| 67 | static bool have_ip;
 | 
|---|
| 68 | 
 | 
|---|
| 69 | /* clitar bits insert */
 | 
|---|
| 70 | extern int blocksize;
 | 
|---|
| 71 | extern bool tar_inc;
 | 
|---|
| 72 | extern bool tar_reset;
 | 
|---|
| 73 | /* clitar bits end */
 | 
|---|
| 74 | 
 | 
|---|
| 75 | static bool prompt = true;
 | 
|---|
| 76 | 
 | 
|---|
| 77 | static bool recurse = false;
 | 
|---|
| 78 | static bool showacls = false;
 | 
|---|
| 79 | bool lowercase = false;
 | 
|---|
| 80 | 
 | 
|---|
| 81 | static struct sockaddr_storage dest_ss;
 | 
|---|
| 82 | static char dest_ss_str[INET6_ADDRSTRLEN];
 | 
|---|
| 83 | 
 | 
|---|
| 84 | #define SEPARATORS " \t\n\r"
 | 
|---|
| 85 | 
 | 
|---|
| 86 | static bool abort_mget = true;
 | 
|---|
| 87 | 
 | 
|---|
| 88 | /* timing globals */
 | 
|---|
| 89 | uint64_t get_total_size = 0;
 | 
|---|
| 90 | unsigned int get_total_time_ms = 0;
 | 
|---|
| 91 | static uint64_t put_total_size = 0;
 | 
|---|
| 92 | static unsigned int put_total_time_ms = 0;
 | 
|---|
| 93 | 
 | 
|---|
| 94 | /* totals globals */
 | 
|---|
| 95 | static double dir_total;
 | 
|---|
| 96 | 
 | 
|---|
| 97 | /* encrypted state. */
 | 
|---|
| 98 | static bool smb_encrypt;
 | 
|---|
| 99 | 
 | 
|---|
| 100 | /* root cli_state connection */
 | 
|---|
| 101 | 
 | 
|---|
| 102 | struct cli_state *cli;
 | 
|---|
| 103 | 
 | 
|---|
| 104 | static char CLI_DIRSEP_CHAR = '\\';
 | 
|---|
| 105 | static char CLI_DIRSEP_STR[] = { '\\', '\0' };
 | 
|---|
| 106 | 
 | 
|---|
| 107 | /* Authentication for client connections. */
 | 
|---|
| 108 | struct user_auth_info *auth_info;
 | 
|---|
| 109 | 
 | 
|---|
| 110 | /* Accessor functions for directory paths. */
 | 
|---|
| 111 | static char *fileselection;
 | 
|---|
| 112 | static const char *client_get_fileselection(void)
 | 
|---|
| 113 | {
 | 
|---|
| 114 |         if (fileselection) {
 | 
|---|
| 115 |                 return fileselection;
 | 
|---|
| 116 |         }
 | 
|---|
| 117 |         return "";
 | 
|---|
| 118 | }
 | 
|---|
| 119 | 
 | 
|---|
| 120 | static const char *client_set_fileselection(const char *new_fs)
 | 
|---|
| 121 | {
 | 
|---|
| 122 |         SAFE_FREE(fileselection);
 | 
|---|
| 123 |         if (new_fs) {
 | 
|---|
| 124 |                 fileselection = SMB_STRDUP(new_fs);
 | 
|---|
| 125 |         }
 | 
|---|
| 126 |         return client_get_fileselection();
 | 
|---|
| 127 | }
 | 
|---|
| 128 | 
 | 
|---|
| 129 | static char *cwd;
 | 
|---|
| 130 | static const char *client_get_cwd(void)
 | 
|---|
| 131 | {
 | 
|---|
| 132 |         if (cwd) {
 | 
|---|
| 133 |                 return cwd;
 | 
|---|
| 134 |         }
 | 
|---|
| 135 |         return CLI_DIRSEP_STR;
 | 
|---|
| 136 | }
 | 
|---|
| 137 | 
 | 
|---|
| 138 | static const char *client_set_cwd(const char *new_cwd)
 | 
|---|
| 139 | {
 | 
|---|
| 140 |         SAFE_FREE(cwd);
 | 
|---|
| 141 |         if (new_cwd) {
 | 
|---|
| 142 |                 cwd = SMB_STRDUP(new_cwd);
 | 
|---|
| 143 |         }
 | 
|---|
| 144 |         return client_get_cwd();
 | 
|---|
| 145 | }
 | 
|---|
| 146 | 
 | 
|---|
| 147 | static char *cur_dir;
 | 
|---|
| 148 | const char *client_get_cur_dir(void)
 | 
|---|
| 149 | {
 | 
|---|
| 150 |         if (cur_dir) {
 | 
|---|
| 151 |                 return cur_dir;
 | 
|---|
| 152 |         }
 | 
|---|
| 153 |         return CLI_DIRSEP_STR;
 | 
|---|
| 154 | }
 | 
|---|
| 155 | 
 | 
|---|
| 156 | const char *client_set_cur_dir(const char *newdir)
 | 
|---|
| 157 | {
 | 
|---|
| 158 |         SAFE_FREE(cur_dir);
 | 
|---|
| 159 |         if (newdir) {
 | 
|---|
| 160 |                 cur_dir = SMB_STRDUP(newdir);
 | 
|---|
| 161 |         }
 | 
|---|
| 162 |         return client_get_cur_dir();
 | 
|---|
| 163 | }
 | 
|---|
| 164 | 
 | 
|---|
| 165 | /****************************************************************************
 | 
|---|
| 166 |  Write to a local file with CR/LF->LF translation if appropriate. Return the
 | 
|---|
| 167 |  number taken from the buffer. This may not equal the number written.
 | 
|---|
| 168 | ****************************************************************************/
 | 
|---|
| 169 | 
 | 
|---|
| 170 | static int writefile(int f, char *b, int n)
 | 
|---|
| 171 | {
 | 
|---|
| 172 |         int i;
 | 
|---|
| 173 | 
 | 
|---|
| 174 |         if (!translation) {
 | 
|---|
| 175 |                 return write(f,b,n);
 | 
|---|
| 176 |         }
 | 
|---|
| 177 | 
 | 
|---|
| 178 |         i = 0;
 | 
|---|
| 179 |         while (i < n) {
 | 
|---|
| 180 |                 if (*b == '\r' && (i<(n-1)) && *(b+1) == '\n') {
 | 
|---|
| 181 |                         b++;i++;
 | 
|---|
| 182 |                 }
 | 
|---|
| 183 |                 if (write(f, b, 1) != 1) {
 | 
|---|
| 184 |                         break;
 | 
|---|
| 185 |                 }
 | 
|---|
| 186 |                 b++;
 | 
|---|
| 187 |                 i++;
 | 
|---|
| 188 |         }
 | 
|---|
| 189 | 
 | 
|---|
| 190 |         return(i);
 | 
|---|
| 191 | }
 | 
|---|
| 192 | 
 | 
|---|
| 193 | /****************************************************************************
 | 
|---|
| 194 |  Read from a file with LF->CR/LF translation if appropriate. Return the
 | 
|---|
| 195 |  number read. read approx n bytes.
 | 
|---|
| 196 | ****************************************************************************/
 | 
|---|
| 197 | 
 | 
|---|
| 198 | static int readfile(uint8_t *b, int n, XFILE *f)
 | 
|---|
| 199 | {
 | 
|---|
| 200 |         int i;
 | 
|---|
| 201 |         int c;
 | 
|---|
| 202 | 
 | 
|---|
| 203 |         if (!translation)
 | 
|---|
| 204 |                 return x_fread(b,1,n,f);
 | 
|---|
| 205 | 
 | 
|---|
| 206 |         i = 0;
 | 
|---|
| 207 |         while (i < (n - 1) && (i < BUFFER_SIZE)) {
 | 
|---|
| 208 |                 if ((c = x_getc(f)) == EOF) {
 | 
|---|
| 209 |                         break;
 | 
|---|
| 210 |                 }
 | 
|---|
| 211 | 
 | 
|---|
| 212 |                 if (c == '\n') { /* change all LFs to CR/LF */
 | 
|---|
| 213 |                         b[i++] = '\r';
 | 
|---|
| 214 |                 }
 | 
|---|
| 215 | 
 | 
|---|
| 216 |                 b[i++] = c;
 | 
|---|
| 217 |         }
 | 
|---|
| 218 | 
 | 
|---|
| 219 |         return(i);
 | 
|---|
| 220 | }
 | 
|---|
| 221 | 
 | 
|---|
| 222 | struct push_state {
 | 
|---|
| 223 |         XFILE *f;
 | 
|---|
| 224 |         SMB_OFF_T nread;
 | 
|---|
| 225 | };
 | 
|---|
| 226 | 
 | 
|---|
| 227 | static size_t push_source(uint8_t *buf, size_t n, void *priv)
 | 
|---|
| 228 | {
 | 
|---|
| 229 |         struct push_state *state = (struct push_state *)priv;
 | 
|---|
| 230 |         int result;
 | 
|---|
| 231 | 
 | 
|---|
| 232 |         if (x_feof(state->f)) {
 | 
|---|
| 233 |                 return 0;
 | 
|---|
| 234 |         }
 | 
|---|
| 235 | 
 | 
|---|
| 236 |         result = readfile(buf, n, state->f);
 | 
|---|
| 237 |         state->nread += result;
 | 
|---|
| 238 |         return result;
 | 
|---|
| 239 | }
 | 
|---|
| 240 | 
 | 
|---|
| 241 | /****************************************************************************
 | 
|---|
| 242 |  Send a message.
 | 
|---|
| 243 | ****************************************************************************/
 | 
|---|
| 244 | 
 | 
|---|
| 245 | static void send_message(const char *username)
 | 
|---|
| 246 | {
 | 
|---|
| 247 |         char buf[1600];
 | 
|---|
| 248 |         NTSTATUS status;
 | 
|---|
| 249 |         int i;
 | 
|---|
| 250 | 
 | 
|---|
| 251 |         d_printf("Type your message, ending it with a Control-D\n");
 | 
|---|
| 252 | 
 | 
|---|
| 253 |         i = 0;
 | 
|---|
| 254 |         while (i<sizeof(buf)-2) {
 | 
|---|
| 255 |                 int c = fgetc(stdin);
 | 
|---|
| 256 |                 if (c == EOF) {
 | 
|---|
| 257 |                         break;
 | 
|---|
| 258 |                 }
 | 
|---|
| 259 |                 if (c == '\n') {
 | 
|---|
| 260 |                         buf[i++] = '\r';
 | 
|---|
| 261 |                 }
 | 
|---|
| 262 |                 buf[i++] = c;
 | 
|---|
| 263 |         }
 | 
|---|
| 264 |         buf[i] = '\0';
 | 
|---|
| 265 | 
 | 
|---|
| 266 |         status = cli_message(cli, desthost, username, buf);
 | 
|---|
| 267 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 268 |                 d_fprintf(stderr, "cli_message returned %s\n",
 | 
|---|
| 269 |                           nt_errstr(status));
 | 
|---|
| 270 |         }
 | 
|---|
| 271 | }
 | 
|---|
| 272 | 
 | 
|---|
| 273 | /****************************************************************************
 | 
|---|
| 274 |  Check the space on a device.
 | 
|---|
| 275 | ****************************************************************************/
 | 
|---|
| 276 | 
 | 
|---|
| 277 | static int do_dskattr(void)
 | 
|---|
| 278 | {
 | 
|---|
| 279 |         int total, bsize, avail;
 | 
|---|
| 280 |         struct cli_state *targetcli = NULL;
 | 
|---|
| 281 |         char *targetpath = NULL;
 | 
|---|
| 282 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 283 | 
 | 
|---|
| 284 |         if ( !cli_resolve_path(ctx, "", auth_info, cli, client_get_cur_dir(), &targetcli, &targetpath)) {
 | 
|---|
| 285 |                 d_printf("Error in dskattr: %s\n", cli_errstr(cli));
 | 
|---|
| 286 |                 return 1;
 | 
|---|
| 287 |         }
 | 
|---|
| 288 | 
 | 
|---|
| 289 |         if (!NT_STATUS_IS_OK(cli_dskattr(targetcli, &bsize, &total, &avail))) {
 | 
|---|
| 290 |                 d_printf("Error in dskattr: %s\n",cli_errstr(targetcli));
 | 
|---|
| 291 |                 return 1;
 | 
|---|
| 292 |         }
 | 
|---|
| 293 | 
 | 
|---|
| 294 |         d_printf("\n\t\t%d blocks of size %d. %d blocks available\n",
 | 
|---|
| 295 |                  total, bsize, avail);
 | 
|---|
| 296 | 
 | 
|---|
| 297 |         return 0;
 | 
|---|
| 298 | }
 | 
|---|
| 299 | 
 | 
|---|
| 300 | /****************************************************************************
 | 
|---|
| 301 |  Show cd/pwd.
 | 
|---|
| 302 | ****************************************************************************/
 | 
|---|
| 303 | 
 | 
|---|
| 304 | static int cmd_pwd(void)
 | 
|---|
| 305 | {
 | 
|---|
| 306 |         d_printf("Current directory is %s",service);
 | 
|---|
| 307 |         d_printf("%s\n",client_get_cur_dir());
 | 
|---|
| 308 |         return 0;
 | 
|---|
| 309 | }
 | 
|---|
| 310 | 
 | 
|---|
| 311 | /****************************************************************************
 | 
|---|
| 312 |  Ensure name has correct directory separators.
 | 
|---|
| 313 | ****************************************************************************/
 | 
|---|
| 314 | 
 | 
|---|
| 315 | static void normalize_name(char *newdir)
 | 
|---|
| 316 | {
 | 
|---|
| 317 |         if (!(cli->posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP)) {
 | 
|---|
| 318 |                 string_replace(newdir,'/','\\');
 | 
|---|
| 319 |         }
 | 
|---|
| 320 | }
 | 
|---|
| 321 | 
 | 
|---|
| 322 | /****************************************************************************
 | 
|---|
| 323 |  Change directory - inner section.
 | 
|---|
| 324 | ****************************************************************************/
 | 
|---|
| 325 | 
 | 
|---|
| 326 | static int do_cd(const char *new_dir)
 | 
|---|
| 327 | {
 | 
|---|
| 328 |         char *newdir = NULL;
 | 
|---|
| 329 |         char *saved_dir = NULL;
 | 
|---|
| 330 |         char *new_cd = NULL;
 | 
|---|
| 331 |         char *targetpath = NULL;
 | 
|---|
| 332 |         struct cli_state *targetcli = NULL;
 | 
|---|
| 333 |         SMB_STRUCT_STAT sbuf;
 | 
|---|
| 334 |         uint32 attributes;
 | 
|---|
| 335 |         int ret = 1;
 | 
|---|
| 336 |         TALLOC_CTX *ctx = talloc_stackframe();
 | 
|---|
| 337 | 
 | 
|---|
| 338 |         newdir = talloc_strdup(ctx, new_dir);
 | 
|---|
| 339 |         if (!newdir) {
 | 
|---|
| 340 |                 TALLOC_FREE(ctx);
 | 
|---|
| 341 |                 return 1;
 | 
|---|
| 342 |         }
 | 
|---|
| 343 | 
 | 
|---|
| 344 |         normalize_name(newdir);
 | 
|---|
| 345 | 
 | 
|---|
| 346 |         /* Save the current directory in case the new directory is invalid */
 | 
|---|
| 347 | 
 | 
|---|
| 348 |         saved_dir = talloc_strdup(ctx, client_get_cur_dir());
 | 
|---|
| 349 |         if (!saved_dir) {
 | 
|---|
| 350 |                 TALLOC_FREE(ctx);
 | 
|---|
| 351 |                 return 1;
 | 
|---|
| 352 |         }
 | 
|---|
| 353 | 
 | 
|---|
| 354 |         if (*newdir == CLI_DIRSEP_CHAR) {
 | 
|---|
| 355 |                 client_set_cur_dir(newdir);
 | 
|---|
| 356 |                 new_cd = newdir;
 | 
|---|
| 357 |         } else {
 | 
|---|
| 358 |                 new_cd = talloc_asprintf(ctx, "%s%s",
 | 
|---|
| 359 |                                 client_get_cur_dir(),
 | 
|---|
| 360 |                                 newdir);
 | 
|---|
| 361 |                 if (!new_cd) {
 | 
|---|
| 362 |                         goto out;
 | 
|---|
| 363 |                 }
 | 
|---|
| 364 |         }
 | 
|---|
| 365 | 
 | 
|---|
| 366 |         /* Ensure cur_dir ends in a DIRSEP */
 | 
|---|
| 367 |         if ((new_cd[0] != '\0') && (*(new_cd+strlen(new_cd)-1) != CLI_DIRSEP_CHAR)) {
 | 
|---|
| 368 |                 new_cd = talloc_asprintf_append(new_cd, "%s", CLI_DIRSEP_STR);
 | 
|---|
| 369 |                 if (!new_cd) {
 | 
|---|
| 370 |                         goto out;
 | 
|---|
| 371 |                 }
 | 
|---|
| 372 |         }
 | 
|---|
| 373 |         client_set_cur_dir(new_cd);
 | 
|---|
| 374 | 
 | 
|---|
| 375 |         new_cd = clean_name(ctx, new_cd);
 | 
|---|
| 376 |         client_set_cur_dir(new_cd);
 | 
|---|
| 377 | 
 | 
|---|
| 378 |         if ( !cli_resolve_path(ctx, "", auth_info, cli, new_cd, &targetcli, &targetpath)) {
 | 
|---|
| 379 |                 d_printf("cd %s: %s\n", new_cd, cli_errstr(cli));
 | 
|---|
| 380 |                 client_set_cur_dir(saved_dir);
 | 
|---|
| 381 |                 goto out;
 | 
|---|
| 382 |         }
 | 
|---|
| 383 | 
 | 
|---|
| 384 |         if (strequal(targetpath,CLI_DIRSEP_STR )) {
 | 
|---|
| 385 |                 TALLOC_FREE(ctx);
 | 
|---|
| 386 |                 return 0;
 | 
|---|
| 387 |         }
 | 
|---|
| 388 | 
 | 
|---|
| 389 |         /* Use a trans2_qpathinfo to test directories for modern servers.
 | 
|---|
| 390 |            Except Win9x doesn't support the qpathinfo_basic() call..... */
 | 
|---|
| 391 | 
 | 
|---|
| 392 |         if (targetcli->protocol > PROTOCOL_LANMAN2 && !targetcli->win95) {
 | 
|---|
| 393 |                 if (!cli_qpathinfo_basic( targetcli, targetpath, &sbuf, &attributes ) ) {
 | 
|---|
| 394 |                         d_printf("cd %s: %s\n", new_cd, cli_errstr(targetcli));
 | 
|---|
| 395 |                         client_set_cur_dir(saved_dir);
 | 
|---|
| 396 |                         goto out;
 | 
|---|
| 397 |                 }
 | 
|---|
| 398 | 
 | 
|---|
| 399 |                 if (!(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
 | 
|---|
| 400 |                         d_printf("cd %s: not a directory\n", new_cd);
 | 
|---|
| 401 |                         client_set_cur_dir(saved_dir);
 | 
|---|
| 402 |                         goto out;
 | 
|---|
| 403 |                 }
 | 
|---|
| 404 |         } else {
 | 
|---|
| 405 |                 targetpath = talloc_asprintf(ctx,
 | 
|---|
| 406 |                                 "%s%s",
 | 
|---|
| 407 |                                 targetpath,
 | 
|---|
| 408 |                                 CLI_DIRSEP_STR );
 | 
|---|
| 409 |                 if (!targetpath) {
 | 
|---|
| 410 |                         client_set_cur_dir(saved_dir);
 | 
|---|
| 411 |                         goto out;
 | 
|---|
| 412 |                 }
 | 
|---|
| 413 |                 targetpath = clean_name(ctx, targetpath);
 | 
|---|
| 414 |                 if (!targetpath) {
 | 
|---|
| 415 |                         client_set_cur_dir(saved_dir);
 | 
|---|
| 416 |                         goto out;
 | 
|---|
| 417 |                 }
 | 
|---|
| 418 | 
 | 
|---|
| 419 |                 if (!NT_STATUS_IS_OK(cli_chkpath(targetcli, targetpath))) {
 | 
|---|
| 420 |                         d_printf("cd %s: %s\n", new_cd, cli_errstr(targetcli));
 | 
|---|
| 421 |                         client_set_cur_dir(saved_dir);
 | 
|---|
| 422 |                         goto out;
 | 
|---|
| 423 |                 }
 | 
|---|
| 424 |         }
 | 
|---|
| 425 | 
 | 
|---|
| 426 |         ret = 0;
 | 
|---|
| 427 | 
 | 
|---|
| 428 | out:
 | 
|---|
| 429 | 
 | 
|---|
| 430 |         TALLOC_FREE(ctx);
 | 
|---|
| 431 |         return ret;
 | 
|---|
| 432 | }
 | 
|---|
| 433 | 
 | 
|---|
| 434 | /****************************************************************************
 | 
|---|
| 435 |  Change directory.
 | 
|---|
| 436 | ****************************************************************************/
 | 
|---|
| 437 | 
 | 
|---|
| 438 | static int cmd_cd(void)
 | 
|---|
| 439 | {
 | 
|---|
| 440 |         char *buf = NULL;
 | 
|---|
| 441 |         int rc = 0;
 | 
|---|
| 442 | 
 | 
|---|
| 443 |         if (next_token_talloc(talloc_tos(), &cmd_ptr, &buf,NULL)) {
 | 
|---|
| 444 |                 rc = do_cd(buf);
 | 
|---|
| 445 |         } else {
 | 
|---|
| 446 |                 d_printf("Current directory is %s\n",client_get_cur_dir());
 | 
|---|
| 447 |         }
 | 
|---|
| 448 | 
 | 
|---|
| 449 |         return rc;
 | 
|---|
| 450 | }
 | 
|---|
| 451 | 
 | 
|---|
| 452 | /****************************************************************************
 | 
|---|
| 453 |  Change directory.
 | 
|---|
| 454 | ****************************************************************************/
 | 
|---|
| 455 | 
 | 
|---|
| 456 | static int cmd_cd_oneup(void)
 | 
|---|
| 457 | {
 | 
|---|
| 458 |         return do_cd("..");
 | 
|---|
| 459 | }
 | 
|---|
| 460 | 
 | 
|---|
| 461 | /*******************************************************************
 | 
|---|
| 462 |  Decide if a file should be operated on.
 | 
|---|
| 463 | ********************************************************************/
 | 
|---|
| 464 | 
 | 
|---|
| 465 | static bool do_this_one(file_info *finfo)
 | 
|---|
| 466 | {
 | 
|---|
| 467 |         if (!finfo->name) {
 | 
|---|
| 468 |                 return false;
 | 
|---|
| 469 |         }
 | 
|---|
| 470 | 
 | 
|---|
| 471 |         if (finfo->mode & aDIR) {
 | 
|---|
| 472 |                 return true;
 | 
|---|
| 473 |         }
 | 
|---|
| 474 | 
 | 
|---|
| 475 |         if (*client_get_fileselection() &&
 | 
|---|
| 476 |             !mask_match(finfo->name,client_get_fileselection(),false)) {
 | 
|---|
| 477 |                 DEBUG(3,("mask_match %s failed\n", finfo->name));
 | 
|---|
| 478 |                 return false;
 | 
|---|
| 479 |         }
 | 
|---|
| 480 | 
 | 
|---|
| 481 |         if (newer_than && finfo->mtime_ts.tv_sec < newer_than) {
 | 
|---|
| 482 |                 DEBUG(3,("newer_than %s failed\n", finfo->name));
 | 
|---|
| 483 |                 return false;
 | 
|---|
| 484 |         }
 | 
|---|
| 485 | 
 | 
|---|
| 486 |         if ((archive_level==1 || archive_level==2) && !(finfo->mode & aARCH)) {
 | 
|---|
| 487 |                 DEBUG(3,("archive %s failed\n", finfo->name));
 | 
|---|
| 488 |                 return false;
 | 
|---|
| 489 |         }
 | 
|---|
| 490 | 
 | 
|---|
| 491 |         return true;
 | 
|---|
| 492 | }
 | 
|---|
| 493 | 
 | 
|---|
| 494 | /****************************************************************************
 | 
|---|
| 495 |  Display info about a file.
 | 
|---|
| 496 | ****************************************************************************/
 | 
|---|
| 497 | 
 | 
|---|
| 498 | static void display_finfo(file_info *finfo, const char *dir)
 | 
|---|
| 499 | {
 | 
|---|
| 500 |         time_t t;
 | 
|---|
| 501 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 502 | 
 | 
|---|
| 503 |         if (!do_this_one(finfo)) {
 | 
|---|
| 504 |                 return;
 | 
|---|
| 505 |         }
 | 
|---|
| 506 | 
 | 
|---|
| 507 |         t = finfo->mtime_ts.tv_sec; /* the time is assumed to be passed as GMT */
 | 
|---|
| 508 |         if (!showacls) {
 | 
|---|
| 509 |                 d_printf("  %-30s%7.7s %8.0f  %s",
 | 
|---|
| 510 |                          finfo->name,
 | 
|---|
| 511 |                          attrib_string(finfo->mode),
 | 
|---|
| 512 |                         (double)finfo->size,
 | 
|---|
| 513 |                         time_to_asc(t));
 | 
|---|
| 514 |                 dir_total += finfo->size;
 | 
|---|
| 515 |         } else {
 | 
|---|
| 516 |                 char *afname = NULL;
 | 
|---|
| 517 |                 uint16_t fnum;
 | 
|---|
| 518 | 
 | 
|---|
| 519 |                 /* skip if this is . or .. */
 | 
|---|
| 520 |                 if ( strequal(finfo->name,"..") || strequal(finfo->name,".") )
 | 
|---|
| 521 |                         return;
 | 
|---|
| 522 |                 /* create absolute filename for cli_ntcreate() FIXME */
 | 
|---|
| 523 |                 afname = talloc_asprintf(ctx,
 | 
|---|
| 524 |                                         "%s%s%s",
 | 
|---|
| 525 |                                         dir,
 | 
|---|
| 526 |                                         CLI_DIRSEP_STR,
 | 
|---|
| 527 |                                         finfo->name);
 | 
|---|
| 528 |                 if (!afname) {
 | 
|---|
| 529 |                         return;
 | 
|---|
| 530 |                 }
 | 
|---|
| 531 |                 /* print file meta date header */
 | 
|---|
| 532 |                 d_printf( "FILENAME:%s\n", finfo->name);
 | 
|---|
| 533 |                 d_printf( "MODE:%s\n", attrib_string(finfo->mode));
 | 
|---|
| 534 |                 d_printf( "SIZE:%.0f\n", (double)finfo->size);
 | 
|---|
| 535 |                 d_printf( "MTIME:%s", time_to_asc(t));
 | 
|---|
| 536 |                 if (!NT_STATUS_IS_OK(cli_ntcreate(finfo->cli, afname, 0,
 | 
|---|
| 537 |                                 CREATE_ACCESS_READ, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
 | 
|---|
| 538 |                                 FILE_OPEN, 0x0, 0x0, &fnum))) {
 | 
|---|
| 539 |                         DEBUG( 0, ("display_finfo() Failed to open %s: %s\n",
 | 
|---|
| 540 |                                 afname,
 | 
|---|
| 541 |                                 cli_errstr( finfo->cli)));
 | 
|---|
| 542 |                 } else {
 | 
|---|
| 543 |                         SEC_DESC *sd = NULL;
 | 
|---|
| 544 |                         sd = cli_query_secdesc(finfo->cli, fnum, ctx);
 | 
|---|
| 545 |                         if (!sd) {
 | 
|---|
| 546 |                                 DEBUG( 0, ("display_finfo() failed to "
 | 
|---|
| 547 |                                         "get security descriptor: %s",
 | 
|---|
| 548 |                                         cli_errstr( finfo->cli)));
 | 
|---|
| 549 |                         } else {
 | 
|---|
| 550 |                                 display_sec_desc(sd);
 | 
|---|
| 551 |                         }
 | 
|---|
| 552 |                         TALLOC_FREE(sd);
 | 
|---|
| 553 |                 }
 | 
|---|
| 554 |                 TALLOC_FREE(afname);
 | 
|---|
| 555 |         }
 | 
|---|
| 556 | }
 | 
|---|
| 557 | 
 | 
|---|
| 558 | /****************************************************************************
 | 
|---|
| 559 |  Accumulate size of a file.
 | 
|---|
| 560 | ****************************************************************************/
 | 
|---|
| 561 | 
 | 
|---|
| 562 | static void do_du(file_info *finfo, const char *dir)
 | 
|---|
| 563 | {
 | 
|---|
| 564 |         if (do_this_one(finfo)) {
 | 
|---|
| 565 |                 dir_total += finfo->size;
 | 
|---|
| 566 |         }
 | 
|---|
| 567 | }
 | 
|---|
| 568 | 
 | 
|---|
| 569 | static bool do_list_recurse;
 | 
|---|
| 570 | static bool do_list_dirs;
 | 
|---|
| 571 | static char *do_list_queue = 0;
 | 
|---|
| 572 | static long do_list_queue_size = 0;
 | 
|---|
| 573 | static long do_list_queue_start = 0;
 | 
|---|
| 574 | static long do_list_queue_end = 0;
 | 
|---|
| 575 | static void (*do_list_fn)(file_info *, const char *dir);
 | 
|---|
| 576 | 
 | 
|---|
| 577 | /****************************************************************************
 | 
|---|
| 578 |  Functions for do_list_queue.
 | 
|---|
| 579 | ****************************************************************************/
 | 
|---|
| 580 | 
 | 
|---|
| 581 | /*
 | 
|---|
| 582 |  * The do_list_queue is a NUL-separated list of strings stored in a
 | 
|---|
| 583 |  * char*.  Since this is a FIFO, we keep track of the beginning and
 | 
|---|
| 584 |  * ending locations of the data in the queue.  When we overflow, we
 | 
|---|
| 585 |  * double the size of the char*.  When the start of the data passes
 | 
|---|
| 586 |  * the midpoint, we move everything back.  This is logically more
 | 
|---|
| 587 |  * complex than a linked list, but easier from a memory management
 | 
|---|
| 588 |  * angle.  In any memory error condition, do_list_queue is reset.
 | 
|---|
| 589 |  * Functions check to ensure that do_list_queue is non-NULL before
 | 
|---|
| 590 |  * accessing it.
 | 
|---|
| 591 |  */
 | 
|---|
| 592 | 
 | 
|---|
| 593 | static void reset_do_list_queue(void)
 | 
|---|
| 594 | {
 | 
|---|
| 595 |         SAFE_FREE(do_list_queue);
 | 
|---|
| 596 |         do_list_queue_size = 0;
 | 
|---|
| 597 |         do_list_queue_start = 0;
 | 
|---|
| 598 |         do_list_queue_end = 0;
 | 
|---|
| 599 | }
 | 
|---|
| 600 | 
 | 
|---|
| 601 | static void init_do_list_queue(void)
 | 
|---|
| 602 | {
 | 
|---|
| 603 |         reset_do_list_queue();
 | 
|---|
| 604 |         do_list_queue_size = 1024;
 | 
|---|
| 605 |         do_list_queue = (char *)SMB_MALLOC(do_list_queue_size);
 | 
|---|
| 606 |         if (do_list_queue == 0) {
 | 
|---|
| 607 |                 d_printf("malloc fail for size %d\n",
 | 
|---|
| 608 |                          (int)do_list_queue_size);
 | 
|---|
| 609 |                 reset_do_list_queue();
 | 
|---|
| 610 |         } else {
 | 
|---|
| 611 |                 memset(do_list_queue, 0, do_list_queue_size);
 | 
|---|
| 612 |         }
 | 
|---|
| 613 | }
 | 
|---|
| 614 | 
 | 
|---|
| 615 | static void adjust_do_list_queue(void)
 | 
|---|
| 616 | {
 | 
|---|
| 617 |         /*
 | 
|---|
| 618 |          * If the starting point of the queue is more than half way through,
 | 
|---|
| 619 |          * move everything toward the beginning.
 | 
|---|
| 620 |          */
 | 
|---|
| 621 | 
 | 
|---|
| 622 |         if (do_list_queue == NULL) {
 | 
|---|
| 623 |                 DEBUG(4,("do_list_queue is empty\n"));
 | 
|---|
| 624 |                 do_list_queue_start = do_list_queue_end = 0;
 | 
|---|
| 625 |                 return;
 | 
|---|
| 626 |         }
 | 
|---|
| 627 | 
 | 
|---|
| 628 |         if (do_list_queue_start == do_list_queue_end) {
 | 
|---|
| 629 |                 DEBUG(4,("do_list_queue is empty\n"));
 | 
|---|
| 630 |                 do_list_queue_start = do_list_queue_end = 0;
 | 
|---|
| 631 |                 *do_list_queue = '\0';
 | 
|---|
| 632 |         } else if (do_list_queue_start > (do_list_queue_size / 2)) {
 | 
|---|
| 633 |                 DEBUG(4,("sliding do_list_queue backward\n"));
 | 
|---|
| 634 |                 memmove(do_list_queue,
 | 
|---|
| 635 |                         do_list_queue + do_list_queue_start,
 | 
|---|
| 636 |                         do_list_queue_end - do_list_queue_start);
 | 
|---|
| 637 |                 do_list_queue_end -= do_list_queue_start;
 | 
|---|
| 638 |                 do_list_queue_start = 0;
 | 
|---|
| 639 |         }
 | 
|---|
| 640 | }
 | 
|---|
| 641 | 
 | 
|---|
| 642 | static void add_to_do_list_queue(const char *entry)
 | 
|---|
| 643 | {
 | 
|---|
| 644 |         long new_end = do_list_queue_end + ((long)strlen(entry)) + 1;
 | 
|---|
| 645 |         while (new_end > do_list_queue_size) {
 | 
|---|
| 646 |                 do_list_queue_size *= 2;
 | 
|---|
| 647 |                 DEBUG(4,("enlarging do_list_queue to %d\n",
 | 
|---|
| 648 |                          (int)do_list_queue_size));
 | 
|---|
| 649 |                 do_list_queue = (char *)SMB_REALLOC(do_list_queue, do_list_queue_size);
 | 
|---|
| 650 |                 if (! do_list_queue) {
 | 
|---|
| 651 |                         d_printf("failure enlarging do_list_queue to %d bytes\n",
 | 
|---|
| 652 |                                  (int)do_list_queue_size);
 | 
|---|
| 653 |                         reset_do_list_queue();
 | 
|---|
| 654 |                 } else {
 | 
|---|
| 655 |                         memset(do_list_queue + do_list_queue_size / 2,
 | 
|---|
| 656 |                                0, do_list_queue_size / 2);
 | 
|---|
| 657 |                 }
 | 
|---|
| 658 |         }
 | 
|---|
| 659 |         if (do_list_queue) {
 | 
|---|
| 660 |                 safe_strcpy_base(do_list_queue + do_list_queue_end,
 | 
|---|
| 661 |                                  entry, do_list_queue, do_list_queue_size);
 | 
|---|
| 662 |                 do_list_queue_end = new_end;
 | 
|---|
| 663 |                 DEBUG(4,("added %s to do_list_queue (start=%d, end=%d)\n",
 | 
|---|
| 664 |                          entry, (int)do_list_queue_start, (int)do_list_queue_end));
 | 
|---|
| 665 |         }
 | 
|---|
| 666 | }
 | 
|---|
| 667 | 
 | 
|---|
| 668 | static char *do_list_queue_head(void)
 | 
|---|
| 669 | {
 | 
|---|
| 670 |         return do_list_queue + do_list_queue_start;
 | 
|---|
| 671 | }
 | 
|---|
| 672 | 
 | 
|---|
| 673 | static void remove_do_list_queue_head(void)
 | 
|---|
| 674 | {
 | 
|---|
| 675 |         if (do_list_queue_end > do_list_queue_start) {
 | 
|---|
| 676 |                 do_list_queue_start += strlen(do_list_queue_head()) + 1;
 | 
|---|
| 677 |                 adjust_do_list_queue();
 | 
|---|
| 678 |                 DEBUG(4,("removed head of do_list_queue (start=%d, end=%d)\n",
 | 
|---|
| 679 |                          (int)do_list_queue_start, (int)do_list_queue_end));
 | 
|---|
| 680 |         }
 | 
|---|
| 681 | }
 | 
|---|
| 682 | 
 | 
|---|
| 683 | static int do_list_queue_empty(void)
 | 
|---|
| 684 | {
 | 
|---|
| 685 |         return (! (do_list_queue && *do_list_queue));
 | 
|---|
| 686 | }
 | 
|---|
| 687 | 
 | 
|---|
| 688 | /****************************************************************************
 | 
|---|
| 689 |  A helper for do_list.
 | 
|---|
| 690 | ****************************************************************************/
 | 
|---|
| 691 | 
 | 
|---|
| 692 | static void do_list_helper(const char *mntpoint, file_info *f, const char *mask, void *state)
 | 
|---|
| 693 | {
 | 
|---|
| 694 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 695 |         char *dir = NULL;
 | 
|---|
| 696 |         char *dir_end = NULL;
 | 
|---|
| 697 | 
 | 
|---|
| 698 |         /* Work out the directory. */
 | 
|---|
| 699 |         dir = talloc_strdup(ctx, mask);
 | 
|---|
| 700 |         if (!dir) {
 | 
|---|
| 701 |                 return;
 | 
|---|
| 702 |         }
 | 
|---|
| 703 |         if ((dir_end = strrchr(dir, CLI_DIRSEP_CHAR)) != NULL) {
 | 
|---|
| 704 |                 *dir_end = '\0';
 | 
|---|
| 705 |         }
 | 
|---|
| 706 | 
 | 
|---|
| 707 |         if (f->mode & aDIR) {
 | 
|---|
| 708 |                 if (do_list_dirs && do_this_one(f)) {
 | 
|---|
| 709 |                         do_list_fn(f, dir);
 | 
|---|
| 710 |                 }
 | 
|---|
| 711 |                 if (do_list_recurse &&
 | 
|---|
| 712 |                     f->name &&
 | 
|---|
| 713 |                     !strequal(f->name,".") &&
 | 
|---|
| 714 |                     !strequal(f->name,"..")) {
 | 
|---|
| 715 |                         char *mask2 = NULL;
 | 
|---|
| 716 |                         char *p = NULL;
 | 
|---|
| 717 | 
 | 
|---|
| 718 |                         if (!f->name[0]) {
 | 
|---|
| 719 |                                 d_printf("Empty dir name returned. Possible server misconfiguration.\n");
 | 
|---|
| 720 |                                 TALLOC_FREE(dir);
 | 
|---|
| 721 |                                 return;
 | 
|---|
| 722 |                         }
 | 
|---|
| 723 | 
 | 
|---|
| 724 |                         mask2 = talloc_asprintf(ctx,
 | 
|---|
| 725 |                                         "%s%s",
 | 
|---|
| 726 |                                         mntpoint,
 | 
|---|
| 727 |                                         mask);
 | 
|---|
| 728 |                         if (!mask2) {
 | 
|---|
| 729 |                                 TALLOC_FREE(dir);
 | 
|---|
| 730 |                                 return;
 | 
|---|
| 731 |                         }
 | 
|---|
| 732 |                         p = strrchr_m(mask2,CLI_DIRSEP_CHAR);
 | 
|---|
| 733 |                         if (p) {
 | 
|---|
| 734 |                                 p[1] = 0;
 | 
|---|
| 735 |                         } else {
 | 
|---|
| 736 |                                 mask2[0] = '\0';
 | 
|---|
| 737 |                         }
 | 
|---|
| 738 |                         mask2 = talloc_asprintf_append(mask2,
 | 
|---|
| 739 |                                         "%s%s*",
 | 
|---|
| 740 |                                         f->name,
 | 
|---|
| 741 |                                         CLI_DIRSEP_STR);
 | 
|---|
| 742 |                         if (!mask2) {
 | 
|---|
| 743 |                                 TALLOC_FREE(dir);
 | 
|---|
| 744 |                                 return;
 | 
|---|
| 745 |                         }
 | 
|---|
| 746 |                         add_to_do_list_queue(mask2);
 | 
|---|
| 747 |                         TALLOC_FREE(mask2);
 | 
|---|
| 748 |                 }
 | 
|---|
| 749 |                 TALLOC_FREE(dir);
 | 
|---|
| 750 |                 return;
 | 
|---|
| 751 |         }
 | 
|---|
| 752 | 
 | 
|---|
| 753 |         if (do_this_one(f)) {
 | 
|---|
| 754 |                 do_list_fn(f,dir);
 | 
|---|
| 755 |         }
 | 
|---|
| 756 |         TALLOC_FREE(dir);
 | 
|---|
| 757 | }
 | 
|---|
| 758 | 
 | 
|---|
| 759 | /****************************************************************************
 | 
|---|
| 760 |  A wrapper around cli_list that adds recursion.
 | 
|---|
| 761 | ****************************************************************************/
 | 
|---|
| 762 | 
 | 
|---|
| 763 | void do_list(const char *mask,
 | 
|---|
| 764 |                         uint16 attribute,
 | 
|---|
| 765 |                         void (*fn)(file_info *, const char *dir),
 | 
|---|
| 766 |                         bool rec,
 | 
|---|
| 767 |                         bool dirs)
 | 
|---|
| 768 | {
 | 
|---|
| 769 |         static int in_do_list = 0;
 | 
|---|
| 770 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 771 |         struct cli_state *targetcli = NULL;
 | 
|---|
| 772 |         char *targetpath = NULL;
 | 
|---|
| 773 | 
 | 
|---|
| 774 |         if (in_do_list && rec) {
 | 
|---|
| 775 |                 fprintf(stderr, "INTERNAL ERROR: do_list called recursively when the recursive flag is true\n");
 | 
|---|
| 776 |                 exit(1);
 | 
|---|
| 777 |         }
 | 
|---|
| 778 | 
 | 
|---|
| 779 |         in_do_list = 1;
 | 
|---|
| 780 | 
 | 
|---|
| 781 |         do_list_recurse = rec;
 | 
|---|
| 782 |         do_list_dirs = dirs;
 | 
|---|
| 783 |         do_list_fn = fn;
 | 
|---|
| 784 | 
 | 
|---|
| 785 |         if (rec) {
 | 
|---|
| 786 |                 init_do_list_queue();
 | 
|---|
| 787 |                 add_to_do_list_queue(mask);
 | 
|---|
| 788 | 
 | 
|---|
| 789 |                 while (!do_list_queue_empty()) {
 | 
|---|
| 790 |                         /*
 | 
|---|
| 791 |                          * Need to copy head so that it doesn't become
 | 
|---|
| 792 |                          * invalid inside the call to cli_list.  This
 | 
|---|
| 793 |                          * would happen if the list were expanded
 | 
|---|
| 794 |                          * during the call.
 | 
|---|
| 795 |                          * Fix from E. Jay Berkenbilt (ejb@ql.org)
 | 
|---|
| 796 |                          */
 | 
|---|
| 797 |                         char *head = talloc_strdup(ctx, do_list_queue_head());
 | 
|---|
| 798 | 
 | 
|---|
| 799 |                         if (!head) {
 | 
|---|
| 800 |                                 return;
 | 
|---|
| 801 |                         }
 | 
|---|
| 802 | 
 | 
|---|
| 803 |                         /* check for dfs */
 | 
|---|
| 804 | 
 | 
|---|
| 805 |                         if ( !cli_resolve_path(ctx, "", auth_info, cli, head, &targetcli, &targetpath ) ) {
 | 
|---|
| 806 |                                 d_printf("do_list: [%s] %s\n", head, cli_errstr(cli));
 | 
|---|
| 807 |                                 remove_do_list_queue_head();
 | 
|---|
| 808 |                                 continue;
 | 
|---|
| 809 |                         }
 | 
|---|
| 810 | 
 | 
|---|
| 811 |                         cli_list(targetcli, targetpath, attribute, do_list_helper, NULL);
 | 
|---|
| 812 |                         remove_do_list_queue_head();
 | 
|---|
| 813 |                         if ((! do_list_queue_empty()) && (fn == display_finfo)) {
 | 
|---|
| 814 |                                 char *next_file = do_list_queue_head();
 | 
|---|
| 815 |                                 char *save_ch = 0;
 | 
|---|
| 816 |                                 if ((strlen(next_file) >= 2) &&
 | 
|---|
| 817 |                                     (next_file[strlen(next_file) - 1] == '*') &&
 | 
|---|
| 818 |                                     (next_file[strlen(next_file) - 2] == CLI_DIRSEP_CHAR)) {
 | 
|---|
| 819 |                                         save_ch = next_file +
 | 
|---|
| 820 |                                                 strlen(next_file) - 2;
 | 
|---|
| 821 |                                         *save_ch = '\0';
 | 
|---|
| 822 |                                         if (showacls) {
 | 
|---|
| 823 |                                                 /* cwd is only used if showacls is on */
 | 
|---|
| 824 |                                                 client_set_cwd(next_file);
 | 
|---|
| 825 |                                         }
 | 
|---|
| 826 |                                 }
 | 
|---|
| 827 |                                 if (!showacls) /* don't disturbe the showacls output */
 | 
|---|
| 828 |                                         d_printf("\n%s\n",next_file);
 | 
|---|
| 829 |                                 if (save_ch) {
 | 
|---|
| 830 |                                         *save_ch = CLI_DIRSEP_CHAR;
 | 
|---|
| 831 |                                 }
 | 
|---|
| 832 |                         }
 | 
|---|
| 833 |                         TALLOC_FREE(head);
 | 
|---|
| 834 |                         TALLOC_FREE(targetpath);
 | 
|---|
| 835 |                 }
 | 
|---|
| 836 |         } else {
 | 
|---|
| 837 |                 /* check for dfs */
 | 
|---|
| 838 |                 if (cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetpath)) {
 | 
|---|
| 839 |                         if (cli_list(targetcli, targetpath, attribute, do_list_helper, NULL) == -1) {
 | 
|---|
| 840 |                                 d_printf("%s listing %s\n",
 | 
|---|
| 841 |                                         cli_errstr(targetcli), targetpath);
 | 
|---|
| 842 |                         }
 | 
|---|
| 843 |                         TALLOC_FREE(targetpath);
 | 
|---|
| 844 |                 } else {
 | 
|---|
| 845 |                         d_printf("do_list: [%s] %s\n", mask, cli_errstr(cli));
 | 
|---|
| 846 |                 }
 | 
|---|
| 847 |         }
 | 
|---|
| 848 | 
 | 
|---|
| 849 |         in_do_list = 0;
 | 
|---|
| 850 |         reset_do_list_queue();
 | 
|---|
| 851 | }
 | 
|---|
| 852 | 
 | 
|---|
| 853 | /****************************************************************************
 | 
|---|
| 854 |  Get a directory listing.
 | 
|---|
| 855 | ****************************************************************************/
 | 
|---|
| 856 | 
 | 
|---|
| 857 | static int cmd_dir(void)
 | 
|---|
| 858 | {
 | 
|---|
| 859 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 860 |         uint16 attribute = aDIR | aSYSTEM | aHIDDEN;
 | 
|---|
| 861 |         char *mask = NULL;
 | 
|---|
| 862 |         char *buf = NULL;
 | 
|---|
| 863 |         int rc = 1;
 | 
|---|
| 864 | 
 | 
|---|
| 865 |         dir_total = 0;
 | 
|---|
| 866 |         mask = talloc_strdup(ctx, client_get_cur_dir());
 | 
|---|
| 867 |         if (!mask) {
 | 
|---|
| 868 |                 return 1;
 | 
|---|
| 869 |         }
 | 
|---|
| 870 | 
 | 
|---|
| 871 |         if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 872 |                 normalize_name(buf);
 | 
|---|
| 873 |                 if (*buf == CLI_DIRSEP_CHAR) {
 | 
|---|
| 874 |                         mask = talloc_strdup(ctx, buf);
 | 
|---|
| 875 |                 } else {
 | 
|---|
| 876 |                         mask = talloc_asprintf_append(mask, "%s", buf);
 | 
|---|
| 877 |                 }
 | 
|---|
| 878 |         } else {
 | 
|---|
| 879 |                 mask = talloc_asprintf_append(mask, "*");
 | 
|---|
| 880 |         }
 | 
|---|
| 881 |         if (!mask) {
 | 
|---|
| 882 |                 return 1;
 | 
|---|
| 883 |         }
 | 
|---|
| 884 | 
 | 
|---|
| 885 |         if (showacls) {
 | 
|---|
| 886 |                 /* cwd is only used if showacls is on */
 | 
|---|
| 887 |                 client_set_cwd(client_get_cur_dir());
 | 
|---|
| 888 |         }
 | 
|---|
| 889 | 
 | 
|---|
| 890 |         do_list(mask, attribute, display_finfo, recurse, true);
 | 
|---|
| 891 | 
 | 
|---|
| 892 |         rc = do_dskattr();
 | 
|---|
| 893 | 
 | 
|---|
| 894 |         DEBUG(3, ("Total bytes listed: %.0f\n", dir_total));
 | 
|---|
| 895 | 
 | 
|---|
| 896 |         return rc;
 | 
|---|
| 897 | }
 | 
|---|
| 898 | 
 | 
|---|
| 899 | /****************************************************************************
 | 
|---|
| 900 |  Get a directory listing.
 | 
|---|
| 901 | ****************************************************************************/
 | 
|---|
| 902 | 
 | 
|---|
| 903 | static int cmd_du(void)
 | 
|---|
| 904 | {
 | 
|---|
| 905 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 906 |         uint16 attribute = aDIR | aSYSTEM | aHIDDEN;
 | 
|---|
| 907 |         char *mask = NULL;
 | 
|---|
| 908 |         char *buf = NULL;
 | 
|---|
| 909 |         int rc = 1;
 | 
|---|
| 910 | 
 | 
|---|
| 911 |         dir_total = 0;
 | 
|---|
| 912 |         mask = talloc_strdup(ctx, client_get_cur_dir());
 | 
|---|
| 913 |         if (!mask) {
 | 
|---|
| 914 |                 return 1;
 | 
|---|
| 915 |         }
 | 
|---|
| 916 |         if ((mask[0] != '\0') && (mask[strlen(mask)-1]!=CLI_DIRSEP_CHAR)) {
 | 
|---|
| 917 |                 mask = talloc_asprintf_append(mask, "%s", CLI_DIRSEP_STR);
 | 
|---|
| 918 |                 if (!mask) {
 | 
|---|
| 919 |                         return 1;
 | 
|---|
| 920 |                 }
 | 
|---|
| 921 |         }
 | 
|---|
| 922 | 
 | 
|---|
| 923 |         if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 924 |                 normalize_name(buf);
 | 
|---|
| 925 |                 if (*buf == CLI_DIRSEP_CHAR) {
 | 
|---|
| 926 |                         mask = talloc_strdup(ctx, buf);
 | 
|---|
| 927 |                 } else {
 | 
|---|
| 928 |                         mask = talloc_asprintf_append(mask, "%s", buf);
 | 
|---|
| 929 |                 }
 | 
|---|
| 930 |         } else {
 | 
|---|
| 931 |                 mask = talloc_strdup(ctx, "*");
 | 
|---|
| 932 |         }
 | 
|---|
| 933 | 
 | 
|---|
| 934 |         do_list(mask, attribute, do_du, recurse, true);
 | 
|---|
| 935 | 
 | 
|---|
| 936 |         rc = do_dskattr();
 | 
|---|
| 937 | 
 | 
|---|
| 938 |         d_printf("Total number of bytes: %.0f\n", dir_total);
 | 
|---|
| 939 | 
 | 
|---|
| 940 |         return rc;
 | 
|---|
| 941 | }
 | 
|---|
| 942 | 
 | 
|---|
| 943 | static int cmd_echo(void)
 | 
|---|
| 944 | {
 | 
|---|
| 945 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 946 |         char *num;
 | 
|---|
| 947 |         char *data;
 | 
|---|
| 948 |         NTSTATUS status;
 | 
|---|
| 949 | 
 | 
|---|
| 950 |         if (!next_token_talloc(ctx, &cmd_ptr, &num, NULL)
 | 
|---|
| 951 |             || !next_token_talloc(ctx, &cmd_ptr, &data, NULL)) {
 | 
|---|
| 952 |                 d_printf("echo <num> <data>\n");
 | 
|---|
| 953 |                 return 1;
 | 
|---|
| 954 |         }
 | 
|---|
| 955 | 
 | 
|---|
| 956 |         status = cli_echo(cli, atoi(num), data_blob_const(data, strlen(data)));
 | 
|---|
| 957 | 
 | 
|---|
| 958 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 959 |                 d_printf("echo failed: %s\n", nt_errstr(status));
 | 
|---|
| 960 |                 return 1;
 | 
|---|
| 961 |         }
 | 
|---|
| 962 | 
 | 
|---|
| 963 |         return 0;
 | 
|---|
| 964 | }
 | 
|---|
| 965 | 
 | 
|---|
| 966 | /****************************************************************************
 | 
|---|
| 967 |  Get a file from rname to lname
 | 
|---|
| 968 | ****************************************************************************/
 | 
|---|
| 969 | 
 | 
|---|
| 970 | static NTSTATUS writefile_sink(char *buf, size_t n, void *priv)
 | 
|---|
| 971 | {
 | 
|---|
| 972 |         int *pfd = (int *)priv;
 | 
|---|
| 973 |         if (writefile(*pfd, buf, n) == -1) {
 | 
|---|
| 974 |                 return map_nt_error_from_unix(errno);
 | 
|---|
| 975 |         }
 | 
|---|
| 976 |         return NT_STATUS_OK;
 | 
|---|
| 977 | }
 | 
|---|
| 978 | 
 | 
|---|
| 979 | static int do_get(const char *rname, const char *lname_in, bool reget)
 | 
|---|
| 980 | {
 | 
|---|
| 981 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 982 |         int handle = 0;
 | 
|---|
| 983 |         uint16_t fnum;
 | 
|---|
| 984 |         bool newhandle = false;
 | 
|---|
| 985 |         struct timeval tp_start;
 | 
|---|
| 986 |         uint16 attr;
 | 
|---|
| 987 |         SMB_OFF_T size;
 | 
|---|
| 988 |         off_t start = 0;
 | 
|---|
| 989 |         SMB_OFF_T nread = 0;
 | 
|---|
| 990 |         int rc = 0;
 | 
|---|
| 991 |         struct cli_state *targetcli = NULL;
 | 
|---|
| 992 |         char *targetname = NULL;
 | 
|---|
| 993 |         char *lname = NULL;
 | 
|---|
| 994 |         NTSTATUS status;
 | 
|---|
| 995 | 
 | 
|---|
| 996 |         lname = talloc_strdup(ctx, lname_in);
 | 
|---|
| 997 |         if (!lname) {
 | 
|---|
| 998 |                 return 1;
 | 
|---|
| 999 |         }
 | 
|---|
| 1000 | 
 | 
|---|
| 1001 |         if (lowercase) {
 | 
|---|
| 1002 |                 strlower_m(lname);
 | 
|---|
| 1003 |         }
 | 
|---|
| 1004 | 
 | 
|---|
| 1005 |         if (!cli_resolve_path(ctx, "", auth_info, cli, rname, &targetcli, &targetname ) ) {
 | 
|---|
| 1006 |                 d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
 | 
|---|
| 1007 |                 return 1;
 | 
|---|
| 1008 |         }
 | 
|---|
| 1009 | 
 | 
|---|
| 1010 |         GetTimeOfDay(&tp_start);
 | 
|---|
| 1011 | 
 | 
|---|
| 1012 |         if (!NT_STATUS_IS_OK(cli_open(targetcli, targetname, O_RDONLY, DENY_NONE, &fnum))) {
 | 
|---|
| 1013 |                 d_printf("%s opening remote file %s\n",cli_errstr(cli),rname);
 | 
|---|
| 1014 |                 return 1;
 | 
|---|
| 1015 |         }
 | 
|---|
| 1016 | 
 | 
|---|
| 1017 |         if(!strcmp(lname,"-")) {
 | 
|---|
| 1018 |                 handle = fileno(stdout);
 | 
|---|
| 1019 |         } else {
 | 
|---|
| 1020 |                 if (reget) {
 | 
|---|
| 1021 |                         handle = sys_open(lname, O_WRONLY|O_CREAT, 0644);
 | 
|---|
| 1022 |                         if (handle >= 0) {
 | 
|---|
| 1023 |                                 start = sys_lseek(handle, 0, SEEK_END);
 | 
|---|
| 1024 |                                 if (start == -1) {
 | 
|---|
| 1025 |                                         d_printf("Error seeking local file\n");
 | 
|---|
| 1026 |                                         return 1;
 | 
|---|
| 1027 |                                 }
 | 
|---|
| 1028 |                         }
 | 
|---|
| 1029 |                 } else {
 | 
|---|
| 1030 |                         handle = sys_open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
 | 
|---|
| 1031 |                 }
 | 
|---|
| 1032 |                 newhandle = true;
 | 
|---|
| 1033 |         }
 | 
|---|
| 1034 |         if (handle < 0) {
 | 
|---|
| 1035 |                 d_printf("Error opening local file %s\n",lname);
 | 
|---|
| 1036 |                 return 1;
 | 
|---|
| 1037 |         }
 | 
|---|
| 1038 | 
 | 
|---|
| 1039 | 
 | 
|---|
| 1040 |         if (!cli_qfileinfo(targetcli, fnum,
 | 
|---|
| 1041 |                            &attr, &size, NULL, NULL, NULL, NULL, NULL) &&
 | 
|---|
| 1042 |             !NT_STATUS_IS_OK(cli_getattrE(targetcli, fnum,
 | 
|---|
| 1043 |                           &attr, &size, NULL, NULL, NULL))) {
 | 
|---|
| 1044 |                 d_printf("getattrib: %s\n",cli_errstr(targetcli));
 | 
|---|
| 1045 |                 return 1;
 | 
|---|
| 1046 |         }
 | 
|---|
| 1047 | 
 | 
|---|
| 1048 |         DEBUG(1,("getting file %s of size %.0f as %s ",
 | 
|---|
| 1049 |                  rname, (double)size, lname));
 | 
|---|
| 1050 | 
 | 
|---|
| 1051 |         status = cli_pull(targetcli, fnum, start, size, io_bufsize,
 | 
|---|
| 1052 |                           writefile_sink, (void *)&handle, &nread);
 | 
|---|
| 1053 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 1054 |                 d_fprintf(stderr, "parallel_read returned %s\n",
 | 
|---|
| 1055 |                           nt_errstr(status));
 | 
|---|
| 1056 |                 cli_close(targetcli, fnum);
 | 
|---|
| 1057 |                 return 1;
 | 
|---|
| 1058 |         }
 | 
|---|
| 1059 | 
 | 
|---|
| 1060 |         if (!NT_STATUS_IS_OK(cli_close(targetcli, fnum))) {
 | 
|---|
| 1061 |                 d_printf("Error %s closing remote file\n",cli_errstr(cli));
 | 
|---|
| 1062 |                 rc = 1;
 | 
|---|
| 1063 |         }
 | 
|---|
| 1064 | 
 | 
|---|
| 1065 |         if (newhandle) {
 | 
|---|
| 1066 |                 close(handle);
 | 
|---|
| 1067 |         }
 | 
|---|
| 1068 | 
 | 
|---|
| 1069 |         if (archive_level >= 2 && (attr & aARCH)) {
 | 
|---|
| 1070 |                 cli_setatr(cli, rname, attr & ~(uint16)aARCH, 0);
 | 
|---|
| 1071 |         }
 | 
|---|
| 1072 | 
 | 
|---|
| 1073 |         {
 | 
|---|
| 1074 |                 struct timeval tp_end;
 | 
|---|
| 1075 |                 int this_time;
 | 
|---|
| 1076 | 
 | 
|---|
| 1077 |                 GetTimeOfDay(&tp_end);
 | 
|---|
| 1078 |                 this_time =
 | 
|---|
| 1079 |                         (tp_end.tv_sec - tp_start.tv_sec)*1000 +
 | 
|---|
| 1080 |                         (tp_end.tv_usec - tp_start.tv_usec)/1000;
 | 
|---|
| 1081 |                 get_total_time_ms += this_time;
 | 
|---|
| 1082 |                 get_total_size += nread;
 | 
|---|
| 1083 | 
 | 
|---|
| 1084 |                 DEBUG(1,("(%3.1f KiloBytes/sec) (average %3.1f KiloBytes/sec)\n",
 | 
|---|
| 1085 |                          nread / (1.024*this_time + 1.0e-4),
 | 
|---|
| 1086 |                          get_total_size / (1.024*get_total_time_ms)));
 | 
|---|
| 1087 |         }
 | 
|---|
| 1088 | 
 | 
|---|
| 1089 |         TALLOC_FREE(targetname);
 | 
|---|
| 1090 |         return rc;
 | 
|---|
| 1091 | }
 | 
|---|
| 1092 | 
 | 
|---|
| 1093 | /****************************************************************************
 | 
|---|
| 1094 |  Get a file.
 | 
|---|
| 1095 | ****************************************************************************/
 | 
|---|
| 1096 | 
 | 
|---|
| 1097 | static int cmd_get(void)
 | 
|---|
| 1098 | {
 | 
|---|
| 1099 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 1100 |         char *lname = NULL;
 | 
|---|
| 1101 |         char *rname = NULL;
 | 
|---|
| 1102 |         char *fname = NULL;
 | 
|---|
| 1103 | 
 | 
|---|
| 1104 |         rname = talloc_strdup(ctx, client_get_cur_dir());
 | 
|---|
| 1105 |         if (!rname) {
 | 
|---|
| 1106 |                 return 1;
 | 
|---|
| 1107 |         }
 | 
|---|
| 1108 | 
 | 
|---|
| 1109 |         if (!next_token_talloc(ctx, &cmd_ptr,&fname,NULL)) {
 | 
|---|
| 1110 |                 d_printf("get <filename> [localname]\n");
 | 
|---|
| 1111 |                 return 1;
 | 
|---|
| 1112 |         }
 | 
|---|
| 1113 |         rname = talloc_asprintf_append(rname, "%s", fname);
 | 
|---|
| 1114 |         if (!rname) {
 | 
|---|
| 1115 |                 return 1;
 | 
|---|
| 1116 |         }
 | 
|---|
| 1117 |         rname = clean_name(ctx, rname);
 | 
|---|
| 1118 |         if (!rname) {
 | 
|---|
| 1119 |                 return 1;
 | 
|---|
| 1120 |         }
 | 
|---|
| 1121 | 
 | 
|---|
| 1122 |         next_token_talloc(ctx, &cmd_ptr,&lname,NULL);
 | 
|---|
| 1123 |         if (!lname) {
 | 
|---|
| 1124 |                 lname = fname;
 | 
|---|
| 1125 |         }
 | 
|---|
| 1126 | 
 | 
|---|
| 1127 |         return do_get(rname, lname, false);
 | 
|---|
| 1128 | }
 | 
|---|
| 1129 | 
 | 
|---|
| 1130 | /****************************************************************************
 | 
|---|
| 1131 |  Do an mget operation on one file.
 | 
|---|
| 1132 | ****************************************************************************/
 | 
|---|
| 1133 | 
 | 
|---|
| 1134 | static void do_mget(file_info *finfo, const char *dir)
 | 
|---|
| 1135 | {
 | 
|---|
| 1136 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 1137 |         char *rname = NULL;
 | 
|---|
| 1138 |         char *quest = NULL;
 | 
|---|
| 1139 |         char *saved_curdir = NULL;
 | 
|---|
| 1140 |         char *mget_mask = NULL;
 | 
|---|
| 1141 |         char *new_cd = NULL;
 | 
|---|
| 1142 | 
 | 
|---|
| 1143 |         if (!finfo->name) {
 | 
|---|
| 1144 |                 return;
 | 
|---|
| 1145 |         }
 | 
|---|
| 1146 | 
 | 
|---|
| 1147 |         if (strequal(finfo->name,".") || strequal(finfo->name,".."))
 | 
|---|
| 1148 |                 return;
 | 
|---|
| 1149 | 
 | 
|---|
| 1150 |         if (abort_mget) {
 | 
|---|
| 1151 |                 d_printf("mget aborted\n");
 | 
|---|
| 1152 |                 return;
 | 
|---|
| 1153 |         }
 | 
|---|
| 1154 | 
 | 
|---|
| 1155 |         if (finfo->mode & aDIR) {
 | 
|---|
| 1156 |                 if (asprintf(&quest,
 | 
|---|
| 1157 |                          "Get directory %s? ",finfo->name) < 0) {
 | 
|---|
| 1158 |                         return;
 | 
|---|
| 1159 |                 }
 | 
|---|
| 1160 |         } else {
 | 
|---|
| 1161 |                 if (asprintf(&quest,
 | 
|---|
| 1162 |                          "Get file %s? ",finfo->name) < 0) {
 | 
|---|
| 1163 |                         return;
 | 
|---|
| 1164 |                 }
 | 
|---|
| 1165 |         }
 | 
|---|
| 1166 | 
 | 
|---|
| 1167 |         if (prompt && !yesno(quest)) {
 | 
|---|
| 1168 |                 SAFE_FREE(quest);
 | 
|---|
| 1169 |                 return;
 | 
|---|
| 1170 |         }
 | 
|---|
| 1171 |         SAFE_FREE(quest);
 | 
|---|
| 1172 | 
 | 
|---|
| 1173 |         if (!(finfo->mode & aDIR)) {
 | 
|---|
| 1174 |                 rname = talloc_asprintf(ctx,
 | 
|---|
| 1175 |                                 "%s%s",
 | 
|---|
| 1176 |                                 client_get_cur_dir(),
 | 
|---|
| 1177 |                                 finfo->name);
 | 
|---|
| 1178 |                 if (!rname) {
 | 
|---|
| 1179 |                         return;
 | 
|---|
| 1180 |                 }
 | 
|---|
| 1181 |                 do_get(rname, finfo->name, false);
 | 
|---|
| 1182 |                 TALLOC_FREE(rname);
 | 
|---|
| 1183 |                 return;
 | 
|---|
| 1184 |         }
 | 
|---|
| 1185 | 
 | 
|---|
| 1186 |         /* handle directories */
 | 
|---|
| 1187 |         saved_curdir = talloc_strdup(ctx, client_get_cur_dir());
 | 
|---|
| 1188 |         if (!saved_curdir) {
 | 
|---|
| 1189 |                 return;
 | 
|---|
| 1190 |         }
 | 
|---|
| 1191 | 
 | 
|---|
| 1192 |         new_cd = talloc_asprintf(ctx,
 | 
|---|
| 1193 |                                 "%s%s%s",
 | 
|---|
| 1194 |                                 client_get_cur_dir(),
 | 
|---|
| 1195 |                                 finfo->name,
 | 
|---|
| 1196 |                                 CLI_DIRSEP_STR);
 | 
|---|
| 1197 |         if (!new_cd) {
 | 
|---|
| 1198 |                 return;
 | 
|---|
| 1199 |         }
 | 
|---|
| 1200 |         client_set_cur_dir(new_cd);
 | 
|---|
| 1201 | 
 | 
|---|
| 1202 |         string_replace(finfo->name,'\\','/');
 | 
|---|
| 1203 |         if (lowercase) {
 | 
|---|
| 1204 |                 strlower_m(finfo->name);
 | 
|---|
| 1205 |         }
 | 
|---|
| 1206 | 
 | 
|---|
| 1207 |         if (!directory_exist(finfo->name) &&
 | 
|---|
| 1208 |             mkdir(finfo->name,0777) != 0) {
 | 
|---|
| 1209 |                 d_printf("failed to create directory %s\n",finfo->name);
 | 
|---|
| 1210 |                 client_set_cur_dir(saved_curdir);
 | 
|---|
| 1211 |                 return;
 | 
|---|
| 1212 |         }
 | 
|---|
| 1213 | 
 | 
|---|
| 1214 |         if (chdir(finfo->name) != 0) {
 | 
|---|
| 1215 |                 d_printf("failed to chdir to directory %s\n",finfo->name);
 | 
|---|
| 1216 |                 client_set_cur_dir(saved_curdir);
 | 
|---|
| 1217 |                 return;
 | 
|---|
| 1218 |         }
 | 
|---|
| 1219 | 
 | 
|---|
| 1220 |         mget_mask = talloc_asprintf(ctx,
 | 
|---|
| 1221 |                         "%s*",
 | 
|---|
| 1222 |                         client_get_cur_dir());
 | 
|---|
| 1223 | 
 | 
|---|
| 1224 |         if (!mget_mask) {
 | 
|---|
| 1225 |                 return;
 | 
|---|
| 1226 |         }
 | 
|---|
| 1227 | 
 | 
|---|
| 1228 |         do_list(mget_mask, aSYSTEM | aHIDDEN | aDIR,do_mget,false, true);
 | 
|---|
| 1229 |         if (chdir("..") == -1) {
 | 
|---|
| 1230 |                 d_printf("do_mget: failed to chdir to .. (error %s)\n",
 | 
|---|
| 1231 |                         strerror(errno) );
 | 
|---|
| 1232 |         }
 | 
|---|
| 1233 |         client_set_cur_dir(saved_curdir);
 | 
|---|
| 1234 |         TALLOC_FREE(mget_mask);
 | 
|---|
| 1235 |         TALLOC_FREE(saved_curdir);
 | 
|---|
| 1236 |         TALLOC_FREE(new_cd);
 | 
|---|
| 1237 | }
 | 
|---|
| 1238 | 
 | 
|---|
| 1239 | /****************************************************************************
 | 
|---|
| 1240 |  View the file using the pager.
 | 
|---|
| 1241 | ****************************************************************************/
 | 
|---|
| 1242 | 
 | 
|---|
| 1243 | static int cmd_more(void)
 | 
|---|
| 1244 | {
 | 
|---|
| 1245 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 1246 |         char *rname = NULL;
 | 
|---|
| 1247 |         char *fname = NULL;
 | 
|---|
| 1248 |         char *lname = NULL;
 | 
|---|
| 1249 |         char *pager_cmd = NULL;
 | 
|---|
| 1250 |         const char *pager;
 | 
|---|
| 1251 |         int fd;
 | 
|---|
| 1252 |         int rc = 0;
 | 
|---|
| 1253 | 
 | 
|---|
| 1254 |         rname = talloc_strdup(ctx, client_get_cur_dir());
 | 
|---|
| 1255 |         if (!rname) {
 | 
|---|
| 1256 |                 return 1;
 | 
|---|
| 1257 |         }
 | 
|---|
| 1258 | 
 | 
|---|
| 1259 |         lname = talloc_asprintf(ctx, "%s/smbmore.XXXXXX",tmpdir());
 | 
|---|
| 1260 |         if (!lname) {
 | 
|---|
| 1261 |                 return 1;
 | 
|---|
| 1262 |         }
 | 
|---|
| 1263 |         fd = mkstemp(lname);
 | 
|---|
| 1264 |         if (fd == -1) {
 | 
|---|
| 1265 |                 d_printf("failed to create temporary file for more\n");
 | 
|---|
| 1266 |                 return 1;
 | 
|---|
| 1267 |         }
 | 
|---|
| 1268 |         close(fd);
 | 
|---|
| 1269 | 
 | 
|---|
| 1270 |         if (!next_token_talloc(ctx, &cmd_ptr,&fname,NULL)) {
 | 
|---|
| 1271 |                 d_printf("more <filename>\n");
 | 
|---|
| 1272 |                 unlink(lname);
 | 
|---|
| 1273 |                 return 1;
 | 
|---|
| 1274 |         }
 | 
|---|
| 1275 |         rname = talloc_asprintf_append(rname, "%s", fname);
 | 
|---|
| 1276 |         if (!rname) {
 | 
|---|
| 1277 |                 return 1;
 | 
|---|
| 1278 |         }
 | 
|---|
| 1279 |         rname = clean_name(ctx,rname);
 | 
|---|
| 1280 |         if (!rname) {
 | 
|---|
| 1281 |                 return 1;
 | 
|---|
| 1282 |         }
 | 
|---|
| 1283 | 
 | 
|---|
| 1284 |         rc = do_get(rname, lname, false);
 | 
|---|
| 1285 | 
 | 
|---|
| 1286 |         pager=getenv("PAGER");
 | 
|---|
| 1287 | 
 | 
|---|
| 1288 |         pager_cmd = talloc_asprintf(ctx,
 | 
|---|
| 1289 |                                 "%s %s",
 | 
|---|
| 1290 |                                 (pager? pager:PAGER),
 | 
|---|
| 1291 |                                 lname);
 | 
|---|
| 1292 |         if (!pager_cmd) {
 | 
|---|
| 1293 |                 return 1;
 | 
|---|
| 1294 |         }
 | 
|---|
| 1295 |         if (system(pager_cmd) == -1) {
 | 
|---|
| 1296 |                 d_printf("system command '%s' returned -1\n",
 | 
|---|
| 1297 |                         pager_cmd);
 | 
|---|
| 1298 |         }
 | 
|---|
| 1299 |         unlink(lname);
 | 
|---|
| 1300 | 
 | 
|---|
| 1301 |         return rc;
 | 
|---|
| 1302 | }
 | 
|---|
| 1303 | 
 | 
|---|
| 1304 | /****************************************************************************
 | 
|---|
| 1305 |  Do a mget command.
 | 
|---|
| 1306 | ****************************************************************************/
 | 
|---|
| 1307 | 
 | 
|---|
| 1308 | static int cmd_mget(void)
 | 
|---|
| 1309 | {
 | 
|---|
| 1310 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 1311 |         uint16 attribute = aSYSTEM | aHIDDEN;
 | 
|---|
| 1312 |         char *mget_mask = NULL;
 | 
|---|
| 1313 |         char *buf = NULL;
 | 
|---|
| 1314 | 
 | 
|---|
| 1315 |         if (recurse) {
 | 
|---|
| 1316 |                 attribute |= aDIR;
 | 
|---|
| 1317 |         }
 | 
|---|
| 1318 | 
 | 
|---|
| 1319 |         abort_mget = false;
 | 
|---|
| 1320 | 
 | 
|---|
| 1321 |         while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 1322 |                 mget_mask = talloc_strdup(ctx, client_get_cur_dir());
 | 
|---|
| 1323 |                 if (!mget_mask) {
 | 
|---|
| 1324 |                         return 1;
 | 
|---|
| 1325 |                 }
 | 
|---|
| 1326 |                 if (*buf == CLI_DIRSEP_CHAR) {
 | 
|---|
| 1327 |                         mget_mask = talloc_strdup(ctx, buf);
 | 
|---|
| 1328 |                 } else {
 | 
|---|
| 1329 |                         mget_mask = talloc_asprintf_append(mget_mask,
 | 
|---|
| 1330 |                                                         "%s", buf);
 | 
|---|
| 1331 |                 }
 | 
|---|
| 1332 |                 if (!mget_mask) {
 | 
|---|
| 1333 |                         return 1;
 | 
|---|
| 1334 |                 }
 | 
|---|
| 1335 |                 do_list(mget_mask, attribute, do_mget, false, true);
 | 
|---|
| 1336 |         }
 | 
|---|
| 1337 | 
 | 
|---|
| 1338 |         if (mget_mask == NULL) {
 | 
|---|
| 1339 |                 d_printf("nothing to mget\n");
 | 
|---|
| 1340 |                 return 0;
 | 
|---|
| 1341 |         }
 | 
|---|
| 1342 | 
 | 
|---|
| 1343 |         if (!*mget_mask) {
 | 
|---|
| 1344 |                 mget_mask = talloc_asprintf(ctx,
 | 
|---|
| 1345 |                                         "%s*",
 | 
|---|
| 1346 |                                         client_get_cur_dir());
 | 
|---|
| 1347 |                 if (!mget_mask) {
 | 
|---|
| 1348 |                         return 1;
 | 
|---|
| 1349 |                 }
 | 
|---|
| 1350 |                 do_list(mget_mask, attribute, do_mget, false, true);
 | 
|---|
| 1351 |         }
 | 
|---|
| 1352 | 
 | 
|---|
| 1353 |         return 0;
 | 
|---|
| 1354 | }
 | 
|---|
| 1355 | 
 | 
|---|
| 1356 | /****************************************************************************
 | 
|---|
| 1357 |  Make a directory of name "name".
 | 
|---|
| 1358 | ****************************************************************************/
 | 
|---|
| 1359 | 
 | 
|---|
| 1360 | static bool do_mkdir(const char *name)
 | 
|---|
| 1361 | {
 | 
|---|
| 1362 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 1363 |         struct cli_state *targetcli;
 | 
|---|
| 1364 |         char *targetname = NULL;
 | 
|---|
| 1365 | 
 | 
|---|
| 1366 |         if (!cli_resolve_path(ctx, "", auth_info, cli, name, &targetcli, &targetname)) {
 | 
|---|
| 1367 |                 d_printf("mkdir %s: %s\n", name, cli_errstr(cli));
 | 
|---|
| 1368 |                 return false;
 | 
|---|
| 1369 |         }
 | 
|---|
| 1370 | 
 | 
|---|
| 1371 |         if (!NT_STATUS_IS_OK(cli_mkdir(targetcli, targetname))) {
 | 
|---|
| 1372 |                 d_printf("%s making remote directory %s\n",
 | 
|---|
| 1373 |                          cli_errstr(targetcli),name);
 | 
|---|
| 1374 |                 return false;
 | 
|---|
| 1375 |         }
 | 
|---|
| 1376 | 
 | 
|---|
| 1377 |         return true;
 | 
|---|
| 1378 | }
 | 
|---|
| 1379 | 
 | 
|---|
| 1380 | /****************************************************************************
 | 
|---|
| 1381 |  Show 8.3 name of a file.
 | 
|---|
| 1382 | ****************************************************************************/
 | 
|---|
| 1383 | 
 | 
|---|
| 1384 | static bool do_altname(const char *name)
 | 
|---|
| 1385 | {
 | 
|---|
| 1386 |         fstring altname;
 | 
|---|
| 1387 | 
 | 
|---|
| 1388 |         if (!NT_STATUS_IS_OK(cli_qpathinfo_alt_name(cli, name, altname))) {
 | 
|---|
| 1389 |                 d_printf("%s getting alt name for %s\n",
 | 
|---|
| 1390 |                          cli_errstr(cli),name);
 | 
|---|
| 1391 |                 return false;
 | 
|---|
| 1392 |         }
 | 
|---|
| 1393 |         d_printf("%s\n", altname);
 | 
|---|
| 1394 | 
 | 
|---|
| 1395 |         return true;
 | 
|---|
| 1396 | }
 | 
|---|
| 1397 | 
 | 
|---|
| 1398 | /****************************************************************************
 | 
|---|
| 1399 |  Exit client.
 | 
|---|
| 1400 | ****************************************************************************/
 | 
|---|
| 1401 | 
 | 
|---|
| 1402 | static int cmd_quit(void)
 | 
|---|
| 1403 | {
 | 
|---|
| 1404 |         cli_shutdown(cli);
 | 
|---|
| 1405 |         exit(0);
 | 
|---|
| 1406 |         /* NOTREACHED */
 | 
|---|
| 1407 |         return 0;
 | 
|---|
| 1408 | }
 | 
|---|
| 1409 | 
 | 
|---|
| 1410 | /****************************************************************************
 | 
|---|
| 1411 |  Make a directory.
 | 
|---|
| 1412 | ****************************************************************************/
 | 
|---|
| 1413 | 
 | 
|---|
| 1414 | static int cmd_mkdir(void)
 | 
|---|
| 1415 | {
 | 
|---|
| 1416 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 1417 |         char *mask = NULL;
 | 
|---|
| 1418 |         char *buf = NULL;
 | 
|---|
| 1419 | 
 | 
|---|
| 1420 |         mask = talloc_strdup(ctx, client_get_cur_dir());
 | 
|---|
| 1421 |         if (!mask) {
 | 
|---|
| 1422 |                 return 1;
 | 
|---|
| 1423 |         }
 | 
|---|
| 1424 | 
 | 
|---|
| 1425 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 1426 |                 if (!recurse) {
 | 
|---|
| 1427 |                         d_printf("mkdir <dirname>\n");
 | 
|---|
| 1428 |                 }
 | 
|---|
| 1429 |                 return 1;
 | 
|---|
| 1430 |         }
 | 
|---|
| 1431 |         mask = talloc_asprintf_append(mask, "%s", buf);
 | 
|---|
| 1432 |         if (!mask) {
 | 
|---|
| 1433 |                 return 1;
 | 
|---|
| 1434 |         }
 | 
|---|
| 1435 | 
 | 
|---|
| 1436 |         if (recurse) {
 | 
|---|
| 1437 |                 char *ddir = NULL;
 | 
|---|
| 1438 |                 char *ddir2 = NULL;
 | 
|---|
| 1439 |                 struct cli_state *targetcli;
 | 
|---|
| 1440 |                 char *targetname = NULL;
 | 
|---|
| 1441 |                 char *p = NULL;
 | 
|---|
| 1442 |                 char *saveptr;
 | 
|---|
| 1443 | 
 | 
|---|
| 1444 |                 ddir2 = talloc_strdup(ctx, "");
 | 
|---|
| 1445 |                 if (!ddir2) {
 | 
|---|
| 1446 |                         return 1;
 | 
|---|
| 1447 |                 }
 | 
|---|
| 1448 | 
 | 
|---|
| 1449 |                 if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
 | 
|---|
| 1450 |                         return 1;
 | 
|---|
| 1451 |                 }
 | 
|---|
| 1452 | 
 | 
|---|
| 1453 |                 ddir = talloc_strdup(ctx, targetname);
 | 
|---|
| 1454 |                 if (!ddir) {
 | 
|---|
| 1455 |                         return 1;
 | 
|---|
| 1456 |                 }
 | 
|---|
| 1457 |                 trim_char(ddir,'.','\0');
 | 
|---|
| 1458 |                 p = strtok_r(ddir, "/\\", &saveptr);
 | 
|---|
| 1459 |                 while (p) {
 | 
|---|
| 1460 |                         ddir2 = talloc_asprintf_append(ddir2, "%s", p);
 | 
|---|
| 1461 |                         if (!ddir2) {
 | 
|---|
| 1462 |                                 return 1;
 | 
|---|
| 1463 |                         }
 | 
|---|
| 1464 |                         if (!NT_STATUS_IS_OK(cli_chkpath(targetcli, ddir2))) {
 | 
|---|
| 1465 |                                 do_mkdir(ddir2);
 | 
|---|
| 1466 |                         }
 | 
|---|
| 1467 |                         ddir2 = talloc_asprintf_append(ddir2, "%s", CLI_DIRSEP_STR);
 | 
|---|
| 1468 |                         if (!ddir2) {
 | 
|---|
| 1469 |                                 return 1;
 | 
|---|
| 1470 |                         }
 | 
|---|
| 1471 |                         p = strtok_r(NULL, "/\\", &saveptr);
 | 
|---|
| 1472 |                 }
 | 
|---|
| 1473 |         } else {
 | 
|---|
| 1474 |                 do_mkdir(mask);
 | 
|---|
| 1475 |         }
 | 
|---|
| 1476 | 
 | 
|---|
| 1477 |         return 0;
 | 
|---|
| 1478 | }
 | 
|---|
| 1479 | 
 | 
|---|
| 1480 | /****************************************************************************
 | 
|---|
| 1481 |  Show alt name.
 | 
|---|
| 1482 | ****************************************************************************/
 | 
|---|
| 1483 | 
 | 
|---|
| 1484 | static int cmd_altname(void)
 | 
|---|
| 1485 | {
 | 
|---|
| 1486 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 1487 |         char *name;
 | 
|---|
| 1488 |         char *buf;
 | 
|---|
| 1489 | 
 | 
|---|
| 1490 |         name = talloc_strdup(ctx, client_get_cur_dir());
 | 
|---|
| 1491 |         if (!name) {
 | 
|---|
| 1492 |                 return 1;
 | 
|---|
| 1493 |         }
 | 
|---|
| 1494 | 
 | 
|---|
| 1495 |         if (!next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
 | 
|---|
| 1496 |                 d_printf("altname <file>\n");
 | 
|---|
| 1497 |                 return 1;
 | 
|---|
| 1498 |         }
 | 
|---|
| 1499 |         name = talloc_asprintf_append(name, "%s", buf);
 | 
|---|
| 1500 |         if (!name) {
 | 
|---|
| 1501 |                 return 1;
 | 
|---|
| 1502 |         }
 | 
|---|
| 1503 |         do_altname(name);
 | 
|---|
| 1504 |         return 0;
 | 
|---|
| 1505 | }
 | 
|---|
| 1506 | 
 | 
|---|
| 1507 | /****************************************************************************
 | 
|---|
| 1508 |  Show all info we can get
 | 
|---|
| 1509 | ****************************************************************************/
 | 
|---|
| 1510 | 
 | 
|---|
| 1511 | static int do_allinfo(const char *name)
 | 
|---|
| 1512 | {
 | 
|---|
| 1513 |         fstring altname;
 | 
|---|
| 1514 |         struct timespec b_time, a_time, m_time, c_time;
 | 
|---|
| 1515 |         SMB_OFF_T size;
 | 
|---|
| 1516 |         uint16_t mode;
 | 
|---|
| 1517 |         SMB_INO_T ino;
 | 
|---|
| 1518 |         NTTIME tmp;
 | 
|---|
| 1519 |         unsigned int num_streams;
 | 
|---|
| 1520 |         struct stream_struct *streams;
 | 
|---|
| 1521 |         unsigned int i;
 | 
|---|
| 1522 | 
 | 
|---|
| 1523 |         if (!NT_STATUS_IS_OK(cli_qpathinfo_alt_name(cli, name, altname))) {
 | 
|---|
| 1524 |                 d_printf("%s getting alt name for %s\n",
 | 
|---|
| 1525 |                          cli_errstr(cli),name);
 | 
|---|
| 1526 |                 return false;
 | 
|---|
| 1527 |         }
 | 
|---|
| 1528 |         d_printf("altname: %s\n", altname);
 | 
|---|
| 1529 | 
 | 
|---|
| 1530 |         if (!cli_qpathinfo2(cli, name, &b_time, &a_time, &m_time, &c_time,
 | 
|---|
| 1531 |                             &size, &mode, &ino)) {
 | 
|---|
| 1532 |                 d_printf("%s getting pathinfo for %s\n",
 | 
|---|
| 1533 |                          cli_errstr(cli),name);
 | 
|---|
| 1534 |                 return false;
 | 
|---|
| 1535 |         }
 | 
|---|
| 1536 | 
 | 
|---|
| 1537 |         unix_timespec_to_nt_time(&tmp, b_time);
 | 
|---|
| 1538 |         d_printf("create_time:    %s\n", nt_time_string(talloc_tos(), tmp));
 | 
|---|
| 1539 | 
 | 
|---|
| 1540 |         unix_timespec_to_nt_time(&tmp, a_time);
 | 
|---|
| 1541 |         d_printf("access_time:    %s\n", nt_time_string(talloc_tos(), tmp));
 | 
|---|
| 1542 | 
 | 
|---|
| 1543 |         unix_timespec_to_nt_time(&tmp, m_time);
 | 
|---|
| 1544 |         d_printf("write_time:     %s\n", nt_time_string(talloc_tos(), tmp));
 | 
|---|
| 1545 | 
 | 
|---|
| 1546 |         unix_timespec_to_nt_time(&tmp, c_time);
 | 
|---|
| 1547 |         d_printf("change_time:    %s\n", nt_time_string(talloc_tos(), tmp));
 | 
|---|
| 1548 | 
 | 
|---|
| 1549 |         if (!cli_qpathinfo_streams(cli, name, talloc_tos(), &num_streams,
 | 
|---|
| 1550 |                                    &streams)) {
 | 
|---|
| 1551 |                 d_printf("%s getting streams for %s\n",
 | 
|---|
| 1552 |                          cli_errstr(cli),name);
 | 
|---|
| 1553 |                 return false;
 | 
|---|
| 1554 |         }
 | 
|---|
| 1555 | 
 | 
|---|
| 1556 |         for (i=0; i<num_streams; i++) {
 | 
|---|
| 1557 |                 d_printf("stream: [%s], %lld bytes\n", streams[i].name,
 | 
|---|
| 1558 |                          (unsigned long long)streams[i].size);
 | 
|---|
| 1559 |         }
 | 
|---|
| 1560 | 
 | 
|---|
| 1561 |         return 0;
 | 
|---|
| 1562 | }
 | 
|---|
| 1563 | 
 | 
|---|
| 1564 | /****************************************************************************
 | 
|---|
| 1565 |  Show all info we can get
 | 
|---|
| 1566 | ****************************************************************************/
 | 
|---|
| 1567 | 
 | 
|---|
| 1568 | static int cmd_allinfo(void)
 | 
|---|
| 1569 | {
 | 
|---|
| 1570 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 1571 |         char *name;
 | 
|---|
| 1572 |         char *buf;
 | 
|---|
| 1573 | 
 | 
|---|
| 1574 |         name = talloc_strdup(ctx, client_get_cur_dir());
 | 
|---|
| 1575 |         if (!name) {
 | 
|---|
| 1576 |                 return 1;
 | 
|---|
| 1577 |         }
 | 
|---|
| 1578 | 
 | 
|---|
| 1579 |         if (!next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
 | 
|---|
| 1580 |                 d_printf("allinfo <file>\n");
 | 
|---|
| 1581 |                 return 1;
 | 
|---|
| 1582 |         }
 | 
|---|
| 1583 |         name = talloc_asprintf_append(name, "%s", buf);
 | 
|---|
| 1584 |         if (!name) {
 | 
|---|
| 1585 |                 return 1;
 | 
|---|
| 1586 |         }
 | 
|---|
| 1587 | 
 | 
|---|
| 1588 |         do_allinfo(name);
 | 
|---|
| 1589 | 
 | 
|---|
| 1590 |         return 0;
 | 
|---|
| 1591 | }
 | 
|---|
| 1592 | 
 | 
|---|
| 1593 | /****************************************************************************
 | 
|---|
| 1594 |  Put a single file.
 | 
|---|
| 1595 | ****************************************************************************/
 | 
|---|
| 1596 | 
 | 
|---|
| 1597 | static int do_put(const char *rname, const char *lname, bool reput)
 | 
|---|
| 1598 | {
 | 
|---|
| 1599 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 1600 |         uint16_t fnum;
 | 
|---|
| 1601 |         XFILE *f;
 | 
|---|
| 1602 |         SMB_OFF_T start = 0;
 | 
|---|
| 1603 |         int rc = 0;
 | 
|---|
| 1604 |         struct timeval tp_start;
 | 
|---|
| 1605 |         struct cli_state *targetcli;
 | 
|---|
| 1606 |         char *targetname = NULL;
 | 
|---|
| 1607 |         struct push_state state;
 | 
|---|
| 1608 |         NTSTATUS status;
 | 
|---|
| 1609 | 
 | 
|---|
| 1610 |         if (!cli_resolve_path(ctx, "", auth_info, cli, rname, &targetcli, &targetname)) {
 | 
|---|
| 1611 |                 d_printf("Failed to open %s: %s\n", rname, cli_errstr(cli));
 | 
|---|
| 1612 |                 return 1;
 | 
|---|
| 1613 |         }
 | 
|---|
| 1614 | 
 | 
|---|
| 1615 |         GetTimeOfDay(&tp_start);
 | 
|---|
| 1616 | 
 | 
|---|
| 1617 |         if (reput) {
 | 
|---|
| 1618 |                 status = cli_open(targetcli, targetname, O_RDWR|O_CREAT, DENY_NONE, &fnum);
 | 
|---|
| 1619 |                 if (NT_STATUS_IS_OK(status)) {
 | 
|---|
| 1620 |                         if (!cli_qfileinfo(targetcli, fnum, NULL, &start, NULL, NULL, NULL, NULL, NULL) &&
 | 
|---|
| 1621 |                             !NT_STATUS_IS_OK(cli_getattrE(targetcli, fnum, NULL, &start, NULL, NULL, NULL))) {
 | 
|---|
| 1622 |                                 d_printf("getattrib: %s\n",cli_errstr(cli));
 | 
|---|
| 1623 |                                 return 1;
 | 
|---|
| 1624 |                         }
 | 
|---|
| 1625 |                 }
 | 
|---|
| 1626 |         } else {
 | 
|---|
| 1627 |                 status = cli_open(targetcli, targetname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum);
 | 
|---|
| 1628 |         }
 | 
|---|
| 1629 | 
 | 
|---|
| 1630 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 1631 |                 d_printf("%s opening remote file %s\n",cli_errstr(targetcli),rname);
 | 
|---|
| 1632 |                 return 1;
 | 
|---|
| 1633 |         }
 | 
|---|
| 1634 | 
 | 
|---|
| 1635 |         /* allow files to be piped into smbclient
 | 
|---|
| 1636 |            jdblair 24.jun.98
 | 
|---|
| 1637 | 
 | 
|---|
| 1638 |            Note that in this case this function will exit(0) rather
 | 
|---|
| 1639 |            than returning. */
 | 
|---|
| 1640 |         if (!strcmp(lname, "-")) {
 | 
|---|
| 1641 |                 f = x_stdin;
 | 
|---|
| 1642 |                 /* size of file is not known */
 | 
|---|
| 1643 |         } else {
 | 
|---|
| 1644 |                 f = x_fopen(lname,O_RDONLY, 0);
 | 
|---|
| 1645 |                 if (f && reput) {
 | 
|---|
| 1646 |                         if (x_tseek(f, start, SEEK_SET) == -1) {
 | 
|---|
| 1647 |                                 d_printf("Error seeking local file\n");
 | 
|---|
| 1648 |                                 x_fclose(f);
 | 
|---|
| 1649 |                                 return 1;
 | 
|---|
| 1650 |                         }
 | 
|---|
| 1651 |                 }
 | 
|---|
| 1652 |         }
 | 
|---|
| 1653 | 
 | 
|---|
| 1654 |         if (!f) {
 | 
|---|
| 1655 |                 d_printf("Error opening local file %s\n",lname);
 | 
|---|
| 1656 |                 return 1;
 | 
|---|
| 1657 |         }
 | 
|---|
| 1658 | 
 | 
|---|
| 1659 |         DEBUG(1,("putting file %s as %s ",lname,
 | 
|---|
| 1660 |                  rname));
 | 
|---|
| 1661 | 
 | 
|---|
| 1662 |         x_setvbuf(f, NULL, X_IOFBF, io_bufsize);
 | 
|---|
| 1663 | 
 | 
|---|
| 1664 |         state.f = f;
 | 
|---|
| 1665 |         state.nread = 0;
 | 
|---|
| 1666 | 
 | 
|---|
| 1667 |         status = cli_push(targetcli, fnum, 0, 0, io_bufsize, push_source,
 | 
|---|
| 1668 |                           &state);
 | 
|---|
| 1669 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 1670 |                 d_fprintf(stderr, "cli_push returned %s\n", nt_errstr(status));
 | 
|---|
| 1671 |         }
 | 
|---|
| 1672 | 
 | 
|---|
| 1673 |         if (!NT_STATUS_IS_OK(cli_close(targetcli, fnum))) {
 | 
|---|
| 1674 |                 d_printf("%s closing remote file %s\n",cli_errstr(cli),rname);
 | 
|---|
| 1675 |                 if (f != x_stdin) {
 | 
|---|
| 1676 |                         x_fclose(f);
 | 
|---|
| 1677 |                 }
 | 
|---|
| 1678 |                 return 1;
 | 
|---|
| 1679 |         }
 | 
|---|
| 1680 | 
 | 
|---|
| 1681 |         if (f != x_stdin) {
 | 
|---|
| 1682 |                 x_fclose(f);
 | 
|---|
| 1683 |         }
 | 
|---|
| 1684 | 
 | 
|---|
| 1685 |         {
 | 
|---|
| 1686 |                 struct timeval tp_end;
 | 
|---|
| 1687 |                 int this_time;
 | 
|---|
| 1688 | 
 | 
|---|
| 1689 |                 GetTimeOfDay(&tp_end);
 | 
|---|
| 1690 |                 this_time =
 | 
|---|
| 1691 |                         (tp_end.tv_sec - tp_start.tv_sec)*1000 +
 | 
|---|
| 1692 |                         (tp_end.tv_usec - tp_start.tv_usec)/1000;
 | 
|---|
| 1693 |                 put_total_time_ms += this_time;
 | 
|---|
| 1694 |                 put_total_size += state.nread;
 | 
|---|
| 1695 | 
 | 
|---|
| 1696 |                 DEBUG(1,("(%3.1f kb/s) (average %3.1f kb/s)\n",
 | 
|---|
| 1697 |                          state.nread / (1.024*this_time + 1.0e-4),
 | 
|---|
| 1698 |                          put_total_size / (1.024*put_total_time_ms)));
 | 
|---|
| 1699 |         }
 | 
|---|
| 1700 | 
 | 
|---|
| 1701 |         if (f == x_stdin) {
 | 
|---|
| 1702 |                 cli_shutdown(cli);
 | 
|---|
| 1703 |                 exit(0);
 | 
|---|
| 1704 |         }
 | 
|---|
| 1705 | 
 | 
|---|
| 1706 |         return rc;
 | 
|---|
| 1707 | }
 | 
|---|
| 1708 | 
 | 
|---|
| 1709 | /****************************************************************************
 | 
|---|
| 1710 |  Put a file.
 | 
|---|
| 1711 | ****************************************************************************/
 | 
|---|
| 1712 | 
 | 
|---|
| 1713 | static int cmd_put(void)
 | 
|---|
| 1714 | {
 | 
|---|
| 1715 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 1716 |         char *lname;
 | 
|---|
| 1717 |         char *rname;
 | 
|---|
| 1718 |         char *buf;
 | 
|---|
| 1719 | 
 | 
|---|
| 1720 |         rname = talloc_strdup(ctx, client_get_cur_dir());
 | 
|---|
| 1721 |         if (!rname) {
 | 
|---|
| 1722 |                 return 1;
 | 
|---|
| 1723 |         }
 | 
|---|
| 1724 | 
 | 
|---|
| 1725 |         if (!next_token_talloc(ctx, &cmd_ptr,&lname,NULL)) {
 | 
|---|
| 1726 |                 d_printf("put <filename>\n");
 | 
|---|
| 1727 |                 return 1;
 | 
|---|
| 1728 |         }
 | 
|---|
| 1729 | 
 | 
|---|
| 1730 |         if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 1731 |                 rname = talloc_asprintf_append(rname, "%s", buf);
 | 
|---|
| 1732 |         } else {
 | 
|---|
| 1733 |                 rname = talloc_asprintf_append(rname, "%s", lname);
 | 
|---|
| 1734 |         }
 | 
|---|
| 1735 |         if (!rname) {
 | 
|---|
| 1736 |                 return 1;
 | 
|---|
| 1737 |         }
 | 
|---|
| 1738 | 
 | 
|---|
| 1739 |         rname = clean_name(ctx, rname);
 | 
|---|
| 1740 |         if (!rname) {
 | 
|---|
| 1741 |                 return 1;
 | 
|---|
| 1742 |         }
 | 
|---|
| 1743 | 
 | 
|---|
| 1744 |         {
 | 
|---|
| 1745 |                 SMB_STRUCT_STAT st;
 | 
|---|
| 1746 |                 /* allow '-' to represent stdin
 | 
|---|
| 1747 |                    jdblair, 24.jun.98 */
 | 
|---|
| 1748 |                 if (!file_exist_stat(lname, &st, false) &&
 | 
|---|
| 1749 |                     (strcmp(lname,"-"))) {
 | 
|---|
| 1750 |                         d_printf("%s does not exist\n",lname);
 | 
|---|
| 1751 |                         return 1;
 | 
|---|
| 1752 |                 }
 | 
|---|
| 1753 |         }
 | 
|---|
| 1754 | 
 | 
|---|
| 1755 |         return do_put(rname, lname, false);
 | 
|---|
| 1756 | }
 | 
|---|
| 1757 | 
 | 
|---|
| 1758 | /*************************************
 | 
|---|
| 1759 |  File list structure.
 | 
|---|
| 1760 | *************************************/
 | 
|---|
| 1761 | 
 | 
|---|
| 1762 | static struct file_list {
 | 
|---|
| 1763 |         struct file_list *prev, *next;
 | 
|---|
| 1764 |         char *file_path;
 | 
|---|
| 1765 |         bool isdir;
 | 
|---|
| 1766 | } *file_list;
 | 
|---|
| 1767 | 
 | 
|---|
| 1768 | /****************************************************************************
 | 
|---|
| 1769 |  Free a file_list structure.
 | 
|---|
| 1770 | ****************************************************************************/
 | 
|---|
| 1771 | 
 | 
|---|
| 1772 | static void free_file_list (struct file_list *l_head)
 | 
|---|
| 1773 | {
 | 
|---|
| 1774 |         struct file_list *list, *next;
 | 
|---|
| 1775 | 
 | 
|---|
| 1776 |         for (list = l_head; list; list = next) {
 | 
|---|
| 1777 |                 next = list->next;
 | 
|---|
| 1778 |                 DLIST_REMOVE(l_head, list);
 | 
|---|
| 1779 |                 SAFE_FREE(list->file_path);
 | 
|---|
| 1780 |                 SAFE_FREE(list);
 | 
|---|
| 1781 |         }
 | 
|---|
| 1782 | }
 | 
|---|
| 1783 | 
 | 
|---|
| 1784 | /****************************************************************************
 | 
|---|
| 1785 |  Seek in a directory/file list until you get something that doesn't start with
 | 
|---|
| 1786 |  the specified name.
 | 
|---|
| 1787 | ****************************************************************************/
 | 
|---|
| 1788 | 
 | 
|---|
| 1789 | static bool seek_list(struct file_list *list, char *name)
 | 
|---|
| 1790 | {
 | 
|---|
| 1791 |         while (list) {
 | 
|---|
| 1792 |                 trim_string(list->file_path,"./","\n");
 | 
|---|
| 1793 |                 if (strncmp(list->file_path, name, strlen(name)) != 0) {
 | 
|---|
| 1794 |                         return true;
 | 
|---|
| 1795 |                 }
 | 
|---|
| 1796 |                 list = list->next;
 | 
|---|
| 1797 |         }
 | 
|---|
| 1798 | 
 | 
|---|
| 1799 |         return false;
 | 
|---|
| 1800 | }
 | 
|---|
| 1801 | 
 | 
|---|
| 1802 | /****************************************************************************
 | 
|---|
| 1803 |  Set the file selection mask.
 | 
|---|
| 1804 | ****************************************************************************/
 | 
|---|
| 1805 | 
 | 
|---|
| 1806 | static int cmd_select(void)
 | 
|---|
| 1807 | {
 | 
|---|
| 1808 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 1809 |         char *new_fs = NULL;
 | 
|---|
| 1810 |         next_token_talloc(ctx, &cmd_ptr,&new_fs,NULL)
 | 
|---|
| 1811 |                 ;
 | 
|---|
| 1812 |         if (new_fs) {
 | 
|---|
| 1813 |                 client_set_fileselection(new_fs);
 | 
|---|
| 1814 |         } else {
 | 
|---|
| 1815 |                 client_set_fileselection("");
 | 
|---|
| 1816 |         }
 | 
|---|
| 1817 |         return 0;
 | 
|---|
| 1818 | }
 | 
|---|
| 1819 | 
 | 
|---|
| 1820 | /****************************************************************************
 | 
|---|
| 1821 |   Recursive file matching function act as find
 | 
|---|
| 1822 |   match must be always set to true when calling this function
 | 
|---|
| 1823 | ****************************************************************************/
 | 
|---|
| 1824 | 
 | 
|---|
| 1825 | static int file_find(struct file_list **list, const char *directory,
 | 
|---|
| 1826 |                       const char *expression, bool match)
 | 
|---|
| 1827 | {
 | 
|---|
| 1828 |         SMB_STRUCT_DIR *dir;
 | 
|---|
| 1829 |         struct file_list *entry;
 | 
|---|
| 1830 |         struct stat statbuf;
 | 
|---|
| 1831 |         int ret;
 | 
|---|
| 1832 |         char *path;
 | 
|---|
| 1833 |         bool isdir;
 | 
|---|
| 1834 |         const char *dname;
 | 
|---|
| 1835 | 
 | 
|---|
| 1836 |         dir = sys_opendir(directory);
 | 
|---|
| 1837 |         if (!dir)
 | 
|---|
| 1838 |                 return -1;
 | 
|---|
| 1839 | 
 | 
|---|
| 1840 |         while ((dname = readdirname(dir))) {
 | 
|---|
| 1841 |                 if (!strcmp("..", dname))
 | 
|---|
| 1842 |                         continue;
 | 
|---|
| 1843 |                 if (!strcmp(".", dname))
 | 
|---|
| 1844 |                         continue;
 | 
|---|
| 1845 | 
 | 
|---|
| 1846 |                 if (asprintf(&path, "%s/%s", directory, dname) <= 0) {
 | 
|---|
| 1847 |                         continue;
 | 
|---|
| 1848 |                 }
 | 
|---|
| 1849 | 
 | 
|---|
| 1850 |                 isdir = false;
 | 
|---|
| 1851 |                 if (!match || !gen_fnmatch(expression, dname)) {
 | 
|---|
| 1852 |                         if (recurse) {
 | 
|---|
| 1853 |                                 ret = stat(path, &statbuf);
 | 
|---|
| 1854 |                                 if (ret == 0) {
 | 
|---|
| 1855 |                                         if (S_ISDIR(statbuf.st_mode)) {
 | 
|---|
| 1856 |                                                 isdir = true;
 | 
|---|
| 1857 |                                                 ret = file_find(list, path, expression, false);
 | 
|---|
| 1858 |                                         }
 | 
|---|
| 1859 |                                 } else {
 | 
|---|
| 1860 |                                         d_printf("file_find: cannot stat file %s\n", path);
 | 
|---|
| 1861 |                                 }
 | 
|---|
| 1862 | 
 | 
|---|
| 1863 |                                 if (ret == -1) {
 | 
|---|
| 1864 |                                         SAFE_FREE(path);
 | 
|---|
| 1865 |                                         sys_closedir(dir);
 | 
|---|
| 1866 |                                         return -1;
 | 
|---|
| 1867 |                                 }
 | 
|---|
| 1868 |                         }
 | 
|---|
| 1869 |                         entry = SMB_MALLOC_P(struct file_list);
 | 
|---|
| 1870 |                         if (!entry) {
 | 
|---|
| 1871 |                                 d_printf("Out of memory in file_find\n");
 | 
|---|
| 1872 |                                 sys_closedir(dir);
 | 
|---|
| 1873 |                                 return -1;
 | 
|---|
| 1874 |                         }
 | 
|---|
| 1875 |                         entry->file_path = path;
 | 
|---|
| 1876 |                         entry->isdir = isdir;
 | 
|---|
| 1877 |                         DLIST_ADD(*list, entry);
 | 
|---|
| 1878 |                 } else {
 | 
|---|
| 1879 |                         SAFE_FREE(path);
 | 
|---|
| 1880 |                 }
 | 
|---|
| 1881 |         }
 | 
|---|
| 1882 | 
 | 
|---|
| 1883 |         sys_closedir(dir);
 | 
|---|
| 1884 |         return 0;
 | 
|---|
| 1885 | }
 | 
|---|
| 1886 | 
 | 
|---|
| 1887 | /****************************************************************************
 | 
|---|
| 1888 |  mput some files.
 | 
|---|
| 1889 | ****************************************************************************/
 | 
|---|
| 1890 | 
 | 
|---|
| 1891 | static int cmd_mput(void)
 | 
|---|
| 1892 | {
 | 
|---|
| 1893 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 1894 |         char *p = NULL;
 | 
|---|
| 1895 | 
 | 
|---|
| 1896 |         while (next_token_talloc(ctx, &cmd_ptr,&p,NULL)) {
 | 
|---|
| 1897 |                 int ret;
 | 
|---|
| 1898 |                 struct file_list *temp_list;
 | 
|---|
| 1899 |                 char *quest, *lname, *rname;
 | 
|---|
| 1900 | 
 | 
|---|
| 1901 |                 file_list = NULL;
 | 
|---|
| 1902 | 
 | 
|---|
| 1903 |                 ret = file_find(&file_list, ".", p, true);
 | 
|---|
| 1904 |                 if (ret) {
 | 
|---|
| 1905 |                         free_file_list(file_list);
 | 
|---|
| 1906 |                         continue;
 | 
|---|
| 1907 |                 }
 | 
|---|
| 1908 | 
 | 
|---|
| 1909 |                 quest = NULL;
 | 
|---|
| 1910 |                 lname = NULL;
 | 
|---|
| 1911 |                 rname = NULL;
 | 
|---|
| 1912 | 
 | 
|---|
| 1913 |                 for (temp_list = file_list; temp_list;
 | 
|---|
| 1914 |                      temp_list = temp_list->next) {
 | 
|---|
| 1915 | 
 | 
|---|
| 1916 |                         SAFE_FREE(lname);
 | 
|---|
| 1917 |                         if (asprintf(&lname, "%s/", temp_list->file_path) <= 0) {
 | 
|---|
| 1918 |                                 continue;
 | 
|---|
| 1919 |                         }
 | 
|---|
| 1920 |                         trim_string(lname, "./", "/");
 | 
|---|
| 1921 | 
 | 
|---|
| 1922 |                         /* check if it's a directory */
 | 
|---|
| 1923 |                         if (temp_list->isdir) {
 | 
|---|
| 1924 |                                 /* if (!recurse) continue; */
 | 
|---|
| 1925 | 
 | 
|---|
| 1926 |                                 SAFE_FREE(quest);
 | 
|---|
| 1927 |                                 if (asprintf(&quest, "Put directory %s? ", lname) < 0) {
 | 
|---|
| 1928 |                                         break;
 | 
|---|
| 1929 |                                 }
 | 
|---|
| 1930 |                                 if (prompt && !yesno(quest)) { /* No */
 | 
|---|
| 1931 |                                         /* Skip the directory */
 | 
|---|
| 1932 |                                         lname[strlen(lname)-1] = '/';
 | 
|---|
| 1933 |                                         if (!seek_list(temp_list, lname))
 | 
|---|
| 1934 |                                                 break;
 | 
|---|
| 1935 |                                 } else { /* Yes */
 | 
|---|
| 1936 |                                         SAFE_FREE(rname);
 | 
|---|
| 1937 |                                         if(asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) {
 | 
|---|
| 1938 |                                                 break;
 | 
|---|
| 1939 |                                         }
 | 
|---|
| 1940 |                                         normalize_name(rname);
 | 
|---|
| 1941 |                                         if (!NT_STATUS_IS_OK(cli_chkpath(cli, rname)) &&
 | 
|---|
| 1942 |                                             !do_mkdir(rname)) {
 | 
|---|
| 1943 |                                                 DEBUG (0, ("Unable to make dir, skipping..."));
 | 
|---|
| 1944 |                                                 /* Skip the directory */
 | 
|---|
| 1945 |                                                 lname[strlen(lname)-1] = '/';
 | 
|---|
| 1946 |                                                 if (!seek_list(temp_list, lname)) {
 | 
|---|
| 1947 |                                                         break;
 | 
|---|
| 1948 |                                                 }
 | 
|---|
| 1949 |                                         }
 | 
|---|
| 1950 |                                 }
 | 
|---|
| 1951 |                                 continue;
 | 
|---|
| 1952 |                         } else {
 | 
|---|
| 1953 |                                 SAFE_FREE(quest);
 | 
|---|
| 1954 |                                 if (asprintf(&quest,"Put file %s? ", lname) < 0) {
 | 
|---|
| 1955 |                                         break;
 | 
|---|
| 1956 |                                 }
 | 
|---|
| 1957 |                                 if (prompt && !yesno(quest)) {
 | 
|---|
| 1958 |                                         /* No */
 | 
|---|
| 1959 |                                         continue;
 | 
|---|
| 1960 |                                 }
 | 
|---|
| 1961 | 
 | 
|---|
| 1962 |                                 /* Yes */
 | 
|---|
| 1963 |                                 SAFE_FREE(rname);
 | 
|---|
| 1964 |                                 if (asprintf(&rname, "%s%s", client_get_cur_dir(), lname) < 0) {
 | 
|---|
| 1965 |                                         break;
 | 
|---|
| 1966 |                                 }
 | 
|---|
| 1967 |                         }
 | 
|---|
| 1968 | 
 | 
|---|
| 1969 |                         normalize_name(rname);
 | 
|---|
| 1970 | 
 | 
|---|
| 1971 |                         do_put(rname, lname, false);
 | 
|---|
| 1972 |                 }
 | 
|---|
| 1973 |                 free_file_list(file_list);
 | 
|---|
| 1974 |                 SAFE_FREE(quest);
 | 
|---|
| 1975 |                 SAFE_FREE(lname);
 | 
|---|
| 1976 |                 SAFE_FREE(rname);
 | 
|---|
| 1977 |         }
 | 
|---|
| 1978 | 
 | 
|---|
| 1979 |         return 0;
 | 
|---|
| 1980 | }
 | 
|---|
| 1981 | 
 | 
|---|
| 1982 | /****************************************************************************
 | 
|---|
| 1983 |  Cancel a print job.
 | 
|---|
| 1984 | ****************************************************************************/
 | 
|---|
| 1985 | 
 | 
|---|
| 1986 | static int do_cancel(int job)
 | 
|---|
| 1987 | {
 | 
|---|
| 1988 |         if (cli_printjob_del(cli, job)) {
 | 
|---|
| 1989 |                 d_printf("Job %d cancelled\n",job);
 | 
|---|
| 1990 |                 return 0;
 | 
|---|
| 1991 |         } else {
 | 
|---|
| 1992 |                 d_printf("Error cancelling job %d : %s\n",job,cli_errstr(cli));
 | 
|---|
| 1993 |                 return 1;
 | 
|---|
| 1994 |         }
 | 
|---|
| 1995 | }
 | 
|---|
| 1996 | 
 | 
|---|
| 1997 | /****************************************************************************
 | 
|---|
| 1998 |  Cancel a print job.
 | 
|---|
| 1999 | ****************************************************************************/
 | 
|---|
| 2000 | 
 | 
|---|
| 2001 | static int cmd_cancel(void)
 | 
|---|
| 2002 | {
 | 
|---|
| 2003 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2004 |         char *buf = NULL;
 | 
|---|
| 2005 |         int job;
 | 
|---|
| 2006 | 
 | 
|---|
| 2007 |         if (!next_token_talloc(ctx, &cmd_ptr, &buf,NULL)) {
 | 
|---|
| 2008 |                 d_printf("cancel <jobid> ...\n");
 | 
|---|
| 2009 |                 return 1;
 | 
|---|
| 2010 |         }
 | 
|---|
| 2011 |         do {
 | 
|---|
| 2012 |                 job = atoi(buf);
 | 
|---|
| 2013 |                 do_cancel(job);
 | 
|---|
| 2014 |         } while (next_token_talloc(ctx, &cmd_ptr,&buf,NULL));
 | 
|---|
| 2015 | 
 | 
|---|
| 2016 |         return 0;
 | 
|---|
| 2017 | }
 | 
|---|
| 2018 | 
 | 
|---|
| 2019 | /****************************************************************************
 | 
|---|
| 2020 |  Print a file.
 | 
|---|
| 2021 | ****************************************************************************/
 | 
|---|
| 2022 | 
 | 
|---|
| 2023 | static int cmd_print(void)
 | 
|---|
| 2024 | {
 | 
|---|
| 2025 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2026 |         char *lname = NULL;
 | 
|---|
| 2027 |         char *rname = NULL;
 | 
|---|
| 2028 |         char *p = NULL;
 | 
|---|
| 2029 | 
 | 
|---|
| 2030 |         if (!next_token_talloc(ctx, &cmd_ptr, &lname,NULL)) {
 | 
|---|
| 2031 |                 d_printf("print <filename>\n");
 | 
|---|
| 2032 |                 return 1;
 | 
|---|
| 2033 |         }
 | 
|---|
| 2034 | 
 | 
|---|
| 2035 |         rname = talloc_strdup(ctx, lname);
 | 
|---|
| 2036 |         if (!rname) {
 | 
|---|
| 2037 |                 return 1;
 | 
|---|
| 2038 |         }
 | 
|---|
| 2039 |         p = strrchr_m(rname,'/');
 | 
|---|
| 2040 |         if (p) {
 | 
|---|
| 2041 |                 rname = talloc_asprintf(ctx,
 | 
|---|
| 2042 |                                         "%s-%d",
 | 
|---|
| 2043 |                                         p+1,
 | 
|---|
| 2044 |                                         (int)sys_getpid());
 | 
|---|
| 2045 |         }
 | 
|---|
| 2046 |         if (strequal(lname,"-")) {
 | 
|---|
| 2047 |                 rname = talloc_asprintf(ctx,
 | 
|---|
| 2048 |                                 "stdin-%d",
 | 
|---|
| 2049 |                                 (int)sys_getpid());
 | 
|---|
| 2050 |         }
 | 
|---|
| 2051 |         if (!rname) {
 | 
|---|
| 2052 |                 return 1;
 | 
|---|
| 2053 |         }
 | 
|---|
| 2054 | 
 | 
|---|
| 2055 |         return do_put(rname, lname, false);
 | 
|---|
| 2056 | }
 | 
|---|
| 2057 | 
 | 
|---|
| 2058 | /****************************************************************************
 | 
|---|
| 2059 |  Show a print queue entry.
 | 
|---|
| 2060 | ****************************************************************************/
 | 
|---|
| 2061 | 
 | 
|---|
| 2062 | static void queue_fn(struct print_job_info *p)
 | 
|---|
| 2063 | {
 | 
|---|
| 2064 |         d_printf("%-6d   %-9d    %s\n", (int)p->id, (int)p->size, p->name);
 | 
|---|
| 2065 | }
 | 
|---|
| 2066 | 
 | 
|---|
| 2067 | /****************************************************************************
 | 
|---|
| 2068 |  Show a print queue.
 | 
|---|
| 2069 | ****************************************************************************/
 | 
|---|
| 2070 | 
 | 
|---|
| 2071 | static int cmd_queue(void)
 | 
|---|
| 2072 | {
 | 
|---|
| 2073 |         cli_print_queue(cli, queue_fn);
 | 
|---|
| 2074 |         return 0;
 | 
|---|
| 2075 | }
 | 
|---|
| 2076 | 
 | 
|---|
| 2077 | /****************************************************************************
 | 
|---|
| 2078 |  Delete some files.
 | 
|---|
| 2079 | ****************************************************************************/
 | 
|---|
| 2080 | 
 | 
|---|
| 2081 | static void do_del(file_info *finfo, const char *dir)
 | 
|---|
| 2082 | {
 | 
|---|
| 2083 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2084 |         char *mask = NULL;
 | 
|---|
| 2085 | 
 | 
|---|
| 2086 |         mask = talloc_asprintf(ctx,
 | 
|---|
| 2087 |                                 "%s%c%s",
 | 
|---|
| 2088 |                                 dir,
 | 
|---|
| 2089 |                                 CLI_DIRSEP_CHAR,
 | 
|---|
| 2090 |                                 finfo->name);
 | 
|---|
| 2091 |         if (!mask) {
 | 
|---|
| 2092 |                 return;
 | 
|---|
| 2093 |         }
 | 
|---|
| 2094 | 
 | 
|---|
| 2095 |         if (finfo->mode & aDIR) {
 | 
|---|
| 2096 |                 TALLOC_FREE(mask);
 | 
|---|
| 2097 |                 return;
 | 
|---|
| 2098 |         }
 | 
|---|
| 2099 | 
 | 
|---|
| 2100 |         if (!NT_STATUS_IS_OK(cli_unlink(finfo->cli, mask, aSYSTEM | aHIDDEN))) {
 | 
|---|
| 2101 |                 d_printf("%s deleting remote file %s\n",
 | 
|---|
| 2102 |                                 cli_errstr(finfo->cli),mask);
 | 
|---|
| 2103 |         }
 | 
|---|
| 2104 |         TALLOC_FREE(mask);
 | 
|---|
| 2105 | }
 | 
|---|
| 2106 | 
 | 
|---|
| 2107 | /****************************************************************************
 | 
|---|
| 2108 |  Delete some files.
 | 
|---|
| 2109 | ****************************************************************************/
 | 
|---|
| 2110 | 
 | 
|---|
| 2111 | static int cmd_del(void)
 | 
|---|
| 2112 | {
 | 
|---|
| 2113 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2114 |         char *mask = NULL;
 | 
|---|
| 2115 |         char *buf = NULL;
 | 
|---|
| 2116 |         uint16 attribute = aSYSTEM | aHIDDEN;
 | 
|---|
| 2117 | 
 | 
|---|
| 2118 |         if (recurse) {
 | 
|---|
| 2119 |                 attribute |= aDIR;
 | 
|---|
| 2120 |         }
 | 
|---|
| 2121 | 
 | 
|---|
| 2122 |         mask = talloc_strdup(ctx, client_get_cur_dir());
 | 
|---|
| 2123 |         if (!mask) {
 | 
|---|
| 2124 |                 return 1;
 | 
|---|
| 2125 |         }
 | 
|---|
| 2126 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2127 |                 d_printf("del <filename>\n");
 | 
|---|
| 2128 |                 return 1;
 | 
|---|
| 2129 |         }
 | 
|---|
| 2130 |         mask = talloc_asprintf_append(mask, "%s", buf);
 | 
|---|
| 2131 |         if (!mask) {
 | 
|---|
| 2132 |                 return 1;
 | 
|---|
| 2133 |         }
 | 
|---|
| 2134 | 
 | 
|---|
| 2135 |         do_list(mask,attribute,do_del,false,false);
 | 
|---|
| 2136 |         return 0;
 | 
|---|
| 2137 | }
 | 
|---|
| 2138 | 
 | 
|---|
| 2139 | /****************************************************************************
 | 
|---|
| 2140 |  Wildcard delete some files.
 | 
|---|
| 2141 | ****************************************************************************/
 | 
|---|
| 2142 | 
 | 
|---|
| 2143 | static int cmd_wdel(void)
 | 
|---|
| 2144 | {
 | 
|---|
| 2145 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2146 |         char *mask = NULL;
 | 
|---|
| 2147 |         char *buf = NULL;
 | 
|---|
| 2148 |         uint16 attribute;
 | 
|---|
| 2149 |         struct cli_state *targetcli;
 | 
|---|
| 2150 |         char *targetname = NULL;
 | 
|---|
| 2151 | 
 | 
|---|
| 2152 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2153 |                 d_printf("wdel 0x<attrib> <wcard>\n");
 | 
|---|
| 2154 |                 return 1;
 | 
|---|
| 2155 |         }
 | 
|---|
| 2156 | 
 | 
|---|
| 2157 |         attribute = (uint16)strtol(buf, (char **)NULL, 16);
 | 
|---|
| 2158 | 
 | 
|---|
| 2159 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2160 |                 d_printf("wdel 0x<attrib> <wcard>\n");
 | 
|---|
| 2161 |                 return 1;
 | 
|---|
| 2162 |         }
 | 
|---|
| 2163 | 
 | 
|---|
| 2164 |         mask = talloc_asprintf(ctx, "%s%s",
 | 
|---|
| 2165 |                         client_get_cur_dir(),
 | 
|---|
| 2166 |                         buf);
 | 
|---|
| 2167 |         if (!mask) {
 | 
|---|
| 2168 |                 return 1;
 | 
|---|
| 2169 |         }
 | 
|---|
| 2170 | 
 | 
|---|
| 2171 |         if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
 | 
|---|
| 2172 |                 d_printf("cmd_wdel %s: %s\n", mask, cli_errstr(cli));
 | 
|---|
| 2173 |                 return 1;
 | 
|---|
| 2174 |         }
 | 
|---|
| 2175 | 
 | 
|---|
| 2176 |         if (!NT_STATUS_IS_OK(cli_unlink(targetcli, targetname, attribute))) {
 | 
|---|
| 2177 |                 d_printf("%s deleting remote files %s\n",cli_errstr(targetcli),targetname);
 | 
|---|
| 2178 |         }
 | 
|---|
| 2179 |         return 0;
 | 
|---|
| 2180 | }
 | 
|---|
| 2181 | 
 | 
|---|
| 2182 | /****************************************************************************
 | 
|---|
| 2183 | ****************************************************************************/
 | 
|---|
| 2184 | 
 | 
|---|
| 2185 | static int cmd_open(void)
 | 
|---|
| 2186 | {
 | 
|---|
| 2187 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2188 |         char *mask = NULL;
 | 
|---|
| 2189 |         char *buf = NULL;
 | 
|---|
| 2190 |         char *targetname = NULL;
 | 
|---|
| 2191 |         struct cli_state *targetcli;
 | 
|---|
| 2192 |         uint16_t fnum = (uint16_t)-1;
 | 
|---|
| 2193 | 
 | 
|---|
| 2194 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2195 |                 d_printf("open <filename>\n");
 | 
|---|
| 2196 |                 return 1;
 | 
|---|
| 2197 |         }
 | 
|---|
| 2198 |         mask = talloc_asprintf(ctx,
 | 
|---|
| 2199 |                         "%s%s",
 | 
|---|
| 2200 |                         client_get_cur_dir(),
 | 
|---|
| 2201 |                         buf);
 | 
|---|
| 2202 |         if (!mask) {
 | 
|---|
| 2203 |                 return 1;
 | 
|---|
| 2204 |         }
 | 
|---|
| 2205 | 
 | 
|---|
| 2206 |         if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
 | 
|---|
| 2207 |                 d_printf("open %s: %s\n", mask, cli_errstr(cli));
 | 
|---|
| 2208 |                 return 1;
 | 
|---|
| 2209 |         }
 | 
|---|
| 2210 | 
 | 
|---|
| 2211 |         if (!NT_STATUS_IS_OK(cli_ntcreate(targetcli, targetname, 0,
 | 
|---|
| 2212 |                         FILE_READ_DATA|FILE_WRITE_DATA, 0,
 | 
|---|
| 2213 |                         FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
 | 
|---|
| 2214 |                 if (NT_STATUS_IS_OK(cli_ntcreate(targetcli, targetname, 0,
 | 
|---|
| 2215 |                                 FILE_READ_DATA, 0,
 | 
|---|
| 2216 |                                 FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN, 0x0, 0x0, &fnum))) {
 | 
|---|
| 2217 |                         d_printf("open file %s: for read/write fnum %d\n", targetname, fnum);
 | 
|---|
| 2218 |                 } else {
 | 
|---|
| 2219 |                         d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
 | 
|---|
| 2220 |                 }
 | 
|---|
| 2221 |         } else {
 | 
|---|
| 2222 |                 d_printf("open file %s: for read/write fnum %d\n", targetname, fnum);
 | 
|---|
| 2223 |         }
 | 
|---|
| 2224 |         return 0;
 | 
|---|
| 2225 | }
 | 
|---|
| 2226 | 
 | 
|---|
| 2227 | static int cmd_posix_encrypt(void)
 | 
|---|
| 2228 | {
 | 
|---|
| 2229 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2230 |         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
 | 
|---|
| 2231 | 
 | 
|---|
| 2232 |         if (cli->use_kerberos) {
 | 
|---|
| 2233 |                 status = cli_gss_smb_encryption_start(cli);
 | 
|---|
| 2234 |         } else {
 | 
|---|
| 2235 |                 char *domain = NULL;
 | 
|---|
| 2236 |                 char *user = NULL;
 | 
|---|
| 2237 |                 char *password = NULL;
 | 
|---|
| 2238 | 
 | 
|---|
| 2239 |                 if (!next_token_talloc(ctx, &cmd_ptr,&domain,NULL)) {
 | 
|---|
| 2240 |                         d_printf("posix_encrypt domain user password\n");
 | 
|---|
| 2241 |                         return 1;
 | 
|---|
| 2242 |                 }
 | 
|---|
| 2243 | 
 | 
|---|
| 2244 |                 if (!next_token_talloc(ctx, &cmd_ptr,&user,NULL)) {
 | 
|---|
| 2245 |                         d_printf("posix_encrypt domain user password\n");
 | 
|---|
| 2246 |                         return 1;
 | 
|---|
| 2247 |                 }
 | 
|---|
| 2248 | 
 | 
|---|
| 2249 |                 if (!next_token_talloc(ctx, &cmd_ptr,&password,NULL)) {
 | 
|---|
| 2250 |                         d_printf("posix_encrypt domain user password\n");
 | 
|---|
| 2251 |                         return 1;
 | 
|---|
| 2252 |                 }
 | 
|---|
| 2253 | 
 | 
|---|
| 2254 |                 status = cli_raw_ntlm_smb_encryption_start(cli,
 | 
|---|
| 2255 |                                                         user,
 | 
|---|
| 2256 |                                                         password,
 | 
|---|
| 2257 |                                                         domain);
 | 
|---|
| 2258 |         }
 | 
|---|
| 2259 | 
 | 
|---|
| 2260 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 2261 |                 d_printf("posix_encrypt failed with error %s\n", nt_errstr(status));
 | 
|---|
| 2262 |         } else {
 | 
|---|
| 2263 |                 d_printf("encryption on\n");
 | 
|---|
| 2264 |                 smb_encrypt = true;
 | 
|---|
| 2265 |         }
 | 
|---|
| 2266 | 
 | 
|---|
| 2267 |         return 0;
 | 
|---|
| 2268 | }
 | 
|---|
| 2269 | 
 | 
|---|
| 2270 | /****************************************************************************
 | 
|---|
| 2271 | ****************************************************************************/
 | 
|---|
| 2272 | 
 | 
|---|
| 2273 | static int cmd_posix_open(void)
 | 
|---|
| 2274 | {
 | 
|---|
| 2275 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2276 |         char *mask = NULL;
 | 
|---|
| 2277 |         char *buf = NULL;
 | 
|---|
| 2278 |         char *targetname = NULL;
 | 
|---|
| 2279 |         struct cli_state *targetcli;
 | 
|---|
| 2280 |         mode_t mode;
 | 
|---|
| 2281 |         uint16_t fnum;
 | 
|---|
| 2282 | 
 | 
|---|
| 2283 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2284 |                 d_printf("posix_open <filename> 0<mode>\n");
 | 
|---|
| 2285 |                 return 1;
 | 
|---|
| 2286 |         }
 | 
|---|
| 2287 |         mask = talloc_asprintf(ctx,
 | 
|---|
| 2288 |                         "%s%s",
 | 
|---|
| 2289 |                         client_get_cur_dir(),
 | 
|---|
| 2290 |                         buf);
 | 
|---|
| 2291 |         if (!mask) {
 | 
|---|
| 2292 |                 return 1;
 | 
|---|
| 2293 |         }
 | 
|---|
| 2294 | 
 | 
|---|
| 2295 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2296 |                 d_printf("posix_open <filename> 0<mode>\n");
 | 
|---|
| 2297 |                 return 1;
 | 
|---|
| 2298 |         }
 | 
|---|
| 2299 |         mode = (mode_t)strtol(buf, (char **)NULL, 8);
 | 
|---|
| 2300 | 
 | 
|---|
| 2301 |         if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
 | 
|---|
| 2302 |                 d_printf("posix_open %s: %s\n", mask, cli_errstr(cli));
 | 
|---|
| 2303 |                 return 1;
 | 
|---|
| 2304 |         }
 | 
|---|
| 2305 | 
 | 
|---|
| 2306 |         if (!NT_STATUS_IS_OK(cli_posix_open(targetcli, targetname, O_CREAT|O_RDWR, mode, &fnum))) {
 | 
|---|
| 2307 |                 if (!NT_STATUS_IS_OK(cli_posix_open(targetcli, targetname, O_CREAT|O_RDONLY, mode, &fnum))) {
 | 
|---|
| 2308 |                         d_printf("posix_open file %s: for read/write fnum %d\n", targetname, fnum);
 | 
|---|
| 2309 |                 } else {
 | 
|---|
| 2310 |                         d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
 | 
|---|
| 2311 |                 }
 | 
|---|
| 2312 |         } else {
 | 
|---|
| 2313 |                 d_printf("posix_open file %s: for read/write fnum %d\n", targetname, fnum);
 | 
|---|
| 2314 |         }
 | 
|---|
| 2315 | 
 | 
|---|
| 2316 |         return 0;
 | 
|---|
| 2317 | }
 | 
|---|
| 2318 | 
 | 
|---|
| 2319 | static int cmd_posix_mkdir(void)
 | 
|---|
| 2320 | {
 | 
|---|
| 2321 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2322 |         char *mask = NULL;
 | 
|---|
| 2323 |         char *buf = NULL;
 | 
|---|
| 2324 |         char *targetname = NULL;
 | 
|---|
| 2325 |         struct cli_state *targetcli;
 | 
|---|
| 2326 |         mode_t mode;
 | 
|---|
| 2327 | 
 | 
|---|
| 2328 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2329 |                 d_printf("posix_mkdir <filename> 0<mode>\n");
 | 
|---|
| 2330 |                 return 1;
 | 
|---|
| 2331 |         }
 | 
|---|
| 2332 |         mask = talloc_asprintf(ctx,
 | 
|---|
| 2333 |                         "%s%s",
 | 
|---|
| 2334 |                         client_get_cur_dir(),
 | 
|---|
| 2335 |                         buf);
 | 
|---|
| 2336 |         if (!mask) {
 | 
|---|
| 2337 |                 return 1;
 | 
|---|
| 2338 |         }
 | 
|---|
| 2339 | 
 | 
|---|
| 2340 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2341 |                 d_printf("posix_mkdir <filename> 0<mode>\n");
 | 
|---|
| 2342 |                 return 1;
 | 
|---|
| 2343 |         }
 | 
|---|
| 2344 |         mode = (mode_t)strtol(buf, (char **)NULL, 8);
 | 
|---|
| 2345 | 
 | 
|---|
| 2346 |         if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
 | 
|---|
| 2347 |                 d_printf("posix_mkdir %s: %s\n", mask, cli_errstr(cli));
 | 
|---|
| 2348 |                 return 1;
 | 
|---|
| 2349 |         }
 | 
|---|
| 2350 | 
 | 
|---|
| 2351 |         if (!NT_STATUS_IS_OK(cli_posix_mkdir(targetcli, targetname, mode))) {
 | 
|---|
| 2352 |                 d_printf("Failed to open file %s. %s\n", targetname, cli_errstr(cli));
 | 
|---|
| 2353 |         } else {
 | 
|---|
| 2354 |                 d_printf("posix_mkdir created directory %s\n", targetname);
 | 
|---|
| 2355 |         }
 | 
|---|
| 2356 |         return 0;
 | 
|---|
| 2357 | }
 | 
|---|
| 2358 | 
 | 
|---|
| 2359 | static int cmd_posix_unlink(void)
 | 
|---|
| 2360 | {
 | 
|---|
| 2361 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2362 |         char *mask = NULL;
 | 
|---|
| 2363 |         char *buf = NULL;
 | 
|---|
| 2364 |         char *targetname = NULL;
 | 
|---|
| 2365 |         struct cli_state *targetcli;
 | 
|---|
| 2366 | 
 | 
|---|
| 2367 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2368 |                 d_printf("posix_unlink <filename>\n");
 | 
|---|
| 2369 |                 return 1;
 | 
|---|
| 2370 |         }
 | 
|---|
| 2371 |         mask = talloc_asprintf(ctx,
 | 
|---|
| 2372 |                         "%s%s",
 | 
|---|
| 2373 |                         client_get_cur_dir(),
 | 
|---|
| 2374 |                         buf);
 | 
|---|
| 2375 |         if (!mask) {
 | 
|---|
| 2376 |                 return 1;
 | 
|---|
| 2377 |         }
 | 
|---|
| 2378 | 
 | 
|---|
| 2379 |         if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
 | 
|---|
| 2380 |                 d_printf("posix_unlink %s: %s\n", mask, cli_errstr(cli));
 | 
|---|
| 2381 |                 return 1;
 | 
|---|
| 2382 |         }
 | 
|---|
| 2383 | 
 | 
|---|
| 2384 |         if (!NT_STATUS_IS_OK(cli_posix_unlink(targetcli, targetname))) {
 | 
|---|
| 2385 |                 d_printf("Failed to unlink file %s. %s\n", targetname, cli_errstr(cli));
 | 
|---|
| 2386 |         } else {
 | 
|---|
| 2387 |                 d_printf("posix_unlink deleted file %s\n", targetname);
 | 
|---|
| 2388 |         }
 | 
|---|
| 2389 | 
 | 
|---|
| 2390 |         return 0;
 | 
|---|
| 2391 | }
 | 
|---|
| 2392 | 
 | 
|---|
| 2393 | static int cmd_posix_rmdir(void)
 | 
|---|
| 2394 | {
 | 
|---|
| 2395 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2396 |         char *mask = NULL;
 | 
|---|
| 2397 |         char *buf = NULL;
 | 
|---|
| 2398 |         char *targetname = NULL;
 | 
|---|
| 2399 |         struct cli_state *targetcli;
 | 
|---|
| 2400 | 
 | 
|---|
| 2401 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2402 |                 d_printf("posix_rmdir <filename>\n");
 | 
|---|
| 2403 |                 return 1;
 | 
|---|
| 2404 |         }
 | 
|---|
| 2405 |         mask = talloc_asprintf(ctx,
 | 
|---|
| 2406 |                         "%s%s",
 | 
|---|
| 2407 |                         client_get_cur_dir(),
 | 
|---|
| 2408 |                         buf);
 | 
|---|
| 2409 |         if (!mask) {
 | 
|---|
| 2410 |                 return 1;
 | 
|---|
| 2411 |         }
 | 
|---|
| 2412 | 
 | 
|---|
| 2413 |         if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
 | 
|---|
| 2414 |                 d_printf("posix_rmdir %s: %s\n", mask, cli_errstr(cli));
 | 
|---|
| 2415 |                 return 1;
 | 
|---|
| 2416 |         }
 | 
|---|
| 2417 | 
 | 
|---|
| 2418 |         if (!NT_STATUS_IS_OK(cli_posix_rmdir(targetcli, targetname))) {
 | 
|---|
| 2419 |                 d_printf("Failed to unlink directory %s. %s\n", targetname, cli_errstr(cli));
 | 
|---|
| 2420 |         } else {
 | 
|---|
| 2421 |                 d_printf("posix_rmdir deleted directory %s\n", targetname);
 | 
|---|
| 2422 |         }
 | 
|---|
| 2423 | 
 | 
|---|
| 2424 |         return 0;
 | 
|---|
| 2425 | }
 | 
|---|
| 2426 | 
 | 
|---|
| 2427 | static int cmd_close(void)
 | 
|---|
| 2428 | {
 | 
|---|
| 2429 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2430 |         char *buf = NULL;
 | 
|---|
| 2431 |         int fnum;
 | 
|---|
| 2432 | 
 | 
|---|
| 2433 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2434 |                 d_printf("close <fnum>\n");
 | 
|---|
| 2435 |                 return 1;
 | 
|---|
| 2436 |         }
 | 
|---|
| 2437 | 
 | 
|---|
| 2438 |         fnum = atoi(buf);
 | 
|---|
| 2439 |         /* We really should use the targetcli here.... */
 | 
|---|
| 2440 |         if (!NT_STATUS_IS_OK(cli_close(cli, fnum))) {
 | 
|---|
| 2441 |                 d_printf("close %d: %s\n", fnum, cli_errstr(cli));
 | 
|---|
| 2442 |                 return 1;
 | 
|---|
| 2443 |         }
 | 
|---|
| 2444 |         return 0;
 | 
|---|
| 2445 | }
 | 
|---|
| 2446 | 
 | 
|---|
| 2447 | static int cmd_posix(void)
 | 
|---|
| 2448 | {
 | 
|---|
| 2449 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2450 |         uint16 major, minor;
 | 
|---|
| 2451 |         uint32 caplow, caphigh;
 | 
|---|
| 2452 |         char *caps;
 | 
|---|
| 2453 |         NTSTATUS status;
 | 
|---|
| 2454 | 
 | 
|---|
| 2455 |         if (!SERVER_HAS_UNIX_CIFS(cli)) {
 | 
|---|
| 2456 |                 d_printf("Server doesn't support UNIX CIFS extensions.\n");
 | 
|---|
| 2457 |                 return 1;
 | 
|---|
| 2458 |         }
 | 
|---|
| 2459 | 
 | 
|---|
| 2460 |         status = cli_unix_extensions_version(cli, &major, &minor, &caplow,
 | 
|---|
| 2461 |                                              &caphigh);
 | 
|---|
| 2462 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 2463 |                 d_printf("Can't get UNIX CIFS extensions version from "
 | 
|---|
| 2464 |                          "server: %s\n", nt_errstr(status));
 | 
|---|
| 2465 |                 return 1;
 | 
|---|
| 2466 |         }
 | 
|---|
| 2467 | 
 | 
|---|
| 2468 |         d_printf("Server supports CIFS extensions %u.%u\n", (unsigned int)major, (unsigned int)minor);
 | 
|---|
| 2469 | 
 | 
|---|
| 2470 |         caps = talloc_strdup(ctx, "");
 | 
|---|
| 2471 |         if (!caps) {
 | 
|---|
| 2472 |                 return 1;
 | 
|---|
| 2473 |         }
 | 
|---|
| 2474 |         if (caplow & CIFS_UNIX_FCNTL_LOCKS_CAP) {
 | 
|---|
| 2475 |                 caps = talloc_asprintf_append(caps, "locks ");
 | 
|---|
| 2476 |                 if (!caps) {
 | 
|---|
| 2477 |                         return 1;
 | 
|---|
| 2478 |                 }
 | 
|---|
| 2479 |         }
 | 
|---|
| 2480 |         if (caplow & CIFS_UNIX_POSIX_ACLS_CAP) {
 | 
|---|
| 2481 |                 caps = talloc_asprintf_append(caps, "acls ");
 | 
|---|
| 2482 |                 if (!caps) {
 | 
|---|
| 2483 |                         return 1;
 | 
|---|
| 2484 |                 }
 | 
|---|
| 2485 |         }
 | 
|---|
| 2486 |         if (caplow & CIFS_UNIX_XATTTR_CAP) {
 | 
|---|
| 2487 |                 caps = talloc_asprintf_append(caps, "eas ");
 | 
|---|
| 2488 |                 if (!caps) {
 | 
|---|
| 2489 |                         return 1;
 | 
|---|
| 2490 |                 }
 | 
|---|
| 2491 |         }
 | 
|---|
| 2492 |         if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
 | 
|---|
| 2493 |                 caps = talloc_asprintf_append(caps, "pathnames ");
 | 
|---|
| 2494 |                 if (!caps) {
 | 
|---|
| 2495 |                         return 1;
 | 
|---|
| 2496 |                 }
 | 
|---|
| 2497 |         }
 | 
|---|
| 2498 |         if (caplow & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP) {
 | 
|---|
| 2499 |                 caps = talloc_asprintf_append(caps, "posix_path_operations ");
 | 
|---|
| 2500 |                 if (!caps) {
 | 
|---|
| 2501 |                         return 1;
 | 
|---|
| 2502 |                 }
 | 
|---|
| 2503 |         }
 | 
|---|
| 2504 |         if (caplow & CIFS_UNIX_LARGE_READ_CAP) {
 | 
|---|
| 2505 |                 caps = talloc_asprintf_append(caps, "large_read ");
 | 
|---|
| 2506 |                 if (!caps) {
 | 
|---|
| 2507 |                         return 1;
 | 
|---|
| 2508 |                 }
 | 
|---|
| 2509 |         }
 | 
|---|
| 2510 |         if (caplow & CIFS_UNIX_LARGE_WRITE_CAP) {
 | 
|---|
| 2511 |                 caps = talloc_asprintf_append(caps, "large_write ");
 | 
|---|
| 2512 |                 if (!caps) {
 | 
|---|
| 2513 |                         return 1;
 | 
|---|
| 2514 |                 }
 | 
|---|
| 2515 |         }
 | 
|---|
| 2516 |         if (caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP) {
 | 
|---|
| 2517 |                 caps = talloc_asprintf_append(caps, "posix_encrypt ");
 | 
|---|
| 2518 |                 if (!caps) {
 | 
|---|
| 2519 |                         return 1;
 | 
|---|
| 2520 |                 }
 | 
|---|
| 2521 |         }
 | 
|---|
| 2522 |         if (caplow & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP) {
 | 
|---|
| 2523 |                 caps = talloc_asprintf_append(caps, "mandatory_posix_encrypt ");
 | 
|---|
| 2524 |                 if (!caps) {
 | 
|---|
| 2525 |                         return 1;
 | 
|---|
| 2526 |                 }
 | 
|---|
| 2527 |         }
 | 
|---|
| 2528 | 
 | 
|---|
| 2529 |         if (*caps && caps[strlen(caps)-1] == ' ') {
 | 
|---|
| 2530 |                 caps[strlen(caps)-1] = '\0';
 | 
|---|
| 2531 |         }
 | 
|---|
| 2532 | 
 | 
|---|
| 2533 |         d_printf("Server supports CIFS capabilities %s\n", caps);
 | 
|---|
| 2534 | 
 | 
|---|
| 2535 |         if (!cli_set_unix_extensions_capabilities(cli, major, minor, caplow, caphigh)) {
 | 
|---|
| 2536 |                 d_printf("Can't set UNIX CIFS extensions capabilities. %s.\n", cli_errstr(cli));
 | 
|---|
| 2537 |                 return 1;
 | 
|---|
| 2538 |         }
 | 
|---|
| 2539 | 
 | 
|---|
| 2540 |         if (caplow & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
 | 
|---|
| 2541 |                 CLI_DIRSEP_CHAR = '/';
 | 
|---|
| 2542 |                 *CLI_DIRSEP_STR = '/';
 | 
|---|
| 2543 |                 client_set_cur_dir(CLI_DIRSEP_STR);
 | 
|---|
| 2544 |         }
 | 
|---|
| 2545 | 
 | 
|---|
| 2546 |         return 0;
 | 
|---|
| 2547 | }
 | 
|---|
| 2548 | 
 | 
|---|
| 2549 | static int cmd_lock(void)
 | 
|---|
| 2550 | {
 | 
|---|
| 2551 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2552 |         char *buf = NULL;
 | 
|---|
| 2553 |         uint64_t start, len;
 | 
|---|
| 2554 |         enum brl_type lock_type;
 | 
|---|
| 2555 |         int fnum;
 | 
|---|
| 2556 | 
 | 
|---|
| 2557 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2558 |                 d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
 | 
|---|
| 2559 |                 return 1;
 | 
|---|
| 2560 |         }
 | 
|---|
| 2561 |         fnum = atoi(buf);
 | 
|---|
| 2562 | 
 | 
|---|
| 2563 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2564 |                 d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
 | 
|---|
| 2565 |                 return 1;
 | 
|---|
| 2566 |         }
 | 
|---|
| 2567 | 
 | 
|---|
| 2568 |         if (*buf == 'r' || *buf == 'R') {
 | 
|---|
| 2569 |                 lock_type = READ_LOCK;
 | 
|---|
| 2570 |         } else if (*buf == 'w' || *buf == 'W') {
 | 
|---|
| 2571 |                 lock_type = WRITE_LOCK;
 | 
|---|
| 2572 |         } else {
 | 
|---|
| 2573 |                 d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
 | 
|---|
| 2574 |                 return 1;
 | 
|---|
| 2575 |         }
 | 
|---|
| 2576 | 
 | 
|---|
| 2577 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2578 |                 d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
 | 
|---|
| 2579 |                 return 1;
 | 
|---|
| 2580 |         }
 | 
|---|
| 2581 | 
 | 
|---|
| 2582 |         start = (uint64_t)strtol(buf, (char **)NULL, 16);
 | 
|---|
| 2583 | 
 | 
|---|
| 2584 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2585 |                 d_printf("lock <fnum> [r|w] <hex-start> <hex-len>\n");
 | 
|---|
| 2586 |                 return 1;
 | 
|---|
| 2587 |         }
 | 
|---|
| 2588 | 
 | 
|---|
| 2589 |         len = (uint64_t)strtol(buf, (char **)NULL, 16);
 | 
|---|
| 2590 | 
 | 
|---|
| 2591 |         if (!NT_STATUS_IS_OK(cli_posix_lock(cli, fnum, start, len, true, lock_type))) {
 | 
|---|
| 2592 |                 d_printf("lock failed %d: %s\n", fnum, cli_errstr(cli));
 | 
|---|
| 2593 |         }
 | 
|---|
| 2594 | 
 | 
|---|
| 2595 |         return 0;
 | 
|---|
| 2596 | }
 | 
|---|
| 2597 | 
 | 
|---|
| 2598 | static int cmd_unlock(void)
 | 
|---|
| 2599 | {
 | 
|---|
| 2600 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2601 |         char *buf = NULL;
 | 
|---|
| 2602 |         uint64_t start, len;
 | 
|---|
| 2603 |         int fnum;
 | 
|---|
| 2604 | 
 | 
|---|
| 2605 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2606 |                 d_printf("unlock <fnum> <hex-start> <hex-len>\n");
 | 
|---|
| 2607 |                 return 1;
 | 
|---|
| 2608 |         }
 | 
|---|
| 2609 |         fnum = atoi(buf);
 | 
|---|
| 2610 | 
 | 
|---|
| 2611 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2612 |                 d_printf("unlock <fnum> <hex-start> <hex-len>\n");
 | 
|---|
| 2613 |                 return 1;
 | 
|---|
| 2614 |         }
 | 
|---|
| 2615 | 
 | 
|---|
| 2616 |         start = (uint64_t)strtol(buf, (char **)NULL, 16);
 | 
|---|
| 2617 | 
 | 
|---|
| 2618 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2619 |                 d_printf("unlock <fnum> <hex-start> <hex-len>\n");
 | 
|---|
| 2620 |                 return 1;
 | 
|---|
| 2621 |         }
 | 
|---|
| 2622 | 
 | 
|---|
| 2623 |         len = (uint64_t)strtol(buf, (char **)NULL, 16);
 | 
|---|
| 2624 | 
 | 
|---|
| 2625 |         if (!NT_STATUS_IS_OK(cli_posix_unlock(cli, fnum, start, len))) {
 | 
|---|
| 2626 |                 d_printf("unlock failed %d: %s\n", fnum, cli_errstr(cli));
 | 
|---|
| 2627 |         }
 | 
|---|
| 2628 | 
 | 
|---|
| 2629 |         return 0;
 | 
|---|
| 2630 | }
 | 
|---|
| 2631 | 
 | 
|---|
| 2632 | 
 | 
|---|
| 2633 | /****************************************************************************
 | 
|---|
| 2634 |  Remove a directory.
 | 
|---|
| 2635 | ****************************************************************************/
 | 
|---|
| 2636 | 
 | 
|---|
| 2637 | static int cmd_rmdir(void)
 | 
|---|
| 2638 | {
 | 
|---|
| 2639 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2640 |         char *mask = NULL;
 | 
|---|
| 2641 |         char *buf = NULL;
 | 
|---|
| 2642 |         char *targetname = NULL;
 | 
|---|
| 2643 |         struct cli_state *targetcli;
 | 
|---|
| 2644 | 
 | 
|---|
| 2645 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2646 |                 d_printf("rmdir <dirname>\n");
 | 
|---|
| 2647 |                 return 1;
 | 
|---|
| 2648 |         }
 | 
|---|
| 2649 |         mask = talloc_asprintf(ctx,
 | 
|---|
| 2650 |                         "%s%s",
 | 
|---|
| 2651 |                         client_get_cur_dir(),
 | 
|---|
| 2652 |                         buf);
 | 
|---|
| 2653 |         if (!mask) {
 | 
|---|
| 2654 |                 return 1;
 | 
|---|
| 2655 |         }
 | 
|---|
| 2656 | 
 | 
|---|
| 2657 |         if (!cli_resolve_path(ctx, "", auth_info, cli, mask, &targetcli, &targetname)) {
 | 
|---|
| 2658 |                 d_printf("rmdir %s: %s\n", mask, cli_errstr(cli));
 | 
|---|
| 2659 |                 return 1;
 | 
|---|
| 2660 |         }
 | 
|---|
| 2661 | 
 | 
|---|
| 2662 |         if (!NT_STATUS_IS_OK(cli_rmdir(targetcli, targetname))) {
 | 
|---|
| 2663 |                 d_printf("%s removing remote directory file %s\n",
 | 
|---|
| 2664 |                          cli_errstr(targetcli),mask);
 | 
|---|
| 2665 |         }
 | 
|---|
| 2666 | 
 | 
|---|
| 2667 |         return 0;
 | 
|---|
| 2668 | }
 | 
|---|
| 2669 | 
 | 
|---|
| 2670 | /****************************************************************************
 | 
|---|
| 2671 |  UNIX hardlink.
 | 
|---|
| 2672 | ****************************************************************************/
 | 
|---|
| 2673 | 
 | 
|---|
| 2674 | static int cmd_link(void)
 | 
|---|
| 2675 | {
 | 
|---|
| 2676 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2677 |         char *oldname = NULL;
 | 
|---|
| 2678 |         char *newname = NULL;
 | 
|---|
| 2679 |         char *buf = NULL;
 | 
|---|
| 2680 |         char *buf2 = NULL;
 | 
|---|
| 2681 |         char *targetname = NULL;
 | 
|---|
| 2682 |         struct cli_state *targetcli;
 | 
|---|
| 2683 | 
 | 
|---|
| 2684 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
 | 
|---|
| 2685 |             !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
 | 
|---|
| 2686 |                 d_printf("link <oldname> <newname>\n");
 | 
|---|
| 2687 |                 return 1;
 | 
|---|
| 2688 |         }
 | 
|---|
| 2689 |         oldname = talloc_asprintf(ctx,
 | 
|---|
| 2690 |                         "%s%s",
 | 
|---|
| 2691 |                         client_get_cur_dir(),
 | 
|---|
| 2692 |                         buf);
 | 
|---|
| 2693 |         if (!oldname) {
 | 
|---|
| 2694 |                 return 1;
 | 
|---|
| 2695 |         }
 | 
|---|
| 2696 |         newname = talloc_asprintf(ctx,
 | 
|---|
| 2697 |                         "%s%s",
 | 
|---|
| 2698 |                         client_get_cur_dir(),
 | 
|---|
| 2699 |                         buf2);
 | 
|---|
| 2700 |         if (!newname) {
 | 
|---|
| 2701 |                 return 1;
 | 
|---|
| 2702 |         }
 | 
|---|
| 2703 | 
 | 
|---|
| 2704 |         if (!cli_resolve_path(ctx, "", auth_info, cli, oldname, &targetcli, &targetname)) {
 | 
|---|
| 2705 |                 d_printf("link %s: %s\n", oldname, cli_errstr(cli));
 | 
|---|
| 2706 |                 return 1;
 | 
|---|
| 2707 |         }
 | 
|---|
| 2708 | 
 | 
|---|
| 2709 |         if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
 | 
|---|
| 2710 |                 d_printf("Server doesn't support UNIX CIFS calls.\n");
 | 
|---|
| 2711 |                 return 1;
 | 
|---|
| 2712 |         }
 | 
|---|
| 2713 | 
 | 
|---|
| 2714 |         if (!NT_STATUS_IS_OK(cli_posix_hardlink(targetcli, targetname, newname))) {
 | 
|---|
| 2715 |                 d_printf("%s linking files (%s -> %s)\n", cli_errstr(targetcli), newname, oldname);
 | 
|---|
| 2716 |                 return 1;
 | 
|---|
| 2717 |         }
 | 
|---|
| 2718 |         return 0;
 | 
|---|
| 2719 | }
 | 
|---|
| 2720 | 
 | 
|---|
| 2721 | /****************************************************************************
 | 
|---|
| 2722 |  UNIX readlink.
 | 
|---|
| 2723 | ****************************************************************************/
 | 
|---|
| 2724 | 
 | 
|---|
| 2725 | static int cmd_readlink(void)
 | 
|---|
| 2726 | {
 | 
|---|
| 2727 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2728 |         char *name= NULL;
 | 
|---|
| 2729 |         char *buf = NULL;
 | 
|---|
| 2730 |         char *targetname = NULL;
 | 
|---|
| 2731 |         char linkname[PATH_MAX+1];
 | 
|---|
| 2732 |         struct cli_state *targetcli;
 | 
|---|
| 2733 | 
 | 
|---|
| 2734 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 2735 |                 d_printf("readlink <name>\n");
 | 
|---|
| 2736 |                 return 1;
 | 
|---|
| 2737 |         }
 | 
|---|
| 2738 |         name = talloc_asprintf(ctx,
 | 
|---|
| 2739 |                         "%s%s",
 | 
|---|
| 2740 |                         client_get_cur_dir(),
 | 
|---|
| 2741 |                         buf);
 | 
|---|
| 2742 |         if (!name) {
 | 
|---|
| 2743 |                 return 1;
 | 
|---|
| 2744 |         }
 | 
|---|
| 2745 | 
 | 
|---|
| 2746 |         if (!cli_resolve_path(ctx, "", auth_info, cli, name, &targetcli, &targetname)) {
 | 
|---|
| 2747 |                 d_printf("readlink %s: %s\n", name, cli_errstr(cli));
 | 
|---|
| 2748 |                 return 1;
 | 
|---|
| 2749 |         }
 | 
|---|
| 2750 | 
 | 
|---|
| 2751 |         if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
 | 
|---|
| 2752 |                 d_printf("Server doesn't support UNIX CIFS calls.\n");
 | 
|---|
| 2753 |                 return 1;
 | 
|---|
| 2754 |         }
 | 
|---|
| 2755 | 
 | 
|---|
| 2756 |         if (!NT_STATUS_IS_OK(cli_posix_readlink(targetcli, name,
 | 
|---|
| 2757 |                         linkname, PATH_MAX+1))) {
 | 
|---|
| 2758 |                 d_printf("%s readlink on file %s\n",
 | 
|---|
| 2759 |                         cli_errstr(targetcli), name);
 | 
|---|
| 2760 |                 return 1;
 | 
|---|
| 2761 |         }
 | 
|---|
| 2762 | 
 | 
|---|
| 2763 |         d_printf("%s -> %s\n", name, linkname);
 | 
|---|
| 2764 | 
 | 
|---|
| 2765 |         return 0;
 | 
|---|
| 2766 | }
 | 
|---|
| 2767 | 
 | 
|---|
| 2768 | 
 | 
|---|
| 2769 | /****************************************************************************
 | 
|---|
| 2770 |  UNIX symlink.
 | 
|---|
| 2771 | ****************************************************************************/
 | 
|---|
| 2772 | 
 | 
|---|
| 2773 | static int cmd_symlink(void)
 | 
|---|
| 2774 | {
 | 
|---|
| 2775 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2776 |         char *oldname = NULL;
 | 
|---|
| 2777 |         char *newname = NULL;
 | 
|---|
| 2778 |         char *buf = NULL;
 | 
|---|
| 2779 |         char *buf2 = NULL;
 | 
|---|
| 2780 |         char *targetname = NULL;
 | 
|---|
| 2781 |         struct cli_state *targetcli;
 | 
|---|
| 2782 | 
 | 
|---|
| 2783 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
 | 
|---|
| 2784 |             !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
 | 
|---|
| 2785 |                 d_printf("symlink <oldname> <newname>\n");
 | 
|---|
| 2786 |                 return 1;
 | 
|---|
| 2787 |         }
 | 
|---|
| 2788 |         oldname = talloc_asprintf(ctx,
 | 
|---|
| 2789 |                         "%s%s",
 | 
|---|
| 2790 |                         client_get_cur_dir(),
 | 
|---|
| 2791 |                         buf);
 | 
|---|
| 2792 |         if (!oldname) {
 | 
|---|
| 2793 |                 return 1;
 | 
|---|
| 2794 |         }
 | 
|---|
| 2795 |         newname = talloc_asprintf(ctx,
 | 
|---|
| 2796 |                         "%s%s",
 | 
|---|
| 2797 |                         client_get_cur_dir(),
 | 
|---|
| 2798 |                         buf2);
 | 
|---|
| 2799 |         if (!newname) {
 | 
|---|
| 2800 |                 return 1;
 | 
|---|
| 2801 |         }
 | 
|---|
| 2802 | 
 | 
|---|
| 2803 |         if (!cli_resolve_path(ctx, "", auth_info, cli, oldname, &targetcli, &targetname)) {
 | 
|---|
| 2804 |                 d_printf("link %s: %s\n", oldname, cli_errstr(cli));
 | 
|---|
| 2805 |                 return 1;
 | 
|---|
| 2806 |         }
 | 
|---|
| 2807 | 
 | 
|---|
| 2808 |         if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
 | 
|---|
| 2809 |                 d_printf("Server doesn't support UNIX CIFS calls.\n");
 | 
|---|
| 2810 |                 return 1;
 | 
|---|
| 2811 |         }
 | 
|---|
| 2812 | 
 | 
|---|
| 2813 |         if (!NT_STATUS_IS_OK(cli_posix_symlink(targetcli, targetname, newname))) {
 | 
|---|
| 2814 |                 d_printf("%s symlinking files (%s -> %s)\n",
 | 
|---|
| 2815 |                         cli_errstr(targetcli), newname, targetname);
 | 
|---|
| 2816 |                 return 1;
 | 
|---|
| 2817 |         }
 | 
|---|
| 2818 | 
 | 
|---|
| 2819 |         return 0;
 | 
|---|
| 2820 | }
 | 
|---|
| 2821 | 
 | 
|---|
| 2822 | /****************************************************************************
 | 
|---|
| 2823 |  UNIX chmod.
 | 
|---|
| 2824 | ****************************************************************************/
 | 
|---|
| 2825 | 
 | 
|---|
| 2826 | static int cmd_chmod(void)
 | 
|---|
| 2827 | {
 | 
|---|
| 2828 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2829 |         char *src = NULL;
 | 
|---|
| 2830 |         char *buf = NULL;
 | 
|---|
| 2831 |         char *buf2 = NULL;
 | 
|---|
| 2832 |         char *targetname = NULL;
 | 
|---|
| 2833 |         struct cli_state *targetcli;
 | 
|---|
| 2834 |         mode_t mode;
 | 
|---|
| 2835 | 
 | 
|---|
| 2836 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
 | 
|---|
| 2837 |             !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
 | 
|---|
| 2838 |                 d_printf("chmod mode file\n");
 | 
|---|
| 2839 |                 return 1;
 | 
|---|
| 2840 |         }
 | 
|---|
| 2841 |         src = talloc_asprintf(ctx,
 | 
|---|
| 2842 |                         "%s%s",
 | 
|---|
| 2843 |                         client_get_cur_dir(),
 | 
|---|
| 2844 |                         buf2);
 | 
|---|
| 2845 |         if (!src) {
 | 
|---|
| 2846 |                 return 1;
 | 
|---|
| 2847 |         }
 | 
|---|
| 2848 | 
 | 
|---|
| 2849 |         mode = (mode_t)strtol(buf, NULL, 8);
 | 
|---|
| 2850 | 
 | 
|---|
| 2851 |         if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
 | 
|---|
| 2852 |                 d_printf("chmod %s: %s\n", src, cli_errstr(cli));
 | 
|---|
| 2853 |                 return 1;
 | 
|---|
| 2854 |         }
 | 
|---|
| 2855 | 
 | 
|---|
| 2856 |         if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
 | 
|---|
| 2857 |                 d_printf("Server doesn't support UNIX CIFS calls.\n");
 | 
|---|
| 2858 |                 return 1;
 | 
|---|
| 2859 |         }
 | 
|---|
| 2860 | 
 | 
|---|
| 2861 |         if (!NT_STATUS_IS_OK(cli_posix_chmod(targetcli, targetname, mode))) {
 | 
|---|
| 2862 |                 d_printf("%s chmod file %s 0%o\n",
 | 
|---|
| 2863 |                         cli_errstr(targetcli), src, (unsigned int)mode);
 | 
|---|
| 2864 |                 return 1;
 | 
|---|
| 2865 |         }
 | 
|---|
| 2866 | 
 | 
|---|
| 2867 |         return 0;
 | 
|---|
| 2868 | }
 | 
|---|
| 2869 | 
 | 
|---|
| 2870 | static const char *filetype_to_str(mode_t mode)
 | 
|---|
| 2871 | {
 | 
|---|
| 2872 |         if (S_ISREG(mode)) {
 | 
|---|
| 2873 |                 return "regular file";
 | 
|---|
| 2874 |         } else if (S_ISDIR(mode)) {
 | 
|---|
| 2875 |                 return "directory";
 | 
|---|
| 2876 |         } else
 | 
|---|
| 2877 | #ifdef S_ISCHR
 | 
|---|
| 2878 |         if (S_ISCHR(mode)) {
 | 
|---|
| 2879 |                 return "character device";
 | 
|---|
| 2880 |         } else
 | 
|---|
| 2881 | #endif
 | 
|---|
| 2882 | #ifdef S_ISBLK
 | 
|---|
| 2883 |         if (S_ISBLK(mode)) {
 | 
|---|
| 2884 |                 return "block device";
 | 
|---|
| 2885 |         } else
 | 
|---|
| 2886 | #endif
 | 
|---|
| 2887 | #ifdef S_ISFIFO
 | 
|---|
| 2888 |         if (S_ISFIFO(mode)) {
 | 
|---|
| 2889 |                 return "fifo";
 | 
|---|
| 2890 |         } else
 | 
|---|
| 2891 | #endif
 | 
|---|
| 2892 | #ifdef S_ISLNK
 | 
|---|
| 2893 |         if (S_ISLNK(mode)) {
 | 
|---|
| 2894 |                 return "symbolic link";
 | 
|---|
| 2895 |         } else
 | 
|---|
| 2896 | #endif
 | 
|---|
| 2897 | #ifdef S_ISSOCK
 | 
|---|
| 2898 |         if (S_ISSOCK(mode)) {
 | 
|---|
| 2899 |                 return "socket";
 | 
|---|
| 2900 |         } else
 | 
|---|
| 2901 | #endif
 | 
|---|
| 2902 |         return "";
 | 
|---|
| 2903 | }
 | 
|---|
| 2904 | 
 | 
|---|
| 2905 | static char rwx_to_str(mode_t m, mode_t bt, char ret)
 | 
|---|
| 2906 | {
 | 
|---|
| 2907 |         if (m & bt) {
 | 
|---|
| 2908 |                 return ret;
 | 
|---|
| 2909 |         } else {
 | 
|---|
| 2910 |                 return '-';
 | 
|---|
| 2911 |         }
 | 
|---|
| 2912 | }
 | 
|---|
| 2913 | 
 | 
|---|
| 2914 | static char *unix_mode_to_str(char *s, mode_t m)
 | 
|---|
| 2915 | {
 | 
|---|
| 2916 |         char *p = s;
 | 
|---|
| 2917 |         const char *str = filetype_to_str(m);
 | 
|---|
| 2918 | 
 | 
|---|
| 2919 |         switch(str[0]) {
 | 
|---|
| 2920 |                 case 'd':
 | 
|---|
| 2921 |                         *p++ = 'd';
 | 
|---|
| 2922 |                         break;
 | 
|---|
| 2923 |                 case 'c':
 | 
|---|
| 2924 |                         *p++ = 'c';
 | 
|---|
| 2925 |                         break;
 | 
|---|
| 2926 |                 case 'b':
 | 
|---|
| 2927 |                         *p++ = 'b';
 | 
|---|
| 2928 |                         break;
 | 
|---|
| 2929 |                 case 'f':
 | 
|---|
| 2930 |                         *p++ = 'p';
 | 
|---|
| 2931 |                         break;
 | 
|---|
| 2932 |                 case 's':
 | 
|---|
| 2933 |                         *p++ = str[1] == 'y' ? 'l' : 's';
 | 
|---|
| 2934 |                         break;
 | 
|---|
| 2935 |                 case 'r':
 | 
|---|
| 2936 |                 default:
 | 
|---|
| 2937 |                         *p++ = '-';
 | 
|---|
| 2938 |                         break;
 | 
|---|
| 2939 |         }
 | 
|---|
| 2940 |         *p++ = rwx_to_str(m, S_IRUSR, 'r');
 | 
|---|
| 2941 |         *p++ = rwx_to_str(m, S_IWUSR, 'w');
 | 
|---|
| 2942 |         *p++ = rwx_to_str(m, S_IXUSR, 'x');
 | 
|---|
| 2943 |         *p++ = rwx_to_str(m, S_IRGRP, 'r');
 | 
|---|
| 2944 |         *p++ = rwx_to_str(m, S_IWGRP, 'w');
 | 
|---|
| 2945 |         *p++ = rwx_to_str(m, S_IXGRP, 'x');
 | 
|---|
| 2946 |         *p++ = rwx_to_str(m, S_IROTH, 'r');
 | 
|---|
| 2947 |         *p++ = rwx_to_str(m, S_IWOTH, 'w');
 | 
|---|
| 2948 |         *p++ = rwx_to_str(m, S_IXOTH, 'x');
 | 
|---|
| 2949 |         *p++ = '\0';
 | 
|---|
| 2950 |         return s;
 | 
|---|
| 2951 | }
 | 
|---|
| 2952 | 
 | 
|---|
| 2953 | /****************************************************************************
 | 
|---|
| 2954 |  Utility function for UNIX getfacl.
 | 
|---|
| 2955 | ****************************************************************************/
 | 
|---|
| 2956 | 
 | 
|---|
| 2957 | static char *perms_to_string(fstring permstr, unsigned char perms)
 | 
|---|
| 2958 | {
 | 
|---|
| 2959 |         fstrcpy(permstr, "---");
 | 
|---|
| 2960 |         if (perms & SMB_POSIX_ACL_READ) {
 | 
|---|
| 2961 |                 permstr[0] = 'r';
 | 
|---|
| 2962 |         }
 | 
|---|
| 2963 |         if (perms & SMB_POSIX_ACL_WRITE) {
 | 
|---|
| 2964 |                 permstr[1] = 'w';
 | 
|---|
| 2965 |         }
 | 
|---|
| 2966 |         if (perms & SMB_POSIX_ACL_EXECUTE) {
 | 
|---|
| 2967 |                 permstr[2] = 'x';
 | 
|---|
| 2968 |         }
 | 
|---|
| 2969 |         return permstr;
 | 
|---|
| 2970 | }
 | 
|---|
| 2971 | 
 | 
|---|
| 2972 | /****************************************************************************
 | 
|---|
| 2973 |  UNIX getfacl.
 | 
|---|
| 2974 | ****************************************************************************/
 | 
|---|
| 2975 | 
 | 
|---|
| 2976 | static int cmd_getfacl(void)
 | 
|---|
| 2977 | {
 | 
|---|
| 2978 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 2979 |         char *src = NULL;
 | 
|---|
| 2980 |         char *name = NULL;
 | 
|---|
| 2981 |         char *targetname = NULL;
 | 
|---|
| 2982 |         struct cli_state *targetcli;
 | 
|---|
| 2983 |         uint16 major, minor;
 | 
|---|
| 2984 |         uint32 caplow, caphigh;
 | 
|---|
| 2985 |         char *retbuf = NULL;
 | 
|---|
| 2986 |         size_t rb_size = 0;
 | 
|---|
| 2987 |         SMB_STRUCT_STAT sbuf;
 | 
|---|
| 2988 |         uint16 num_file_acls = 0;
 | 
|---|
| 2989 |         uint16 num_dir_acls = 0;
 | 
|---|
| 2990 |         uint16 i;
 | 
|---|
| 2991 |         NTSTATUS status;
 | 
|---|
| 2992 | 
 | 
|---|
| 2993 |         if (!next_token_talloc(ctx, &cmd_ptr,&name,NULL)) {
 | 
|---|
| 2994 |                 d_printf("getfacl filename\n");
 | 
|---|
| 2995 |                 return 1;
 | 
|---|
| 2996 |         }
 | 
|---|
| 2997 |         src = talloc_asprintf(ctx,
 | 
|---|
| 2998 |                         "%s%s",
 | 
|---|
| 2999 |                         client_get_cur_dir(),
 | 
|---|
| 3000 |                         name);
 | 
|---|
| 3001 |         if (!src) {
 | 
|---|
| 3002 |                 return 1;
 | 
|---|
| 3003 |         }
 | 
|---|
| 3004 | 
 | 
|---|
| 3005 |         if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
 | 
|---|
| 3006 |                 d_printf("stat %s: %s\n", src, cli_errstr(cli));
 | 
|---|
| 3007 |                 return 1;
 | 
|---|
| 3008 |         }
 | 
|---|
| 3009 | 
 | 
|---|
| 3010 |         if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
 | 
|---|
| 3011 |                 d_printf("Server doesn't support UNIX CIFS calls.\n");
 | 
|---|
| 3012 |                 return 1;
 | 
|---|
| 3013 |         }
 | 
|---|
| 3014 | 
 | 
|---|
| 3015 |         status = cli_unix_extensions_version(targetcli, &major, &minor,
 | 
|---|
| 3016 |                                              &caplow, &caphigh);
 | 
|---|
| 3017 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 3018 |                 d_printf("Can't get UNIX CIFS version from server: %s.\n",
 | 
|---|
| 3019 |                          nt_errstr(status));
 | 
|---|
| 3020 |                 return 1;
 | 
|---|
| 3021 |         }
 | 
|---|
| 3022 | 
 | 
|---|
| 3023 |         if (!(caplow & CIFS_UNIX_POSIX_ACLS_CAP)) {
 | 
|---|
| 3024 |                 d_printf("This server supports UNIX extensions "
 | 
|---|
| 3025 |                         "but doesn't support POSIX ACLs.\n");
 | 
|---|
| 3026 |                 return 1;
 | 
|---|
| 3027 |         }
 | 
|---|
| 3028 | 
 | 
|---|
| 3029 |         if (!NT_STATUS_IS_OK(cli_posix_stat(targetcli, targetname, &sbuf))) {
 | 
|---|
| 3030 |                 d_printf("%s getfacl doing a stat on file %s\n",
 | 
|---|
| 3031 |                         cli_errstr(targetcli), src);
 | 
|---|
| 3032 |                 return 1;
 | 
|---|
| 3033 |         }
 | 
|---|
| 3034 | 
 | 
|---|
| 3035 |         if (!NT_STATUS_IS_OK(cli_posix_getfacl(targetcli, targetname, ctx, &rb_size, &retbuf))) {
 | 
|---|
| 3036 |                 d_printf("%s getfacl file %s\n",
 | 
|---|
| 3037 |                         cli_errstr(targetcli), src);
 | 
|---|
| 3038 |                 return 1;
 | 
|---|
| 3039 |         }
 | 
|---|
| 3040 | 
 | 
|---|
| 3041 |         /* ToDo : Print out the ACL values. */
 | 
|---|
| 3042 |         if (rb_size < 6 || SVAL(retbuf,0) != SMB_POSIX_ACL_VERSION) {
 | 
|---|
| 3043 |                 d_printf("getfacl file %s, unknown POSIX acl version %u.\n",
 | 
|---|
| 3044 |                         src, (unsigned int)CVAL(retbuf,0) );
 | 
|---|
| 3045 |                 return 1;
 | 
|---|
| 3046 |         }
 | 
|---|
| 3047 | 
 | 
|---|
| 3048 |         num_file_acls = SVAL(retbuf,2);
 | 
|---|
| 3049 |         num_dir_acls = SVAL(retbuf,4);
 | 
|---|
| 3050 |         if (rb_size != SMB_POSIX_ACL_HEADER_SIZE + SMB_POSIX_ACL_ENTRY_SIZE*(num_file_acls+num_dir_acls)) {
 | 
|---|
| 3051 |                 d_printf("getfacl file %s, incorrect POSIX acl buffer size (should be %u, was %u).\n",
 | 
|---|
| 3052 |                         src,
 | 
|---|
| 3053 |                         (unsigned int)(SMB_POSIX_ACL_HEADER_SIZE + SMB_POSIX_ACL_ENTRY_SIZE*(num_file_acls+num_dir_acls)),
 | 
|---|
| 3054 |                         (unsigned int)rb_size);
 | 
|---|
| 3055 |                 return 1;
 | 
|---|
| 3056 |         }
 | 
|---|
| 3057 | 
 | 
|---|
| 3058 |         d_printf("# file: %s\n", src);
 | 
|---|
| 3059 |         d_printf("# owner: %u\n# group: %u\n", (unsigned int)sbuf.st_ex_uid, (unsigned int)sbuf.st_ex_gid);
 | 
|---|
| 3060 | 
 | 
|---|
| 3061 |         if (num_file_acls == 0 && num_dir_acls == 0) {
 | 
|---|
| 3062 |                 d_printf("No acls found.\n");
 | 
|---|
| 3063 |         }
 | 
|---|
| 3064 | 
 | 
|---|
| 3065 |         for (i = 0; i < num_file_acls; i++) {
 | 
|---|
| 3066 |                 uint32 uorg;
 | 
|---|
| 3067 |                 fstring permstring;
 | 
|---|
| 3068 |                 unsigned char tagtype = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE));
 | 
|---|
| 3069 |                 unsigned char perms = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+1);
 | 
|---|
| 3070 | 
 | 
|---|
| 3071 |                 switch(tagtype) {
 | 
|---|
| 3072 |                         case SMB_POSIX_ACL_USER_OBJ:
 | 
|---|
| 3073 |                                 d_printf("user::");
 | 
|---|
| 3074 |                                 break;
 | 
|---|
| 3075 |                         case SMB_POSIX_ACL_USER:
 | 
|---|
| 3076 |                                 uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
 | 
|---|
| 3077 |                                 d_printf("user:%u:", uorg);
 | 
|---|
| 3078 |                                 break;
 | 
|---|
| 3079 |                         case SMB_POSIX_ACL_GROUP_OBJ:
 | 
|---|
| 3080 |                                 d_printf("group::");
 | 
|---|
| 3081 |                                 break;
 | 
|---|
| 3082 |                         case SMB_POSIX_ACL_GROUP:
 | 
|---|
| 3083 |                                 uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+(i*SMB_POSIX_ACL_ENTRY_SIZE)+2);
 | 
|---|
| 3084 |                                 d_printf("group:%u:", uorg);
 | 
|---|
| 3085 |                                 break;
 | 
|---|
| 3086 |                         case SMB_POSIX_ACL_MASK:
 | 
|---|
| 3087 |                                 d_printf("mask::");
 | 
|---|
| 3088 |                                 break;
 | 
|---|
| 3089 |                         case SMB_POSIX_ACL_OTHER:
 | 
|---|
| 3090 |                                 d_printf("other::");
 | 
|---|
| 3091 |                                 break;
 | 
|---|
| 3092 |                         default:
 | 
|---|
| 3093 |                                 d_printf("getfacl file %s, incorrect POSIX acl tagtype (%u).\n",
 | 
|---|
| 3094 |                                         src, (unsigned int)tagtype );
 | 
|---|
| 3095 |                                 SAFE_FREE(retbuf);
 | 
|---|
| 3096 |                                 return 1;
 | 
|---|
| 3097 |                 }
 | 
|---|
| 3098 | 
 | 
|---|
| 3099 |                 d_printf("%s\n", perms_to_string(permstring, perms));
 | 
|---|
| 3100 |         }
 | 
|---|
| 3101 | 
 | 
|---|
| 3102 |         for (i = 0; i < num_dir_acls; i++) {
 | 
|---|
| 3103 |                 uint32 uorg;
 | 
|---|
| 3104 |                 fstring permstring;
 | 
|---|
| 3105 |                 unsigned char tagtype = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE));
 | 
|---|
| 3106 |                 unsigned char perms = CVAL(retbuf, SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+1);
 | 
|---|
| 3107 | 
 | 
|---|
| 3108 |                 switch(tagtype) {
 | 
|---|
| 3109 |                         case SMB_POSIX_ACL_USER_OBJ:
 | 
|---|
| 3110 |                                 d_printf("default:user::");
 | 
|---|
| 3111 |                                 break;
 | 
|---|
| 3112 |                         case SMB_POSIX_ACL_USER:
 | 
|---|
| 3113 |                                 uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+2);
 | 
|---|
| 3114 |                                 d_printf("default:user:%u:", uorg);
 | 
|---|
| 3115 |                                 break;
 | 
|---|
| 3116 |                         case SMB_POSIX_ACL_GROUP_OBJ:
 | 
|---|
| 3117 |                                 d_printf("default:group::");
 | 
|---|
| 3118 |                                 break;
 | 
|---|
| 3119 |                         case SMB_POSIX_ACL_GROUP:
 | 
|---|
| 3120 |                                 uorg = IVAL(retbuf,SMB_POSIX_ACL_HEADER_SIZE+((i+num_file_acls)*SMB_POSIX_ACL_ENTRY_SIZE)+2);
 | 
|---|
| 3121 |                                 d_printf("default:group:%u:", uorg);
 | 
|---|
| 3122 |                                 break;
 | 
|---|
| 3123 |                         case SMB_POSIX_ACL_MASK:
 | 
|---|
| 3124 |                                 d_printf("default:mask::");
 | 
|---|
| 3125 |                                 break;
 | 
|---|
| 3126 |                         case SMB_POSIX_ACL_OTHER:
 | 
|---|
| 3127 |                                 d_printf("default:other::");
 | 
|---|
| 3128 |                                 break;
 | 
|---|
| 3129 |                         default:
 | 
|---|
| 3130 |                                 d_printf("getfacl file %s, incorrect POSIX acl tagtype (%u).\n",
 | 
|---|
| 3131 |                                         src, (unsigned int)tagtype );
 | 
|---|
| 3132 |                                 SAFE_FREE(retbuf);
 | 
|---|
| 3133 |                                 return 1;
 | 
|---|
| 3134 |                 }
 | 
|---|
| 3135 | 
 | 
|---|
| 3136 |                 d_printf("%s\n", perms_to_string(permstring, perms));
 | 
|---|
| 3137 |         }
 | 
|---|
| 3138 | 
 | 
|---|
| 3139 |         return 0;
 | 
|---|
| 3140 | }
 | 
|---|
| 3141 | 
 | 
|---|
| 3142 | /****************************************************************************
 | 
|---|
| 3143 |  UNIX stat.
 | 
|---|
| 3144 | ****************************************************************************/
 | 
|---|
| 3145 | 
 | 
|---|
| 3146 | static int cmd_stat(void)
 | 
|---|
| 3147 | {
 | 
|---|
| 3148 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 3149 |         char *src = NULL;
 | 
|---|
| 3150 |         char *name = NULL;
 | 
|---|
| 3151 |         char *targetname = NULL;
 | 
|---|
| 3152 |         struct cli_state *targetcli;
 | 
|---|
| 3153 |         fstring mode_str;
 | 
|---|
| 3154 |         SMB_STRUCT_STAT sbuf;
 | 
|---|
| 3155 |         struct tm *lt;
 | 
|---|
| 3156 |         time_t tmp_time;
 | 
|---|
| 3157 | 
 | 
|---|
| 3158 |         if (!next_token_talloc(ctx, &cmd_ptr,&name,NULL)) {
 | 
|---|
| 3159 |                 d_printf("stat file\n");
 | 
|---|
| 3160 |                 return 1;
 | 
|---|
| 3161 |         }
 | 
|---|
| 3162 |         src = talloc_asprintf(ctx,
 | 
|---|
| 3163 |                         "%s%s",
 | 
|---|
| 3164 |                         client_get_cur_dir(),
 | 
|---|
| 3165 |                         name);
 | 
|---|
| 3166 |         if (!src) {
 | 
|---|
| 3167 |                 return 1;
 | 
|---|
| 3168 |         }
 | 
|---|
| 3169 | 
 | 
|---|
| 3170 |         if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
 | 
|---|
| 3171 |                 d_printf("stat %s: %s\n", src, cli_errstr(cli));
 | 
|---|
| 3172 |                 return 1;
 | 
|---|
| 3173 |         }
 | 
|---|
| 3174 | 
 | 
|---|
| 3175 |         if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
 | 
|---|
| 3176 |                 d_printf("Server doesn't support UNIX CIFS calls.\n");
 | 
|---|
| 3177 |                 return 1;
 | 
|---|
| 3178 |         }
 | 
|---|
| 3179 | 
 | 
|---|
| 3180 |         if (!NT_STATUS_IS_OK(cli_posix_stat(targetcli, targetname, &sbuf))) {
 | 
|---|
| 3181 |                 d_printf("%s stat file %s\n",
 | 
|---|
| 3182 |                         cli_errstr(targetcli), src);
 | 
|---|
| 3183 |                 return 1;
 | 
|---|
| 3184 |         }
 | 
|---|
| 3185 | 
 | 
|---|
| 3186 |         /* Print out the stat values. */
 | 
|---|
| 3187 |         d_printf("File: %s\n", src);
 | 
|---|
| 3188 |         d_printf("Size: %-12.0f\tBlocks: %u\t%s\n",
 | 
|---|
| 3189 |                 (double)sbuf.st_ex_size,
 | 
|---|
| 3190 |                 (unsigned int)sbuf.st_ex_blocks,
 | 
|---|
| 3191 |                 filetype_to_str(sbuf.st_ex_mode));
 | 
|---|
| 3192 | 
 | 
|---|
| 3193 | #if defined(S_ISCHR) && defined(S_ISBLK)
 | 
|---|
| 3194 |         if (S_ISCHR(sbuf.st_ex_mode) || S_ISBLK(sbuf.st_ex_mode)) {
 | 
|---|
| 3195 |                 d_printf("Inode: %.0f\tLinks: %u\tDevice type: %u,%u\n",
 | 
|---|
| 3196 |                         (double)sbuf.st_ex_ino,
 | 
|---|
| 3197 |                         (unsigned int)sbuf.st_ex_nlink,
 | 
|---|
| 3198 |                         unix_dev_major(sbuf.st_ex_rdev),
 | 
|---|
| 3199 |                         unix_dev_minor(sbuf.st_ex_rdev));
 | 
|---|
| 3200 |         } else
 | 
|---|
| 3201 | #endif
 | 
|---|
| 3202 |                 d_printf("Inode: %.0f\tLinks: %u\n",
 | 
|---|
| 3203 |                         (double)sbuf.st_ex_ino,
 | 
|---|
| 3204 |                         (unsigned int)sbuf.st_ex_nlink);
 | 
|---|
| 3205 | 
 | 
|---|
| 3206 |         d_printf("Access: (0%03o/%s)\tUid: %u\tGid: %u\n",
 | 
|---|
| 3207 |                 ((int)sbuf.st_ex_mode & 0777),
 | 
|---|
| 3208 |                 unix_mode_to_str(mode_str, sbuf.st_ex_mode),
 | 
|---|
| 3209 |                 (unsigned int)sbuf.st_ex_uid,
 | 
|---|
| 3210 |                 (unsigned int)sbuf.st_ex_gid);
 | 
|---|
| 3211 | 
 | 
|---|
| 3212 |         tmp_time = convert_timespec_to_time_t(sbuf.st_ex_atime);
 | 
|---|
| 3213 |         lt = localtime(&tmp_time);
 | 
|---|
| 3214 |         if (lt) {
 | 
|---|
| 3215 |                 strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
 | 
|---|
| 3216 |         } else {
 | 
|---|
| 3217 |                 fstrcpy(mode_str, "unknown");
 | 
|---|
| 3218 |         }
 | 
|---|
| 3219 |         d_printf("Access: %s\n", mode_str);
 | 
|---|
| 3220 | 
 | 
|---|
| 3221 |         tmp_time = convert_timespec_to_time_t(sbuf.st_ex_mtime);
 | 
|---|
| 3222 |         lt = localtime(&tmp_time);
 | 
|---|
| 3223 |         if (lt) {
 | 
|---|
| 3224 |                 strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
 | 
|---|
| 3225 |         } else {
 | 
|---|
| 3226 |                 fstrcpy(mode_str, "unknown");
 | 
|---|
| 3227 |         }
 | 
|---|
| 3228 |         d_printf("Modify: %s\n", mode_str);
 | 
|---|
| 3229 | 
 | 
|---|
| 3230 |         tmp_time = convert_timespec_to_time_t(sbuf.st_ex_ctime);
 | 
|---|
| 3231 |         lt = localtime(&tmp_time);
 | 
|---|
| 3232 |         if (lt) {
 | 
|---|
| 3233 |                 strftime(mode_str, sizeof(mode_str), "%Y-%m-%d %T %z", lt);
 | 
|---|
| 3234 |         } else {
 | 
|---|
| 3235 |                 fstrcpy(mode_str, "unknown");
 | 
|---|
| 3236 |         }
 | 
|---|
| 3237 |         d_printf("Change: %s\n", mode_str);
 | 
|---|
| 3238 | 
 | 
|---|
| 3239 |         return 0;
 | 
|---|
| 3240 | }
 | 
|---|
| 3241 | 
 | 
|---|
| 3242 | 
 | 
|---|
| 3243 | /****************************************************************************
 | 
|---|
| 3244 |  UNIX chown.
 | 
|---|
| 3245 | ****************************************************************************/
 | 
|---|
| 3246 | 
 | 
|---|
| 3247 | static int cmd_chown(void)
 | 
|---|
| 3248 | {
 | 
|---|
| 3249 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 3250 |         char *src = NULL;
 | 
|---|
| 3251 |         uid_t uid;
 | 
|---|
| 3252 |         gid_t gid;
 | 
|---|
| 3253 |         char *buf, *buf2, *buf3;
 | 
|---|
| 3254 |         struct cli_state *targetcli;
 | 
|---|
| 3255 |         char *targetname = NULL;
 | 
|---|
| 3256 | 
 | 
|---|
| 3257 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
 | 
|---|
| 3258 |             !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL) ||
 | 
|---|
| 3259 |             !next_token_talloc(ctx, &cmd_ptr,&buf3,NULL)) {
 | 
|---|
| 3260 |                 d_printf("chown uid gid file\n");
 | 
|---|
| 3261 |                 return 1;
 | 
|---|
| 3262 |         }
 | 
|---|
| 3263 | 
 | 
|---|
| 3264 |         uid = (uid_t)atoi(buf);
 | 
|---|
| 3265 |         gid = (gid_t)atoi(buf2);
 | 
|---|
| 3266 | 
 | 
|---|
| 3267 |         src = talloc_asprintf(ctx,
 | 
|---|
| 3268 |                         "%s%s",
 | 
|---|
| 3269 |                         client_get_cur_dir(),
 | 
|---|
| 3270 |                         buf3);
 | 
|---|
| 3271 |         if (!src) {
 | 
|---|
| 3272 |                 return 1;
 | 
|---|
| 3273 |         }
 | 
|---|
| 3274 |         if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname) ) {
 | 
|---|
| 3275 |                 d_printf("chown %s: %s\n", src, cli_errstr(cli));
 | 
|---|
| 3276 |                 return 1;
 | 
|---|
| 3277 |         }
 | 
|---|
| 3278 | 
 | 
|---|
| 3279 |         if (!SERVER_HAS_UNIX_CIFS(targetcli)) {
 | 
|---|
| 3280 |                 d_printf("Server doesn't support UNIX CIFS calls.\n");
 | 
|---|
| 3281 |                 return 1;
 | 
|---|
| 3282 |         }
 | 
|---|
| 3283 | 
 | 
|---|
| 3284 |         if (!NT_STATUS_IS_OK(cli_posix_chown(targetcli, targetname, uid, gid))) {
 | 
|---|
| 3285 |                 d_printf("%s chown file %s uid=%d, gid=%d\n",
 | 
|---|
| 3286 |                         cli_errstr(targetcli), src, (int)uid, (int)gid);
 | 
|---|
| 3287 |                 return 1;
 | 
|---|
| 3288 |         }
 | 
|---|
| 3289 | 
 | 
|---|
| 3290 |         return 0;
 | 
|---|
| 3291 | }
 | 
|---|
| 3292 | 
 | 
|---|
| 3293 | /****************************************************************************
 | 
|---|
| 3294 |  Rename some file.
 | 
|---|
| 3295 | ****************************************************************************/
 | 
|---|
| 3296 | 
 | 
|---|
| 3297 | static int cmd_rename(void)
 | 
|---|
| 3298 | {
 | 
|---|
| 3299 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 3300 |         char *src, *dest;
 | 
|---|
| 3301 |         char *buf, *buf2;
 | 
|---|
| 3302 |         struct cli_state *targetcli;
 | 
|---|
| 3303 |         char *targetsrc;
 | 
|---|
| 3304 |         char *targetdest;
 | 
|---|
| 3305 | 
 | 
|---|
| 3306 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
 | 
|---|
| 3307 |             !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
 | 
|---|
| 3308 |                 d_printf("rename <src> <dest>\n");
 | 
|---|
| 3309 |                 return 1;
 | 
|---|
| 3310 |         }
 | 
|---|
| 3311 | 
 | 
|---|
| 3312 |         src = talloc_asprintf(ctx,
 | 
|---|
| 3313 |                         "%s%s",
 | 
|---|
| 3314 |                         client_get_cur_dir(),
 | 
|---|
| 3315 |                         buf);
 | 
|---|
| 3316 |         if (!src) {
 | 
|---|
| 3317 |                 return 1;
 | 
|---|
| 3318 |         }
 | 
|---|
| 3319 | 
 | 
|---|
| 3320 |         dest = talloc_asprintf(ctx,
 | 
|---|
| 3321 |                         "%s%s",
 | 
|---|
| 3322 |                         client_get_cur_dir(),
 | 
|---|
| 3323 |                         buf2);
 | 
|---|
| 3324 |         if (!dest) {
 | 
|---|
| 3325 |                 return 1;
 | 
|---|
| 3326 |         }
 | 
|---|
| 3327 | 
 | 
|---|
| 3328 |         if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetsrc)) {
 | 
|---|
| 3329 |                 d_printf("rename %s: %s\n", src, cli_errstr(cli));
 | 
|---|
| 3330 |                 return 1;
 | 
|---|
| 3331 |         }
 | 
|---|
| 3332 | 
 | 
|---|
| 3333 |         if (!cli_resolve_path(ctx, "", auth_info, cli, dest, &targetcli, &targetdest)) {
 | 
|---|
| 3334 |                 d_printf("rename %s: %s\n", dest, cli_errstr(cli));
 | 
|---|
| 3335 |                 return 1;
 | 
|---|
| 3336 |         }
 | 
|---|
| 3337 | 
 | 
|---|
| 3338 |         if (!NT_STATUS_IS_OK(cli_rename(targetcli, targetsrc, targetdest))) {
 | 
|---|
| 3339 |                 d_printf("%s renaming files %s -> %s \n",
 | 
|---|
| 3340 |                         cli_errstr(targetcli),
 | 
|---|
| 3341 |                         targetsrc,
 | 
|---|
| 3342 |                         targetdest);
 | 
|---|
| 3343 |                 return 1;
 | 
|---|
| 3344 |         }
 | 
|---|
| 3345 | 
 | 
|---|
| 3346 |         return 0;
 | 
|---|
| 3347 | }
 | 
|---|
| 3348 | 
 | 
|---|
| 3349 | /****************************************************************************
 | 
|---|
| 3350 |  Print the volume name.
 | 
|---|
| 3351 | ****************************************************************************/
 | 
|---|
| 3352 | 
 | 
|---|
| 3353 | static int cmd_volume(void)
 | 
|---|
| 3354 | {
 | 
|---|
| 3355 |         fstring volname;
 | 
|---|
| 3356 |         uint32 serial_num;
 | 
|---|
| 3357 |         time_t create_date;
 | 
|---|
| 3358 | 
 | 
|---|
| 3359 |         if (!cli_get_fs_volume_info(cli, volname, &serial_num, &create_date)) {
 | 
|---|
| 3360 |                 d_printf("Errr %s getting volume info\n",cli_errstr(cli));
 | 
|---|
| 3361 |                 return 1;
 | 
|---|
| 3362 |         }
 | 
|---|
| 3363 | 
 | 
|---|
| 3364 |         d_printf("Volume: |%s| serial number 0x%x\n",
 | 
|---|
| 3365 |                         volname, (unsigned int)serial_num);
 | 
|---|
| 3366 |         return 0;
 | 
|---|
| 3367 | }
 | 
|---|
| 3368 | 
 | 
|---|
| 3369 | /****************************************************************************
 | 
|---|
| 3370 |  Hard link files using the NT call.
 | 
|---|
| 3371 | ****************************************************************************/
 | 
|---|
| 3372 | 
 | 
|---|
| 3373 | static int cmd_hardlink(void)
 | 
|---|
| 3374 | {
 | 
|---|
| 3375 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 3376 |         char *src, *dest;
 | 
|---|
| 3377 |         char *buf, *buf2;
 | 
|---|
| 3378 |         struct cli_state *targetcli;
 | 
|---|
| 3379 |         char *targetname;
 | 
|---|
| 3380 | 
 | 
|---|
| 3381 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL) ||
 | 
|---|
| 3382 |             !next_token_talloc(ctx, &cmd_ptr,&buf2,NULL)) {
 | 
|---|
| 3383 |                 d_printf("hardlink <src> <dest>\n");
 | 
|---|
| 3384 |                 return 1;
 | 
|---|
| 3385 |         }
 | 
|---|
| 3386 | 
 | 
|---|
| 3387 |         src = talloc_asprintf(ctx,
 | 
|---|
| 3388 |                         "%s%s",
 | 
|---|
| 3389 |                         client_get_cur_dir(),
 | 
|---|
| 3390 |                         buf);
 | 
|---|
| 3391 |         if (!src) {
 | 
|---|
| 3392 |                 return 1;
 | 
|---|
| 3393 |         }
 | 
|---|
| 3394 | 
 | 
|---|
| 3395 |         dest = talloc_asprintf(ctx,
 | 
|---|
| 3396 |                         "%s%s",
 | 
|---|
| 3397 |                         client_get_cur_dir(),
 | 
|---|
| 3398 |                         buf2);
 | 
|---|
| 3399 |         if (!dest) {
 | 
|---|
| 3400 |                 return 1;
 | 
|---|
| 3401 |         }
 | 
|---|
| 3402 | 
 | 
|---|
| 3403 |         if (!cli_resolve_path(ctx, "", auth_info, cli, src, &targetcli, &targetname)) {
 | 
|---|
| 3404 |                 d_printf("hardlink %s: %s\n", src, cli_errstr(cli));
 | 
|---|
| 3405 |                 return 1;
 | 
|---|
| 3406 |         }
 | 
|---|
| 3407 | 
 | 
|---|
| 3408 |         if (!NT_STATUS_IS_OK(cli_nt_hardlink(targetcli, targetname, dest))) {
 | 
|---|
| 3409 |                 d_printf("%s doing an NT hard link of files\n",cli_errstr(targetcli));
 | 
|---|
| 3410 |                 return 1;
 | 
|---|
| 3411 |         }
 | 
|---|
| 3412 | 
 | 
|---|
| 3413 |         return 0;
 | 
|---|
| 3414 | }
 | 
|---|
| 3415 | 
 | 
|---|
| 3416 | /****************************************************************************
 | 
|---|
| 3417 |  Toggle the prompt flag.
 | 
|---|
| 3418 | ****************************************************************************/
 | 
|---|
| 3419 | 
 | 
|---|
| 3420 | static int cmd_prompt(void)
 | 
|---|
| 3421 | {
 | 
|---|
| 3422 |         prompt = !prompt;
 | 
|---|
| 3423 |         DEBUG(2,("prompting is now %s\n",prompt?"on":"off"));
 | 
|---|
| 3424 |         return 1;
 | 
|---|
| 3425 | }
 | 
|---|
| 3426 | 
 | 
|---|
| 3427 | /****************************************************************************
 | 
|---|
| 3428 |  Set the newer than time.
 | 
|---|
| 3429 | ****************************************************************************/
 | 
|---|
| 3430 | 
 | 
|---|
| 3431 | static int cmd_newer(void)
 | 
|---|
| 3432 | {
 | 
|---|
| 3433 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 3434 |         char *buf;
 | 
|---|
| 3435 |         bool ok;
 | 
|---|
| 3436 |         SMB_STRUCT_STAT sbuf;
 | 
|---|
| 3437 | 
 | 
|---|
| 3438 |         ok = next_token_talloc(ctx, &cmd_ptr,&buf,NULL);
 | 
|---|
| 3439 |         if (ok && (sys_stat(buf, &sbuf, false) == 0)) {
 | 
|---|
| 3440 |                 newer_than = convert_timespec_to_time_t(sbuf.st_ex_mtime);
 | 
|---|
| 3441 |                 DEBUG(1,("Getting files newer than %s",
 | 
|---|
| 3442 |                          time_to_asc(newer_than)));
 | 
|---|
| 3443 |         } else {
 | 
|---|
| 3444 |                 newer_than = 0;
 | 
|---|
| 3445 |         }
 | 
|---|
| 3446 | 
 | 
|---|
| 3447 |         if (ok && newer_than == 0) {
 | 
|---|
| 3448 |                 d_printf("Error setting newer-than time\n");
 | 
|---|
| 3449 |                 return 1;
 | 
|---|
| 3450 |         }
 | 
|---|
| 3451 | 
 | 
|---|
| 3452 |         return 0;
 | 
|---|
| 3453 | }
 | 
|---|
| 3454 | 
 | 
|---|
| 3455 | /****************************************************************************
 | 
|---|
| 3456 |  Set the archive level.
 | 
|---|
| 3457 | ****************************************************************************/
 | 
|---|
| 3458 | 
 | 
|---|
| 3459 | static int cmd_archive(void)
 | 
|---|
| 3460 | {
 | 
|---|
| 3461 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 3462 |         char *buf;
 | 
|---|
| 3463 | 
 | 
|---|
| 3464 |         if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 3465 |                 archive_level = atoi(buf);
 | 
|---|
| 3466 |         } else {
 | 
|---|
| 3467 |                 d_printf("Archive level is %d\n",archive_level);
 | 
|---|
| 3468 |         }
 | 
|---|
| 3469 | 
 | 
|---|
| 3470 |         return 0;
 | 
|---|
| 3471 | }
 | 
|---|
| 3472 | 
 | 
|---|
| 3473 | /****************************************************************************
 | 
|---|
| 3474 |  Toggle the lowercaseflag.
 | 
|---|
| 3475 | ****************************************************************************/
 | 
|---|
| 3476 | 
 | 
|---|
| 3477 | static int cmd_lowercase(void)
 | 
|---|
| 3478 | {
 | 
|---|
| 3479 |         lowercase = !lowercase;
 | 
|---|
| 3480 |         DEBUG(2,("filename lowercasing is now %s\n",lowercase?"on":"off"));
 | 
|---|
| 3481 |         return 0;
 | 
|---|
| 3482 | }
 | 
|---|
| 3483 | 
 | 
|---|
| 3484 | /****************************************************************************
 | 
|---|
| 3485 |  Toggle the case sensitive flag.
 | 
|---|
| 3486 | ****************************************************************************/
 | 
|---|
| 3487 | 
 | 
|---|
| 3488 | static int cmd_setcase(void)
 | 
|---|
| 3489 | {
 | 
|---|
| 3490 |         bool orig_case_sensitive = cli_set_case_sensitive(cli, false);
 | 
|---|
| 3491 | 
 | 
|---|
| 3492 |         cli_set_case_sensitive(cli, !orig_case_sensitive);
 | 
|---|
| 3493 |         DEBUG(2,("filename case sensitivity is now %s\n",!orig_case_sensitive ?
 | 
|---|
| 3494 |                 "on":"off"));
 | 
|---|
| 3495 |         return 0;
 | 
|---|
| 3496 | }
 | 
|---|
| 3497 | 
 | 
|---|
| 3498 | /****************************************************************************
 | 
|---|
| 3499 |  Toggle the showacls flag.
 | 
|---|
| 3500 | ****************************************************************************/
 | 
|---|
| 3501 | 
 | 
|---|
| 3502 | static int cmd_showacls(void)
 | 
|---|
| 3503 | {
 | 
|---|
| 3504 |         showacls = !showacls;
 | 
|---|
| 3505 |         DEBUG(2,("showacls is now %s\n",showacls?"on":"off"));
 | 
|---|
| 3506 |         return 0;
 | 
|---|
| 3507 | }
 | 
|---|
| 3508 | 
 | 
|---|
| 3509 | 
 | 
|---|
| 3510 | /****************************************************************************
 | 
|---|
| 3511 |  Toggle the recurse flag.
 | 
|---|
| 3512 | ****************************************************************************/
 | 
|---|
| 3513 | 
 | 
|---|
| 3514 | static int cmd_recurse(void)
 | 
|---|
| 3515 | {
 | 
|---|
| 3516 |         recurse = !recurse;
 | 
|---|
| 3517 |         DEBUG(2,("directory recursion is now %s\n",recurse?"on":"off"));
 | 
|---|
| 3518 |         return 0;
 | 
|---|
| 3519 | }
 | 
|---|
| 3520 | 
 | 
|---|
| 3521 | /****************************************************************************
 | 
|---|
| 3522 |  Toggle the translate flag.
 | 
|---|
| 3523 | ****************************************************************************/
 | 
|---|
| 3524 | 
 | 
|---|
| 3525 | static int cmd_translate(void)
 | 
|---|
| 3526 | {
 | 
|---|
| 3527 |         translation = !translation;
 | 
|---|
| 3528 |         DEBUG(2,("CR/LF<->LF and print text translation now %s\n",
 | 
|---|
| 3529 |                  translation?"on":"off"));
 | 
|---|
| 3530 |         return 0;
 | 
|---|
| 3531 | }
 | 
|---|
| 3532 | 
 | 
|---|
| 3533 | /****************************************************************************
 | 
|---|
| 3534 |  Do the lcd command.
 | 
|---|
| 3535 |  ****************************************************************************/
 | 
|---|
| 3536 | 
 | 
|---|
| 3537 | static int cmd_lcd(void)
 | 
|---|
| 3538 | {
 | 
|---|
| 3539 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 3540 |         char *buf;
 | 
|---|
| 3541 |         char *d;
 | 
|---|
| 3542 | 
 | 
|---|
| 3543 |         if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 3544 |                 if (chdir(buf) == -1) {
 | 
|---|
| 3545 |                         d_printf("chdir to %s failed (%s)\n",
 | 
|---|
| 3546 |                                 buf, strerror(errno));
 | 
|---|
| 3547 |                 }
 | 
|---|
| 3548 |         }
 | 
|---|
| 3549 |         d = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
 | 
|---|
| 3550 |         if (!d) {
 | 
|---|
| 3551 |                 return 1;
 | 
|---|
| 3552 |         }
 | 
|---|
| 3553 |         DEBUG(2,("the local directory is now %s\n",sys_getwd(d)));
 | 
|---|
| 3554 |         return 0;
 | 
|---|
| 3555 | }
 | 
|---|
| 3556 | 
 | 
|---|
| 3557 | /****************************************************************************
 | 
|---|
| 3558 |  Get a file restarting at end of local file.
 | 
|---|
| 3559 |  ****************************************************************************/
 | 
|---|
| 3560 | 
 | 
|---|
| 3561 | static int cmd_reget(void)
 | 
|---|
| 3562 | {
 | 
|---|
| 3563 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 3564 |         char *local_name = NULL;
 | 
|---|
| 3565 |         char *remote_name = NULL;
 | 
|---|
| 3566 |         char *fname = NULL;
 | 
|---|
| 3567 |         char *p = NULL;
 | 
|---|
| 3568 | 
 | 
|---|
| 3569 |         remote_name = talloc_strdup(ctx, client_get_cur_dir());
 | 
|---|
| 3570 |         if (!remote_name) {
 | 
|---|
| 3571 |                 return 1;
 | 
|---|
| 3572 |         }
 | 
|---|
| 3573 | 
 | 
|---|
| 3574 |         if (!next_token_talloc(ctx, &cmd_ptr, &fname, NULL)) {
 | 
|---|
| 3575 |                 d_printf("reget <filename>\n");
 | 
|---|
| 3576 |                 return 1;
 | 
|---|
| 3577 |         }
 | 
|---|
| 3578 |         remote_name = talloc_asprintf_append(remote_name, "%s", fname);
 | 
|---|
| 3579 |         if (!remote_name) {
 | 
|---|
| 3580 |                 return 1;
 | 
|---|
| 3581 |         }
 | 
|---|
| 3582 |         remote_name = clean_name(ctx,remote_name);
 | 
|---|
| 3583 |         if (!remote_name) {
 | 
|---|
| 3584 |                 return 1;
 | 
|---|
| 3585 |         }
 | 
|---|
| 3586 | 
 | 
|---|
| 3587 |         local_name = fname;
 | 
|---|
| 3588 |         next_token_talloc(ctx, &cmd_ptr, &p, NULL);
 | 
|---|
| 3589 |         if (p) {
 | 
|---|
| 3590 |                 local_name = p;
 | 
|---|
| 3591 |         }
 | 
|---|
| 3592 | 
 | 
|---|
| 3593 |         return do_get(remote_name, local_name, true);
 | 
|---|
| 3594 | }
 | 
|---|
| 3595 | 
 | 
|---|
| 3596 | /****************************************************************************
 | 
|---|
| 3597 |  Put a file restarting at end of local file.
 | 
|---|
| 3598 |  ****************************************************************************/
 | 
|---|
| 3599 | 
 | 
|---|
| 3600 | static int cmd_reput(void)
 | 
|---|
| 3601 | {
 | 
|---|
| 3602 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 3603 |         char *local_name = NULL;
 | 
|---|
| 3604 |         char *remote_name = NULL;
 | 
|---|
| 3605 |         char *buf;
 | 
|---|
| 3606 |         SMB_STRUCT_STAT st;
 | 
|---|
| 3607 | 
 | 
|---|
| 3608 |         remote_name = talloc_strdup(ctx, client_get_cur_dir());
 | 
|---|
| 3609 |         if (!remote_name) {
 | 
|---|
| 3610 |                 return 1;
 | 
|---|
| 3611 |         }
 | 
|---|
| 3612 | 
 | 
|---|
| 3613 |         if (!next_token_talloc(ctx, &cmd_ptr, &local_name, NULL)) {
 | 
|---|
| 3614 |                 d_printf("reput <filename>\n");
 | 
|---|
| 3615 |                 return 1;
 | 
|---|
| 3616 |         }
 | 
|---|
| 3617 | 
 | 
|---|
| 3618 |         if (!file_exist_stat(local_name, &st, false)) {
 | 
|---|
| 3619 |                 d_printf("%s does not exist\n", local_name);
 | 
|---|
| 3620 |                 return 1;
 | 
|---|
| 3621 |         }
 | 
|---|
| 3622 | 
 | 
|---|
| 3623 |         if (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
 | 
|---|
| 3624 |                 remote_name = talloc_asprintf_append(remote_name,
 | 
|---|
| 3625 |                                                 "%s", buf);
 | 
|---|
| 3626 |         } else {
 | 
|---|
| 3627 |                 remote_name = talloc_asprintf_append(remote_name,
 | 
|---|
| 3628 |                                                 "%s", local_name);
 | 
|---|
| 3629 |         }
 | 
|---|
| 3630 |         if (!remote_name) {
 | 
|---|
| 3631 |                 return 1;
 | 
|---|
| 3632 |         }
 | 
|---|
| 3633 | 
 | 
|---|
| 3634 |         remote_name = clean_name(ctx, remote_name);
 | 
|---|
| 3635 |         if (!remote_name) {
 | 
|---|
| 3636 |                 return 1;
 | 
|---|
| 3637 |         }
 | 
|---|
| 3638 | 
 | 
|---|
| 3639 |         return do_put(remote_name, local_name, true);
 | 
|---|
| 3640 | }
 | 
|---|
| 3641 | 
 | 
|---|
| 3642 | /****************************************************************************
 | 
|---|
| 3643 |  List a share name.
 | 
|---|
| 3644 |  ****************************************************************************/
 | 
|---|
| 3645 | 
 | 
|---|
| 3646 | static void browse_fn(const char *name, uint32 m,
 | 
|---|
| 3647 |                       const char *comment, void *state)
 | 
|---|
| 3648 | {
 | 
|---|
| 3649 |         const char *typestr = "";
 | 
|---|
| 3650 | 
 | 
|---|
| 3651 |         switch (m & 7) {
 | 
|---|
| 3652 |         case STYPE_DISKTREE:
 | 
|---|
| 3653 |                 typestr = "Disk";
 | 
|---|
| 3654 |                 break;
 | 
|---|
| 3655 |         case STYPE_PRINTQ:
 | 
|---|
| 3656 |                 typestr = "Printer";
 | 
|---|
| 3657 |                 break;
 | 
|---|
| 3658 |         case STYPE_DEVICE:
 | 
|---|
| 3659 |                 typestr = "Device";
 | 
|---|
| 3660 |                 break;
 | 
|---|
| 3661 |         case STYPE_IPC:
 | 
|---|
| 3662 |                 typestr = "IPC";
 | 
|---|
| 3663 |                 break;
 | 
|---|
| 3664 |         }
 | 
|---|
| 3665 |         /* FIXME: If the remote machine returns non-ascii characters
 | 
|---|
| 3666 |            in any of these fields, they can corrupt the output.  We
 | 
|---|
| 3667 |            should remove them. */
 | 
|---|
| 3668 |         if (!grepable) {
 | 
|---|
| 3669 |                 d_printf("\t%-15s %-10.10s%s\n",
 | 
|---|
| 3670 |                         name,typestr,comment);
 | 
|---|
| 3671 |         } else {
 | 
|---|
| 3672 |                 d_printf ("%s|%s|%s\n",typestr,name,comment);
 | 
|---|
| 3673 |         }
 | 
|---|
| 3674 | }
 | 
|---|
| 3675 | 
 | 
|---|
| 3676 | static bool browse_host_rpc(bool sort)
 | 
|---|
| 3677 | {
 | 
|---|
| 3678 |         NTSTATUS status;
 | 
|---|
| 3679 |         struct rpc_pipe_client *pipe_hnd = NULL;
 | 
|---|
| 3680 |         TALLOC_CTX *frame = talloc_stackframe();
 | 
|---|
| 3681 |         WERROR werr;
 | 
|---|
| 3682 |         struct srvsvc_NetShareInfoCtr info_ctr;
 | 
|---|
| 3683 |         struct srvsvc_NetShareCtr1 ctr1;
 | 
|---|
| 3684 |         uint32_t resume_handle = 0;
 | 
|---|
| 3685 |         uint32_t total_entries = 0;
 | 
|---|
| 3686 |         int i;
 | 
|---|
| 3687 | 
 | 
|---|
| 3688 |         status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id,
 | 
|---|
| 3689 |                                           &pipe_hnd);
 | 
|---|
| 3690 | 
 | 
|---|
| 3691 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 3692 |                 DEBUG(10, ("Could not connect to srvsvc pipe: %s\n",
 | 
|---|
| 3693 |                            nt_errstr(status)));
 | 
|---|
| 3694 |                 TALLOC_FREE(frame);
 | 
|---|
| 3695 |                 return false;
 | 
|---|
| 3696 |         }
 | 
|---|
| 3697 | 
 | 
|---|
| 3698 |         ZERO_STRUCT(info_ctr);
 | 
|---|
| 3699 |         ZERO_STRUCT(ctr1);
 | 
|---|
| 3700 | 
 | 
|---|
| 3701 |         info_ctr.level = 1;
 | 
|---|
| 3702 |         info_ctr.ctr.ctr1 = &ctr1;
 | 
|---|
| 3703 | 
 | 
|---|
| 3704 |         status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, frame,
 | 
|---|
| 3705 |                                               pipe_hnd->desthost,
 | 
|---|
| 3706 |                                               &info_ctr,
 | 
|---|
| 3707 |                                               0xffffffff,
 | 
|---|
| 3708 |                                               &total_entries,
 | 
|---|
| 3709 |                                               &resume_handle,
 | 
|---|
| 3710 |                                               &werr);
 | 
|---|
| 3711 | 
 | 
|---|
| 3712 |         if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
 | 
|---|
| 3713 |                 TALLOC_FREE(pipe_hnd);
 | 
|---|
| 3714 |                 TALLOC_FREE(frame);
 | 
|---|
| 3715 |                 return false;
 | 
|---|
| 3716 |         }
 | 
|---|
| 3717 | 
 | 
|---|
| 3718 |         for (i=0; i < info_ctr.ctr.ctr1->count; i++) {
 | 
|---|
| 3719 |                 struct srvsvc_NetShareInfo1 info = info_ctr.ctr.ctr1->array[i];
 | 
|---|
| 3720 |                 browse_fn(info.name, info.type, info.comment, NULL);
 | 
|---|
| 3721 |         }
 | 
|---|
| 3722 | 
 | 
|---|
| 3723 |         TALLOC_FREE(pipe_hnd);
 | 
|---|
| 3724 |         TALLOC_FREE(frame);
 | 
|---|
| 3725 |         return true;
 | 
|---|
| 3726 | }
 | 
|---|
| 3727 | 
 | 
|---|
| 3728 | /****************************************************************************
 | 
|---|
| 3729 |  Try and browse available connections on a host.
 | 
|---|
| 3730 | ****************************************************************************/
 | 
|---|
| 3731 | 
 | 
|---|
| 3732 | static bool browse_host(bool sort)
 | 
|---|
| 3733 | {
 | 
|---|
| 3734 |         int ret;
 | 
|---|
| 3735 |         if (!grepable) {
 | 
|---|
| 3736 |                 d_printf("\n\tSharename       Type      Comment\n");
 | 
|---|
| 3737 |                 d_printf("\t---------       ----      -------\n");
 | 
|---|
| 3738 |         }
 | 
|---|
| 3739 | 
 | 
|---|
| 3740 |         if (browse_host_rpc(sort)) {
 | 
|---|
| 3741 |                 return true;
 | 
|---|
| 3742 |         }
 | 
|---|
| 3743 | 
 | 
|---|
| 3744 |         if((ret = cli_RNetShareEnum(cli, browse_fn, NULL)) == -1)
 | 
|---|
| 3745 |                 d_printf("Error returning browse list: %s\n", cli_errstr(cli));
 | 
|---|
| 3746 | 
 | 
|---|
| 3747 |         return (ret != -1);
 | 
|---|
| 3748 | }
 | 
|---|
| 3749 | 
 | 
|---|
| 3750 | /****************************************************************************
 | 
|---|
| 3751 |  List a server name.
 | 
|---|
| 3752 | ****************************************************************************/
 | 
|---|
| 3753 | 
 | 
|---|
| 3754 | static void server_fn(const char *name, uint32 m,
 | 
|---|
| 3755 |                       const char *comment, void *state)
 | 
|---|
| 3756 | {
 | 
|---|
| 3757 | 
 | 
|---|
| 3758 |         if (!grepable){
 | 
|---|
| 3759 |                 d_printf("\t%-16s     %s\n", name, comment);
 | 
|---|
| 3760 |         } else {
 | 
|---|
| 3761 |                 d_printf("%s|%s|%s\n",(char *)state, name, comment);
 | 
|---|
| 3762 |         }
 | 
|---|
| 3763 | }
 | 
|---|
| 3764 | 
 | 
|---|
| 3765 | /****************************************************************************
 | 
|---|
| 3766 |  Try and browse available connections on a host.
 | 
|---|
| 3767 | ****************************************************************************/
 | 
|---|
| 3768 | 
 | 
|---|
| 3769 | static bool list_servers(const char *wk_grp)
 | 
|---|
| 3770 | {
 | 
|---|
| 3771 |         fstring state;
 | 
|---|
| 3772 | 
 | 
|---|
| 3773 |         if (!cli->server_domain)
 | 
|---|
| 3774 |                 return false;
 | 
|---|
| 3775 | 
 | 
|---|
| 3776 |         if (!grepable) {
 | 
|---|
| 3777 |                 d_printf("\n\tServer               Comment\n");
 | 
|---|
| 3778 |                 d_printf("\t---------            -------\n");
 | 
|---|
| 3779 |         };
 | 
|---|
| 3780 |         fstrcpy( state, "Server" );
 | 
|---|
| 3781 |         cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_ALL, server_fn,
 | 
|---|
| 3782 |                           state);
 | 
|---|
| 3783 | 
 | 
|---|
| 3784 |         if (!grepable) {
 | 
|---|
| 3785 |                 d_printf("\n\tWorkgroup            Master\n");
 | 
|---|
| 3786 |                 d_printf("\t---------            -------\n");
 | 
|---|
| 3787 |         };
 | 
|---|
| 3788 | 
 | 
|---|
| 3789 |         fstrcpy( state, "Workgroup" );
 | 
|---|
| 3790 |         cli_NetServerEnum(cli, cli->server_domain, SV_TYPE_DOMAIN_ENUM,
 | 
|---|
| 3791 |                           server_fn, state);
 | 
|---|
| 3792 |         return true;
 | 
|---|
| 3793 | }
 | 
|---|
| 3794 | 
 | 
|---|
| 3795 | /****************************************************************************
 | 
|---|
| 3796 |  Print or set current VUID
 | 
|---|
| 3797 | ****************************************************************************/
 | 
|---|
| 3798 | 
 | 
|---|
| 3799 | static int cmd_vuid(void)
 | 
|---|
| 3800 | {
 | 
|---|
| 3801 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 3802 |         char *buf;
 | 
|---|
| 3803 | 
 | 
|---|
| 3804 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 3805 |                 d_printf("Current VUID is %d\n", cli->vuid);
 | 
|---|
| 3806 |                 return 0;
 | 
|---|
| 3807 |         }
 | 
|---|
| 3808 | 
 | 
|---|
| 3809 |         cli->vuid = atoi(buf);
 | 
|---|
| 3810 |         return 0;
 | 
|---|
| 3811 | }
 | 
|---|
| 3812 | 
 | 
|---|
| 3813 | /****************************************************************************
 | 
|---|
| 3814 |  Setup a new VUID, by issuing a session setup
 | 
|---|
| 3815 | ****************************************************************************/
 | 
|---|
| 3816 | 
 | 
|---|
| 3817 | static int cmd_logon(void)
 | 
|---|
| 3818 | {
 | 
|---|
| 3819 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 3820 |         char *l_username, *l_password;
 | 
|---|
| 3821 | 
 | 
|---|
| 3822 |         if (!next_token_talloc(ctx, &cmd_ptr,&l_username,NULL)) {
 | 
|---|
| 3823 |                 d_printf("logon <username> [<password>]\n");
 | 
|---|
| 3824 |                 return 0;
 | 
|---|
| 3825 |         }
 | 
|---|
| 3826 | 
 | 
|---|
| 3827 |         if (!next_token_talloc(ctx, &cmd_ptr,&l_password,NULL)) {
 | 
|---|
| 3828 |                 char *pass = getpass("Password: ");
 | 
|---|
| 3829 |                 if (pass) {
 | 
|---|
| 3830 |                         l_password = talloc_strdup(ctx,pass);
 | 
|---|
| 3831 |                 }
 | 
|---|
| 3832 |         }
 | 
|---|
| 3833 |         if (!l_password) {
 | 
|---|
| 3834 |                 return 1;
 | 
|---|
| 3835 |         }
 | 
|---|
| 3836 | 
 | 
|---|
| 3837 |         if (!NT_STATUS_IS_OK(cli_session_setup(cli, l_username,
 | 
|---|
| 3838 |                                                l_password, strlen(l_password),
 | 
|---|
| 3839 |                                                l_password, strlen(l_password),
 | 
|---|
| 3840 |                                                lp_workgroup()))) {
 | 
|---|
| 3841 |                 d_printf("session setup failed: %s\n", cli_errstr(cli));
 | 
|---|
| 3842 |                 return -1;
 | 
|---|
| 3843 |         }
 | 
|---|
| 3844 | 
 | 
|---|
| 3845 |         d_printf("Current VUID is %d\n", cli->vuid);
 | 
|---|
| 3846 |         return 0;
 | 
|---|
| 3847 | }
 | 
|---|
| 3848 | 
 | 
|---|
| 3849 | 
 | 
|---|
| 3850 | /****************************************************************************
 | 
|---|
| 3851 |  list active connections
 | 
|---|
| 3852 | ****************************************************************************/
 | 
|---|
| 3853 | 
 | 
|---|
| 3854 | static int cmd_list_connect(void)
 | 
|---|
| 3855 | {
 | 
|---|
| 3856 |         cli_cm_display(cli);
 | 
|---|
| 3857 |         return 0;
 | 
|---|
| 3858 | }
 | 
|---|
| 3859 | 
 | 
|---|
| 3860 | /****************************************************************************
 | 
|---|
| 3861 |  display the current active client connection
 | 
|---|
| 3862 | ****************************************************************************/
 | 
|---|
| 3863 | 
 | 
|---|
| 3864 | static int cmd_show_connect( void )
 | 
|---|
| 3865 | {
 | 
|---|
| 3866 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 3867 |         struct cli_state *targetcli;
 | 
|---|
| 3868 |         char *targetpath;
 | 
|---|
| 3869 | 
 | 
|---|
| 3870 |         if (!cli_resolve_path(ctx, "", auth_info, cli, client_get_cur_dir(),
 | 
|---|
| 3871 |                                 &targetcli, &targetpath ) ) {
 | 
|---|
| 3872 |                 d_printf("showconnect %s: %s\n", cur_dir, cli_errstr(cli));
 | 
|---|
| 3873 |                 return 1;
 | 
|---|
| 3874 |         }
 | 
|---|
| 3875 | 
 | 
|---|
| 3876 |         d_printf("//%s/%s\n", targetcli->desthost, targetcli->share);
 | 
|---|
| 3877 |         return 0;
 | 
|---|
| 3878 | }
 | 
|---|
| 3879 | 
 | 
|---|
| 3880 | /****************************************************************************
 | 
|---|
| 3881 |  iosize command
 | 
|---|
| 3882 | ***************************************************************************/
 | 
|---|
| 3883 | 
 | 
|---|
| 3884 | int cmd_iosize(void)
 | 
|---|
| 3885 | {
 | 
|---|
| 3886 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 3887 |         char *buf;
 | 
|---|
| 3888 |         int iosize;
 | 
|---|
| 3889 | 
 | 
|---|
| 3890 |         if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 3891 |                 if (!smb_encrypt) {
 | 
|---|
| 3892 |                         d_printf("iosize <n> or iosize 0x<n>. "
 | 
|---|
| 3893 |                                 "Minimum is 16384 (0x4000), "
 | 
|---|
| 3894 |                                 "max is 16776960 (0xFFFF00)\n");
 | 
|---|
| 3895 |                 } else {
 | 
|---|
| 3896 |                         d_printf("iosize <n> or iosize 0x<n>. "
 | 
|---|
| 3897 |                                 "(Encrypted connection) ,"
 | 
|---|
| 3898 |                                 "Minimum is 16384 (0x4000), "
 | 
|---|
| 3899 |                                 "max is 130048 (0x1FC00)\n");
 | 
|---|
| 3900 |                 }
 | 
|---|
| 3901 |                 return 1;
 | 
|---|
| 3902 |         }
 | 
|---|
| 3903 | 
 | 
|---|
| 3904 |         iosize = strtol(buf,NULL,0);
 | 
|---|
| 3905 |         if (smb_encrypt && (iosize < 0x4000 || iosize > 0xFC00)) {
 | 
|---|
| 3906 |                 d_printf("iosize out of range for encrypted "
 | 
|---|
| 3907 |                         "connection (min = 16384 (0x4000), "
 | 
|---|
| 3908 |                         "max = 130048 (0x1FC00)");
 | 
|---|
| 3909 |                 return 1;
 | 
|---|
| 3910 |         } else if (!smb_encrypt && (iosize < 0x4000 || iosize > 0xFFFF00)) {
 | 
|---|
| 3911 |                 d_printf("iosize out of range (min = 16384 (0x4000), "
 | 
|---|
| 3912 |                         "max = 16776960 (0xFFFF00)");
 | 
|---|
| 3913 |                 return 1;
 | 
|---|
| 3914 |         }
 | 
|---|
| 3915 | 
 | 
|---|
| 3916 |         io_bufsize = iosize;
 | 
|---|
| 3917 |         d_printf("iosize is now %d\n", io_bufsize);
 | 
|---|
| 3918 |         return 0;
 | 
|---|
| 3919 | }
 | 
|---|
| 3920 | 
 | 
|---|
| 3921 | 
 | 
|---|
| 3922 | /* Some constants for completing filename arguments */
 | 
|---|
| 3923 | 
 | 
|---|
| 3924 | #define COMPL_NONE        0          /* No completions */
 | 
|---|
| 3925 | #define COMPL_REMOTE      1          /* Complete remote filename */
 | 
|---|
| 3926 | #define COMPL_LOCAL       2          /* Complete local filename */
 | 
|---|
| 3927 | 
 | 
|---|
| 3928 | /* This defines the commands supported by this client.
 | 
|---|
| 3929 |  * NOTE: The "!" must be the last one in the list because it's fn pointer
 | 
|---|
| 3930 |  *       field is NULL, and NULL in that field is used in process_tok()
 | 
|---|
| 3931 |  *       (below) to indicate the end of the list.  crh
 | 
|---|
| 3932 |  */
 | 
|---|
| 3933 | static struct {
 | 
|---|
| 3934 |         const char *name;
 | 
|---|
| 3935 |         int (*fn)(void);
 | 
|---|
| 3936 |         const char *description;
 | 
|---|
| 3937 |         char compl_args[2];      /* Completion argument info */
 | 
|---|
| 3938 | } commands[] = {
 | 
|---|
| 3939 |   {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3940 |   {"allinfo",cmd_allinfo,"<file> show all available info",
 | 
|---|
| 3941 |    {COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3942 |   {"altname",cmd_altname,"<file> show alt name",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3943 |   {"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3944 |   {"blocksize",cmd_block,"blocksize <number> (default 20)",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3945 |   {"cancel",cmd_cancel,"<jobid> cancel a print queue entry",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3946 |   {"case_sensitive",cmd_setcase,"toggle the case sensitive flag to server",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3947 |   {"cd",cmd_cd,"[directory] change/report the remote directory",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3948 |   {"chmod",cmd_chmod,"<src> <mode> chmod a file using UNIX permission",{COMPL_REMOTE,COMPL_REMOTE}},
 | 
|---|
| 3949 |   {"chown",cmd_chown,"<src> <uid> <gid> chown a file using UNIX uids and gids",{COMPL_REMOTE,COMPL_REMOTE}},
 | 
|---|
| 3950 |   {"close",cmd_close,"<fid> close a file given a fid",{COMPL_REMOTE,COMPL_REMOTE}},
 | 
|---|
| 3951 |   {"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3952 |   {"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3953 |   {"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3954 |   {"echo",cmd_echo,"ping the server",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3955 |   {"exit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3956 |   {"get",cmd_get,"<remote name> [local name] get a file",{COMPL_REMOTE,COMPL_LOCAL}},
 | 
|---|
| 3957 |   {"getfacl",cmd_getfacl,"<file name> get the POSIX ACL on a file (UNIX extensions only)",{COMPL_REMOTE,COMPL_LOCAL}},
 | 
|---|
| 3958 |   {"hardlink",cmd_hardlink,"<src> <dest> create a Windows hard link",{COMPL_REMOTE,COMPL_REMOTE}},
 | 
|---|
| 3959 |   {"help",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3960 |   {"history",cmd_history,"displays the command history",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3961 |   {"iosize",cmd_iosize,"iosize <number> (default 64512)",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3962 |   {"lcd",cmd_lcd,"[directory] change/report the local current working directory",{COMPL_LOCAL,COMPL_NONE}},
 | 
|---|
| 3963 |   {"link",cmd_link,"<oldname> <newname> create a UNIX hard link",{COMPL_REMOTE,COMPL_REMOTE}},
 | 
|---|
| 3964 |   {"lock",cmd_lock,"lock <fnum> [r|w] <hex-start> <hex-len> : set a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}},
 | 
|---|
| 3965 |   {"lowercase",cmd_lowercase,"toggle lowercasing of filenames for get",{COMPL_NONE,COMPL_NONE}},  
 | 
|---|
| 3966 |   {"ls",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3967 |   {"l",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3968 |   {"mask",cmd_select,"<mask> mask all filenames against this",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3969 |   {"md",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3970 |   {"mget",cmd_mget,"<mask> get all the matching files",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3971 |   {"mkdir",cmd_mkdir,"<directory> make a directory",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3972 |   {"more",cmd_more,"<remote name> view a remote file with your pager",{COMPL_REMOTE,COMPL_NONE}},  
 | 
|---|
| 3973 |   {"mput",cmd_mput,"<mask> put all matching files",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3974 |   {"newer",cmd_newer,"<file> only mget files newer than the specified local file",{COMPL_LOCAL,COMPL_NONE}},
 | 
|---|
| 3975 |   {"open",cmd_open,"<mask> open a file",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3976 |   {"posix", cmd_posix, "turn on all POSIX capabilities", {COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3977 |   {"posix_encrypt",cmd_posix_encrypt,"<domain> <user> <password> start up transport encryption",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3978 |   {"posix_open",cmd_posix_open,"<name> 0<mode> open_flags mode open a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3979 |   {"posix_mkdir",cmd_posix_mkdir,"<name> 0<mode> creates a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3980 |   {"posix_rmdir",cmd_posix_rmdir,"<name> removes a directory using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3981 |   {"posix_unlink",cmd_posix_unlink,"<name> removes a file using POSIX interface",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3982 |   {"print",cmd_print,"<file name> print a file",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3983 |   {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput",{COMPL_NONE,COMPL_NONE}},  
 | 
|---|
| 3984 |   {"put",cmd_put,"<local name> [remote name] put a file",{COMPL_LOCAL,COMPL_REMOTE}},
 | 
|---|
| 3985 |   {"pwd",cmd_pwd,"show current remote directory (same as 'cd' with no args)",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3986 |   {"q",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3987 |   {"queue",cmd_queue,"show the print queue",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3988 |   {"quit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3989 |   {"readlink",cmd_readlink,"filename Do a UNIX extensions readlink call on a symlink",{COMPL_REMOTE,COMPL_REMOTE}},
 | 
|---|
| 3990 |   {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3991 |   {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},  
 | 
|---|
| 3992 |   {"reget",cmd_reget,"<remote name> [local name] get a file restarting at end of local file",{COMPL_REMOTE,COMPL_LOCAL}},
 | 
|---|
| 3993 |   {"rename",cmd_rename,"<src> <dest> rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
 | 
|---|
| 3994 |   {"reput",cmd_reput,"<local name> [remote name] put a file restarting at end of remote file",{COMPL_LOCAL,COMPL_REMOTE}},
 | 
|---|
| 3995 |   {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3996 |   {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 3997 |   {"showacls",cmd_showacls,"toggle if ACLs are shown or not",{COMPL_NONE,COMPL_NONE}},  
 | 
|---|
| 3998 |   {"setmode",cmd_setmode,"filename <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 3999 |   {"stat",cmd_stat,"filename Do a UNIX extensions stat call on a file",{COMPL_REMOTE,COMPL_REMOTE}},
 | 
|---|
| 4000 |   {"symlink",cmd_symlink,"<oldname> <newname> create a UNIX symlink",{COMPL_REMOTE,COMPL_REMOTE}},
 | 
|---|
| 4001 |   {"tar",cmd_tar,"tar <c|x>[IXFqbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 4002 |   {"tarmode",cmd_tarmode,"<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 4003 |   {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 4004 |   {"unlock",cmd_unlock,"unlock <fnum> <hex-start> <hex-len> : remove a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}},
 | 
|---|
| 4005 |   {"volume",cmd_volume,"print the volume name",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 4006 |   {"vuid",cmd_vuid,"change current vuid",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 4007 |   {"wdel",cmd_wdel,"<attrib> <mask> wildcard delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 4008 |   {"logon",cmd_logon,"establish new logon",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 4009 |   {"listconnect",cmd_list_connect,"list open connections",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 4010 |   {"showconnect",cmd_show_connect,"display the current active connection",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 4011 |   {"..",cmd_cd_oneup,"change the remote directory (up one level)",{COMPL_REMOTE,COMPL_NONE}},
 | 
|---|
| 4012 | 
 | 
|---|
| 4013 |   /* Yes, this must be here, see crh's comment above. */
 | 
|---|
| 4014 |   {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
 | 
|---|
| 4015 |   {NULL,NULL,NULL,{COMPL_NONE,COMPL_NONE}}
 | 
|---|
| 4016 | };
 | 
|---|
| 4017 | 
 | 
|---|
| 4018 | /*******************************************************************
 | 
|---|
| 4019 |  Lookup a command string in the list of commands, including
 | 
|---|
| 4020 |  abbreviations.
 | 
|---|
| 4021 | ******************************************************************/
 | 
|---|
| 4022 | 
 | 
|---|
| 4023 | static int process_tok(char *tok)
 | 
|---|
| 4024 | {
 | 
|---|
| 4025 |         int i = 0, matches = 0;
 | 
|---|
| 4026 |         int cmd=0;
 | 
|---|
| 4027 |         int tok_len = strlen(tok);
 | 
|---|
| 4028 | 
 | 
|---|
| 4029 |         while (commands[i].fn != NULL) {
 | 
|---|
| 4030 |                 if (strequal(commands[i].name,tok)) {
 | 
|---|
| 4031 |                         matches = 1;
 | 
|---|
| 4032 |                         cmd = i;
 | 
|---|
| 4033 |                         break;
 | 
|---|
| 4034 |                 } else if (strnequal(commands[i].name, tok, tok_len)) {
 | 
|---|
| 4035 |                         matches++;
 | 
|---|
| 4036 |                         cmd = i;
 | 
|---|
| 4037 |                 }
 | 
|---|
| 4038 |                 i++;
 | 
|---|
| 4039 |         }
 | 
|---|
| 4040 | 
 | 
|---|
| 4041 |         if (matches == 0)
 | 
|---|
| 4042 |                 return(-1);
 | 
|---|
| 4043 |         else if (matches == 1)
 | 
|---|
| 4044 |                 return(cmd);
 | 
|---|
| 4045 |         else
 | 
|---|
| 4046 |                 return(-2);
 | 
|---|
| 4047 | }
 | 
|---|
| 4048 | 
 | 
|---|
| 4049 | /****************************************************************************
 | 
|---|
| 4050 |  Help.
 | 
|---|
| 4051 | ****************************************************************************/
 | 
|---|
| 4052 | 
 | 
|---|
| 4053 | static int cmd_help(void)
 | 
|---|
| 4054 | {
 | 
|---|
| 4055 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 4056 |         int i=0,j;
 | 
|---|
| 4057 |         char *buf;
 | 
|---|
| 4058 | 
 | 
|---|
| 4059 |         if (next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
 | 
|---|
| 4060 |                 if ((i = process_tok(buf)) >= 0)
 | 
|---|
| 4061 |                         d_printf("HELP %s:\n\t%s\n\n",
 | 
|---|
| 4062 |                                 commands[i].name,commands[i].description);
 | 
|---|
| 4063 |         } else {
 | 
|---|
| 4064 |                 while (commands[i].description) {
 | 
|---|
| 4065 |                         for (j=0; commands[i].description && (j<5); j++) {
 | 
|---|
| 4066 |                                 d_printf("%-15s",commands[i].name);
 | 
|---|
| 4067 |                                 i++;
 | 
|---|
| 4068 |                         }
 | 
|---|
| 4069 |                         d_printf("\n");
 | 
|---|
| 4070 |                 }
 | 
|---|
| 4071 |         }
 | 
|---|
| 4072 |         return 0;
 | 
|---|
| 4073 | }
 | 
|---|
| 4074 | 
 | 
|---|
| 4075 | /****************************************************************************
 | 
|---|
| 4076 |  Process a -c command string.
 | 
|---|
| 4077 | ****************************************************************************/
 | 
|---|
| 4078 | 
 | 
|---|
| 4079 | static int process_command_string(const char *cmd_in)
 | 
|---|
| 4080 | {
 | 
|---|
| 4081 |         TALLOC_CTX *ctx = talloc_tos();
 | 
|---|
| 4082 |         char *cmd = talloc_strdup(ctx, cmd_in);
 | 
|---|
| 4083 |         int rc = 0;
 | 
|---|
| 4084 | 
 | 
|---|
| 4085 |         if (!cmd) {
 | 
|---|
| 4086 |                 return 1;
 | 
|---|
| 4087 |         }
 | 
|---|
| 4088 |         /* establish the connection if not already */
 | 
|---|
| 4089 | 
 | 
|---|
| 4090 |         if (!cli) {
 | 
|---|
| 4091 |                 cli = cli_cm_open(talloc_tos(), NULL,
 | 
|---|
| 4092 |                                 have_ip ? dest_ss_str : desthost,
 | 
|---|
| 4093 |                                 service, auth_info,
 | 
|---|
| 4094 |                                 true, smb_encrypt,
 | 
|---|
| 4095 |                                 max_protocol, port, name_type);
 | 
|---|
| 4096 |                 if (!cli) {
 | 
|---|
| 4097 |                         return 1;
 | 
|---|
| 4098 |                 }
 | 
|---|
| 4099 |         }
 | 
|---|
| 4100 | 
 | 
|---|
| 4101 |         while (cmd[0] != '\0')    {
 | 
|---|
| 4102 |                 char *line;
 | 
|---|
| 4103 |                 char *p;
 | 
|---|
| 4104 |                 char *tok;
 | 
|---|
| 4105 |                 int i;
 | 
|---|
| 4106 | 
 | 
|---|
| 4107 |                 if ((p = strchr_m(cmd, ';')) == 0) {
 | 
|---|
| 4108 |                         line = cmd;
 | 
|---|
| 4109 |                         cmd += strlen(cmd);
 | 
|---|
| 4110 |                 } else {
 | 
|---|
| 4111 |                         *p = '\0';
 | 
|---|
| 4112 |                         line = cmd;
 | 
|---|
| 4113 |                         cmd = p + 1;
 | 
|---|
| 4114 |                 }
 | 
|---|
| 4115 | 
 | 
|---|
| 4116 |                 /* and get the first part of the command */
 | 
|---|
| 4117 |                 cmd_ptr = line;
 | 
|---|
| 4118 |                 if (!next_token_talloc(ctx, &cmd_ptr,&tok,NULL)) {
 | 
|---|
| 4119 |                         continue;
 | 
|---|
| 4120 |                 }
 | 
|---|
| 4121 | 
 | 
|---|
| 4122 |                 if ((i = process_tok(tok)) >= 0) {
 | 
|---|
| 4123 |                         rc = commands[i].fn();
 | 
|---|
| 4124 |                 } else if (i == -2) {
 | 
|---|
| 4125 |                         d_printf("%s: command abbreviation ambiguous\n",tok);
 | 
|---|
| 4126 |                 } else {
 | 
|---|
| 4127 |                         d_printf("%s: command not found\n",tok);
 | 
|---|
| 4128 |                 }
 | 
|---|
| 4129 |         }
 | 
|---|
| 4130 | 
 | 
|---|
| 4131 |         return rc;
 | 
|---|
| 4132 | }
 | 
|---|
| 4133 | 
 | 
|---|
| 4134 | #define MAX_COMPLETIONS 100
 | 
|---|
| 4135 | 
 | 
|---|
| 4136 | typedef struct {
 | 
|---|
| 4137 |         char *dirmask;
 | 
|---|
| 4138 |         char **matches;
 | 
|---|
| 4139 |         int count, samelen;
 | 
|---|
| 4140 |         const char *text;
 | 
|---|
| 4141 |         int len;
 | 
|---|
| 4142 | } completion_remote_t;
 | 
|---|
| 4143 | 
 | 
|---|
| 4144 | static void completion_remote_filter(const char *mnt,
 | 
|---|
| 4145 |                                 file_info *f,
 | 
|---|
| 4146 |                                 const char *mask,
 | 
|---|
| 4147 |                                 void *state)
 | 
|---|
| 4148 | {
 | 
|---|
| 4149 |         completion_remote_t *info = (completion_remote_t *)state;
 | 
|---|
| 4150 | 
 | 
|---|
| 4151 |         if ((info->count < MAX_COMPLETIONS - 1) &&
 | 
|---|
| 4152 |                         (strncmp(info->text, f->name, info->len) == 0) &&
 | 
|---|
| 4153 |                         (strcmp(f->name, ".") != 0) &&
 | 
|---|
| 4154 |                         (strcmp(f->name, "..") != 0)) {
 | 
|---|
| 4155 |                 if ((info->dirmask[0] == 0) && !(f->mode & aDIR))
 | 
|---|
| 4156 |                         info->matches[info->count] = SMB_STRDUP(f->name);
 | 
|---|
| 4157 |                 else {
 | 
|---|
| 4158 |                         TALLOC_CTX *ctx = talloc_stackframe();
 | 
|---|
| 4159 |                         char *tmp;
 | 
|---|
| 4160 | 
 | 
|---|
| 4161 |                         tmp = talloc_strdup(ctx,info->dirmask);
 | 
|---|
| 4162 |                         if (!tmp) {
 | 
|---|
| 4163 |                                 TALLOC_FREE(ctx);
 | 
|---|
| 4164 |                                 return;
 | 
|---|
| 4165 |                         }
 | 
|---|
| 4166 |                         tmp = talloc_asprintf_append(tmp, "%s", f->name);
 | 
|---|
| 4167 |                         if (!tmp) {
 | 
|---|
| 4168 |                                 TALLOC_FREE(ctx);
 | 
|---|
| 4169 |                                 return;
 | 
|---|
| 4170 |                         }
 | 
|---|
| 4171 |                         if (f->mode & aDIR) {
 | 
|---|
| 4172 |                                 tmp = talloc_asprintf_append(tmp, "%s", CLI_DIRSEP_STR);
 | 
|---|
| 4173 |                         }
 | 
|---|
| 4174 |                         if (!tmp) {
 | 
|---|
| 4175 |                                 TALLOC_FREE(ctx);
 | 
|---|
| 4176 |                                 return;
 | 
|---|
| 4177 |                         }
 | 
|---|
| 4178 |                         info->matches[info->count] = SMB_STRDUP(tmp);
 | 
|---|
| 4179 |                         TALLOC_FREE(ctx);
 | 
|---|
| 4180 |                 }
 | 
|---|
| 4181 |                 if (info->matches[info->count] == NULL) {
 | 
|---|
| 4182 |                         return;
 | 
|---|
| 4183 |                 }
 | 
|---|
| 4184 |                 if (f->mode & aDIR) {
 | 
|---|
| 4185 |                         smb_readline_ca_char(0);
 | 
|---|
| 4186 |                 }
 | 
|---|
| 4187 |                 if (info->count == 1) {
 | 
|---|
| 4188 |                         info->samelen = strlen(info->matches[info->count]);
 | 
|---|
| 4189 |                 } else {
 | 
|---|
| 4190 |                         while (strncmp(info->matches[info->count],
 | 
|---|
| 4191 |                                                 info->matches[info->count-1],
 | 
|---|
| 4192 |                                                 info->samelen) != 0) {
 | 
|---|
| 4193 |                                 info->samelen--;
 | 
|---|
| 4194 |                         }
 | 
|---|
| 4195 |                 }
 | 
|---|
| 4196 |                 info->count++;
 | 
|---|
| 4197 |         }
 | 
|---|
| 4198 | }
 | 
|---|
| 4199 | 
 | 
|---|
| 4200 | static char **remote_completion(const char *text, int len)
 | 
|---|
| 4201 | {
 | 
|---|
| 4202 |         TALLOC_CTX *ctx = talloc_stackframe();
 | 
|---|
| 4203 |         char *dirmask = NULL;
 | 
|---|
| 4204 |         char *targetpath = NULL;
 | 
|---|
| 4205 |         struct cli_state *targetcli = NULL;
 | 
|---|
| 4206 |         int i;
 | 
|---|
| 4207 |         completion_remote_t info = { NULL, NULL, 1, 0, NULL, 0 };
 | 
|---|
| 4208 | 
 | 
|---|
| 4209 |         /* can't have non-static intialisation on Sun CC, so do it
 | 
|---|
| 4210 |            at run time here */
 | 
|---|
| 4211 |         info.samelen = len;
 | 
|---|
| 4212 |         info.text = text;
 | 
|---|
| 4213 |         info.len = len;
 | 
|---|
| 4214 | 
 | 
|---|
| 4215 |         info.matches = SMB_MALLOC_ARRAY(char *,MAX_COMPLETIONS);
 | 
|---|
| 4216 |         if (!info.matches) {
 | 
|---|
| 4217 |                 TALLOC_FREE(ctx);
 | 
|---|
| 4218 |                 return NULL;
 | 
|---|
| 4219 |         }
 | 
|---|
| 4220 | 
 | 
|---|
| 4221 |         /*
 | 
|---|
| 4222 |          * We're leaving matches[0] free to fill it later with the text to
 | 
|---|
| 4223 |          * display: Either the one single match or the longest common subset
 | 
|---|
| 4224 |          * of the matches.
 | 
|---|
| 4225 |          */
 | 
|---|
| 4226 |         info.matches[0] = NULL;
 | 
|---|
| 4227 |         info.count = 1;
 | 
|---|
| 4228 | 
 | 
|---|
| 4229 |         for (i = len-1; i >= 0; i--) {
 | 
|---|
| 4230 |                 if ((text[i] == '/') || (text[i] == CLI_DIRSEP_CHAR)) {
 | 
|---|
| 4231 |                         break;
 | 
|---|
| 4232 |                 }
 | 
|---|
| 4233 |         }
 | 
|---|
| 4234 | 
 | 
|---|
| 4235 |         info.text = text+i+1;
 | 
|---|
| 4236 |         info.samelen = info.len = len-i-1;
 | 
|---|
| 4237 | 
 | 
|---|
| 4238 |         if (i > 0) {
 | 
|---|
| 4239 |                 info.dirmask = SMB_MALLOC_ARRAY(char, i+2);
 | 
|---|
| 4240 |                 if (!info.dirmask) {
 | 
|---|
| 4241 |                         goto cleanup;
 | 
|---|
| 4242 |                 }
 | 
|---|
| 4243 |                 strncpy(info.dirmask, text, i+1);
 | 
|---|
| 4244 |                 info.dirmask[i+1] = 0;
 | 
|---|
| 4245 |                 dirmask = talloc_asprintf(ctx,
 | 
|---|
| 4246 |                                         "%s%*s*",
 | 
|---|
| 4247 |                                         client_get_cur_dir(),
 | 
|---|
| 4248 |                                         i-1,
 | 
|---|
| 4249 |                                         text);
 | 
|---|
| 4250 |         } else {
 | 
|---|
| 4251 |                 info.dirmask = SMB_STRDUP("");
 | 
|---|
| 4252 |                 if (!info.dirmask) {
 | 
|---|
| 4253 |                         goto cleanup;
 | 
|---|
| 4254 |                 }
 | 
|---|
| 4255 |                 dirmask = talloc_asprintf(ctx,
 | 
|---|
| 4256 |                                         "%s*",
 | 
|---|
| 4257 |                                         client_get_cur_dir());
 | 
|---|
| 4258 |         }
 | 
|---|
| 4259 |         if (!dirmask) {
 | 
|---|
| 4260 |                 goto cleanup;
 | 
|---|
| 4261 |         }
 | 
|---|
| 4262 | 
 | 
|---|
| 4263 |         if (!cli_resolve_path(ctx, "", auth_info, cli, dirmask, &targetcli, &targetpath)) {
 | 
|---|
| 4264 |                 goto cleanup;
 | 
|---|
| 4265 |         }
 | 
|---|
| 4266 |         if (cli_list(targetcli, targetpath, aDIR | aSYSTEM | aHIDDEN,
 | 
|---|
| 4267 |                                 completion_remote_filter, (void *)&info) < 0) {
 | 
|---|
| 4268 |                 goto cleanup;
 | 
|---|
| 4269 |         }
 | 
|---|
| 4270 | 
 | 
|---|
| 4271 |         if (info.count == 1) {
 | 
|---|
| 4272 |                 /*
 | 
|---|
| 4273 |                  * No matches at all, NULL indicates there is nothing
 | 
|---|
| 4274 |                  */
 | 
|---|
| 4275 |                 SAFE_FREE(info.matches[0]);
 | 
|---|
| 4276 |                 SAFE_FREE(info.matches);
 | 
|---|
| 4277 |                 TALLOC_FREE(ctx);
 | 
|---|
| 4278 |                 return NULL;
 | 
|---|
| 4279 |         }
 | 
|---|
| 4280 | 
 | 
|---|
| 4281 |         if (info.count == 2) {
 | 
|---|
| 4282 |                 /*
 | 
|---|
| 4283 |                  * Exactly one match in matches[1], indicate this is the one
 | 
|---|
| 4284 |                  * in matches[0].
 | 
|---|
| 4285 |                  */
 | 
|---|
| 4286 |                 info.matches[0] = info.matches[1];
 | 
|---|
| 4287 |                 info.matches[1] = NULL;
 | 
|---|
| 4288 |                 info.count -= 1;
 | 
|---|
| 4289 |                 TALLOC_FREE(ctx);
 | 
|---|
| 4290 |                 return info.matches;
 | 
|---|
| 4291 |         }
 | 
|---|
| 4292 | 
 | 
|---|
| 4293 |         /*
 | 
|---|
| 4294 |          * We got more than one possible match, set the result to the maximum
 | 
|---|
| 4295 |          * common subset
 | 
|---|
| 4296 |          */
 | 
|---|
| 4297 | 
 | 
|---|
| 4298 |         info.matches[0] = SMB_STRNDUP(info.matches[1], info.samelen);
 | 
|---|
| 4299 |         info.matches[info.count] = NULL;
 | 
|---|
| 4300 |         return info.matches;
 | 
|---|
| 4301 | 
 | 
|---|
| 4302 | cleanup:
 | 
|---|
| 4303 |         for (i = 0; i < info.count; i++) {
 | 
|---|
| 4304 |                 SAFE_FREE(info.matches[i]);
 | 
|---|
| 4305 |         }
 | 
|---|
| 4306 |         SAFE_FREE(info.matches);
 | 
|---|
| 4307 |         SAFE_FREE(info.dirmask);
 | 
|---|
| 4308 |         TALLOC_FREE(ctx);
 | 
|---|
| 4309 |         return NULL;
 | 
|---|
| 4310 | }
 | 
|---|
| 4311 | 
 | 
|---|
| 4312 | static char **completion_fn(const char *text, int start, int end)
 | 
|---|
| 4313 | {
 | 
|---|
| 4314 |         smb_readline_ca_char(' ');
 | 
|---|
| 4315 | 
 | 
|---|
| 4316 |         if (start) {
 | 
|---|
| 4317 |                 const char *buf, *sp;
 | 
|---|
| 4318 |                 int i;
 | 
|---|
| 4319 |                 char compl_type;
 | 
|---|
| 4320 | 
 | 
|---|
| 4321 |                 buf = smb_readline_get_line_buffer();
 | 
|---|
| 4322 |                 if (buf == NULL)
 | 
|---|
| 4323 |                         return NULL;
 | 
|---|
| 4324 | 
 | 
|---|
| 4325 |                 sp = strchr(buf, ' ');
 | 
|---|
| 4326 |                 if (sp == NULL)
 | 
|---|
| 4327 |                         return NULL;
 | 
|---|
| 4328 | 
 | 
|---|
| 4329 |                 for (i = 0; commands[i].name; i++) {
 | 
|---|
| 4330 |                         if ((strncmp(commands[i].name, buf, sp - buf) == 0) &&
 | 
|---|
| 4331 |                             (commands[i].name[sp - buf] == 0)) {
 | 
|---|
| 4332 |                                 break;
 | 
|---|
| 4333 |                         }
 | 
|---|
| 4334 |                 }
 | 
|---|
| 4335 |                 if (commands[i].name == NULL)
 | 
|---|
| 4336 |                         return NULL;
 | 
|---|
| 4337 | 
 | 
|---|
| 4338 |                 while (*sp == ' ')
 | 
|---|
| 4339 |                         sp++;
 | 
|---|
| 4340 | 
 | 
|---|
| 4341 |                 if (sp == (buf + start))
 | 
|---|
| 4342 |                         compl_type = commands[i].compl_args[0];
 | 
|---|
| 4343 |                 else
 | 
|---|
| 4344 |                         compl_type = commands[i].compl_args[1];
 | 
|---|
| 4345 | 
 | 
|---|
| 4346 |                 if (compl_type == COMPL_REMOTE)
 | 
|---|
| 4347 |                         return remote_completion(text, end - start);
 | 
|---|
| 4348 |                 else /* fall back to local filename completion */
 | 
|---|
| 4349 |                         return NULL;
 | 
|---|
| 4350 |         } else {
 | 
|---|
| 4351 |                 char **matches;
 | 
|---|
| 4352 |                 int i, len, samelen = 0, count=1;
 | 
|---|
| 4353 | 
 | 
|---|
| 4354 |                 matches = SMB_MALLOC_ARRAY(char *, MAX_COMPLETIONS);
 | 
|---|
| 4355 |                 if (!matches) {
 | 
|---|
| 4356 |                         return NULL;
 | 
|---|
| 4357 |                 }
 | 
|---|
| 4358 |                 matches[0] = NULL;
 | 
|---|
| 4359 | 
 | 
|---|
| 4360 |                 len = strlen(text);
 | 
|---|
| 4361 |                 for (i=0;commands[i].fn && count < MAX_COMPLETIONS-1;i++) {
 | 
|---|
| 4362 |                         if (strncmp(text, commands[i].name, len) == 0) {
 | 
|---|
| 4363 |                                 matches[count] = SMB_STRDUP(commands[i].name);
 | 
|---|
| 4364 |                                 if (!matches[count])
 | 
|---|
| 4365 |                                         goto cleanup;
 | 
|---|
| 4366 |                                 if (count == 1)
 | 
|---|
| 4367 |                                         samelen = strlen(matches[count]);
 | 
|---|
| 4368 |                                 else
 | 
|---|
| 4369 |                                         while (strncmp(matches[count], matches[count-1], samelen) != 0)
 | 
|---|
| 4370 |                                                 samelen--;
 | 
|---|
| 4371 |                                 count++;
 | 
|---|
| 4372 |                         }
 | 
|---|
| 4373 |                 }
 | 
|---|
| 4374 | 
 | 
|---|
| 4375 |                 switch (count) {
 | 
|---|
| 4376 |                 case 0: /* should never happen */
 | 
|---|
| 4377 |                 case 1:
 | 
|---|
| 4378 |                         goto cleanup;
 | 
|---|
| 4379 |                 case 2:
 | 
|---|
| 4380 |                         matches[0] = SMB_STRDUP(matches[1]);
 | 
|---|
| 4381 |                         break;
 | 
|---|
| 4382 |                 default:
 | 
|---|
| 4383 |                         matches[0] = (char *)SMB_MALLOC(samelen+1);
 | 
|---|
| 4384 |                         if (!matches[0])
 | 
|---|
| 4385 |                                 goto cleanup;
 | 
|---|
| 4386 |                         strncpy(matches[0], matches[1], samelen);
 | 
|---|
| 4387 |                         matches[0][samelen] = 0;
 | 
|---|
| 4388 |                 }
 | 
|---|
| 4389 |                 matches[count] = NULL;
 | 
|---|
| 4390 |                 return matches;
 | 
|---|
| 4391 | 
 | 
|---|
| 4392 | cleanup:
 | 
|---|
| 4393 |                 for (i = 0; i < count; i++)
 | 
|---|
| 4394 |                         free(matches[i]);
 | 
|---|
| 4395 | 
 | 
|---|
| 4396 |                 free(matches);
 | 
|---|
| 4397 |                 return NULL;
 | 
|---|
| 4398 |         }
 | 
|---|
| 4399 | }
 | 
|---|
| 4400 | 
 | 
|---|
| 4401 | static bool finished;
 | 
|---|
| 4402 | 
 | 
|---|
| 4403 | /****************************************************************************
 | 
|---|
| 4404 |  Make sure we swallow keepalives during idle time.
 | 
|---|
| 4405 | ****************************************************************************/
 | 
|---|
| 4406 | 
 | 
|---|
| 4407 | static void readline_callback(void)
 | 
|---|
| 4408 | {
 | 
|---|
| 4409 |         fd_set fds;
 | 
|---|
| 4410 |         struct timeval timeout;
 | 
|---|
| 4411 |         static time_t last_t;
 | 
|---|
| 4412 |         time_t t;
 | 
|---|
| 4413 | 
 | 
|---|
| 4414 |         t = time(NULL);
 | 
|---|
| 4415 | 
 | 
|---|
| 4416 |         if (t - last_t < 5)
 | 
|---|
| 4417 |                 return;
 | 
|---|
| 4418 | 
 | 
|---|
| 4419 |         last_t = t;
 | 
|---|
| 4420 | 
 | 
|---|
| 4421 |  again:
 | 
|---|
| 4422 | 
 | 
|---|
| 4423 |         if (cli->fd == -1)
 | 
|---|
| 4424 |                 return;
 | 
|---|
| 4425 | 
 | 
|---|
| 4426 |         FD_ZERO(&fds);
 | 
|---|
| 4427 |         FD_SET(cli->fd,&fds);
 | 
|---|
| 4428 | 
 | 
|---|
| 4429 |         timeout.tv_sec = 0;
 | 
|---|
| 4430 |         timeout.tv_usec = 0;
 | 
|---|
| 4431 |         sys_select_intr(cli->fd+1,&fds,NULL,NULL,&timeout);
 | 
|---|
| 4432 | 
 | 
|---|
| 4433 |         /* We deliberately use receive_smb_raw instead of
 | 
|---|
| 4434 |            client_receive_smb as we want to receive
 | 
|---|
| 4435 |            session keepalives and then drop them here.
 | 
|---|
| 4436 |         */
 | 
|---|
| 4437 |         if (FD_ISSET(cli->fd,&fds)) {
 | 
|---|
| 4438 |                 NTSTATUS status;
 | 
|---|
| 4439 |                 size_t len;
 | 
|---|
| 4440 | 
 | 
|---|
| 4441 |                 set_smb_read_error(&cli->smb_rw_error, SMB_READ_OK);
 | 
|---|
| 4442 | 
 | 
|---|
| 4443 |                 status = receive_smb_raw(cli->fd, cli->inbuf, cli->bufsize, 0, 0, &len);
 | 
|---|
| 4444 | 
 | 
|---|
| 4445 |                 if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 4446 |                         DEBUG(0, ("Read from server failed, maybe it closed "
 | 
|---|
| 4447 |                                   "the connection\n"));
 | 
|---|
| 4448 | 
 | 
|---|
| 4449 |                         finished = true;
 | 
|---|
| 4450 |                         smb_readline_done();
 | 
|---|
| 4451 |                         if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE)) {
 | 
|---|
| 4452 |                                 set_smb_read_error(&cli->smb_rw_error,
 | 
|---|
| 4453 |                                                    SMB_READ_EOF);
 | 
|---|
| 4454 |                                 return;
 | 
|---|
| 4455 |                         }
 | 
|---|
| 4456 | 
 | 
|---|
| 4457 |                         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
 | 
|---|
| 4458 |                                 set_smb_read_error(&cli->smb_rw_error,
 | 
|---|
| 4459 |                                                    SMB_READ_TIMEOUT);
 | 
|---|
| 4460 |                                 return;
 | 
|---|
| 4461 |                         }
 | 
|---|
| 4462 | 
 | 
|---|
| 4463 |                         set_smb_read_error(&cli->smb_rw_error, SMB_READ_ERROR);
 | 
|---|
| 4464 |                         return;
 | 
|---|
| 4465 |                 }
 | 
|---|
| 4466 |                 if(CVAL(cli->inbuf,0) != SMBkeepalive) {
 | 
|---|
| 4467 |                         DEBUG(0, ("Read from server "
 | 
|---|
| 4468 |                                 "returned unexpected packet!\n"));
 | 
|---|
| 4469 |                         return;
 | 
|---|
| 4470 |                 }
 | 
|---|
| 4471 | 
 | 
|---|
| 4472 |                 goto again;
 | 
|---|
| 4473 |         }
 | 
|---|
| 4474 | 
 | 
|---|
| 4475 |         /* Ping the server to keep the connection alive using SMBecho. */
 | 
|---|
| 4476 |         {
 | 
|---|
| 4477 |                 NTSTATUS status;
 | 
|---|
| 4478 |                 unsigned char garbage[16];
 | 
|---|
| 4479 |                 memset(garbage, 0xf0, sizeof(garbage));
 | 
|---|
| 4480 |                 status = cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage)));
 | 
|---|
| 4481 | 
 | 
|---|
| 4482 |                 if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 4483 |                         DEBUG(0, ("SMBecho failed. Maybe server has closed "
 | 
|---|
| 4484 |                                 "the connection\n"));
 | 
|---|
| 4485 |                         finished = true;
 | 
|---|
| 4486 |                         smb_readline_done();
 | 
|---|
| 4487 |                 }
 | 
|---|
| 4488 |         }
 | 
|---|
| 4489 | }
 | 
|---|
| 4490 | 
 | 
|---|
| 4491 | /****************************************************************************
 | 
|---|
| 4492 |  Process commands on stdin.
 | 
|---|
| 4493 | ****************************************************************************/
 | 
|---|
| 4494 | 
 | 
|---|
| 4495 | static int process_stdin(void)
 | 
|---|
| 4496 | {
 | 
|---|
| 4497 |         int rc = 0;
 | 
|---|
| 4498 | 
 | 
|---|
| 4499 |         while (!finished) {
 | 
|---|
| 4500 |                 TALLOC_CTX *frame = talloc_stackframe();
 | 
|---|
| 4501 |                 char *tok = NULL;
 | 
|---|
| 4502 |                 char *the_prompt = NULL;
 | 
|---|
| 4503 |                 char *line = NULL;
 | 
|---|
| 4504 |                 int i;
 | 
|---|
| 4505 | 
 | 
|---|
| 4506 |                 /* display a prompt */
 | 
|---|
| 4507 |                 if (asprintf(&the_prompt, "smb: %s> ", client_get_cur_dir()) < 0) {
 | 
|---|
| 4508 |                         TALLOC_FREE(frame);
 | 
|---|
| 4509 |                         break;
 | 
|---|
| 4510 |                 }
 | 
|---|
| 4511 |                 line = smb_readline(the_prompt, readline_callback, completion_fn);
 | 
|---|
| 4512 |                 SAFE_FREE(the_prompt);
 | 
|---|
| 4513 |                 if (!line) {
 | 
|---|
| 4514 |                         TALLOC_FREE(frame);
 | 
|---|
| 4515 |                         break;
 | 
|---|
| 4516 |                 }
 | 
|---|
| 4517 | 
 | 
|---|
| 4518 |                 /* special case - first char is ! */
 | 
|---|
| 4519 |                 if (*line == '!') {
 | 
|---|
| 4520 |                         if (system(line + 1) == -1) {
 | 
|---|
| 4521 |                                 d_printf("system() command %s failed.\n",
 | 
|---|
| 4522 |                                         line+1);
 | 
|---|
| 4523 |                         }
 | 
|---|
| 4524 |                         SAFE_FREE(line);
 | 
|---|
| 4525 |                         TALLOC_FREE(frame);
 | 
|---|
| 4526 |                         continue;
 | 
|---|
| 4527 |                 }
 | 
|---|
| 4528 | 
 | 
|---|
| 4529 |                 /* and get the first part of the command */
 | 
|---|
| 4530 |                 cmd_ptr = line;
 | 
|---|
| 4531 |                 if (!next_token_talloc(frame, &cmd_ptr,&tok,NULL)) {
 | 
|---|
| 4532 |                         TALLOC_FREE(frame);
 | 
|---|
| 4533 |                         SAFE_FREE(line);
 | 
|---|
| 4534 |                         continue;
 | 
|---|
| 4535 |                 }
 | 
|---|
| 4536 | 
 | 
|---|
| 4537 |                 if ((i = process_tok(tok)) >= 0) {
 | 
|---|
| 4538 |                         rc = commands[i].fn();
 | 
|---|
| 4539 |                 } else if (i == -2) {
 | 
|---|
| 4540 |                         d_printf("%s: command abbreviation ambiguous\n",tok);
 | 
|---|
| 4541 |                 } else {
 | 
|---|
| 4542 |                         d_printf("%s: command not found\n",tok);
 | 
|---|
| 4543 |                 }
 | 
|---|
| 4544 |                 SAFE_FREE(line);
 | 
|---|
| 4545 |                 TALLOC_FREE(frame);
 | 
|---|
| 4546 |         }
 | 
|---|
| 4547 |         return rc;
 | 
|---|
| 4548 | }
 | 
|---|
| 4549 | 
 | 
|---|
| 4550 | /****************************************************************************
 | 
|---|
| 4551 |  Process commands from the client.
 | 
|---|
| 4552 | ****************************************************************************/
 | 
|---|
| 4553 | 
 | 
|---|
| 4554 | static int process(const char *base_directory)
 | 
|---|
| 4555 | {
 | 
|---|
| 4556 |         int rc = 0;
 | 
|---|
| 4557 | 
 | 
|---|
| 4558 |         cli = cli_cm_open(talloc_tos(), NULL,
 | 
|---|
| 4559 |                         have_ip ? dest_ss_str : desthost,
 | 
|---|
| 4560 |                         service, auth_info, true, smb_encrypt,
 | 
|---|
| 4561 |                         max_protocol, port, name_type);
 | 
|---|
| 4562 |         if (!cli) {
 | 
|---|
| 4563 |                 return 1;
 | 
|---|
| 4564 |         }
 | 
|---|
| 4565 | 
 | 
|---|
| 4566 |         if (base_directory && *base_directory) {
 | 
|---|
| 4567 |                 rc = do_cd(base_directory);
 | 
|---|
| 4568 |                 if (rc) {
 | 
|---|
| 4569 |                         cli_shutdown(cli);
 | 
|---|
| 4570 |                         return rc;
 | 
|---|
| 4571 |                 }
 | 
|---|
| 4572 |         }
 | 
|---|
| 4573 | 
 | 
|---|
| 4574 |         if (cmdstr) {
 | 
|---|
| 4575 |                 rc = process_command_string(cmdstr);
 | 
|---|
| 4576 |         } else {
 | 
|---|
| 4577 |                 process_stdin();
 | 
|---|
| 4578 |         }
 | 
|---|
| 4579 | 
 | 
|---|
| 4580 |         cli_shutdown(cli);
 | 
|---|
| 4581 |         return rc;
 | 
|---|
| 4582 | }
 | 
|---|
| 4583 | 
 | 
|---|
| 4584 | /****************************************************************************
 | 
|---|
| 4585 |  Handle a -L query.
 | 
|---|
| 4586 | ****************************************************************************/
 | 
|---|
| 4587 | 
 | 
|---|
| 4588 | static int do_host_query(const char *query_host)
 | 
|---|
| 4589 | {
 | 
|---|
| 4590 |         cli = cli_cm_open(talloc_tos(), NULL,
 | 
|---|
| 4591 |                         query_host, "IPC$", auth_info, true, smb_encrypt,
 | 
|---|
| 4592 |                         max_protocol, port, name_type);
 | 
|---|
| 4593 |         if (!cli)
 | 
|---|
| 4594 |                 return 1;
 | 
|---|
| 4595 | 
 | 
|---|
| 4596 |         browse_host(true);
 | 
|---|
| 4597 | 
 | 
|---|
| 4598 |         /* Ensure that the host can do IPv4 */
 | 
|---|
| 4599 | 
 | 
|---|
| 4600 |         if (!interpret_addr(query_host)) {
 | 
|---|
| 4601 |                 struct sockaddr_storage ss;
 | 
|---|
| 4602 |                 if (interpret_string_addr(&ss, query_host, 0) &&
 | 
|---|
| 4603 |                                 (ss.ss_family != AF_INET)) {
 | 
|---|
| 4604 |                         d_printf("%s is an IPv6 address -- no workgroup available\n",
 | 
|---|
| 4605 |                                 query_host);
 | 
|---|
| 4606 |                         return 1;
 | 
|---|
| 4607 |                 }
 | 
|---|
| 4608 |         }
 | 
|---|
| 4609 | 
 | 
|---|
| 4610 |         if (port != 139) {
 | 
|---|
| 4611 | 
 | 
|---|
| 4612 |                 /* Workgroups simply don't make sense over anything
 | 
|---|
| 4613 |                    else but port 139... */
 | 
|---|
| 4614 | 
 | 
|---|
| 4615 |                 cli_shutdown(cli);
 | 
|---|
| 4616 |                 cli = cli_cm_open(talloc_tos(), NULL,
 | 
|---|
| 4617 |                                 query_host, "IPC$", auth_info, true, smb_encrypt,
 | 
|---|
| 4618 |                                 max_protocol, 139, name_type);
 | 
|---|
| 4619 |         }
 | 
|---|
| 4620 | 
 | 
|---|
| 4621 |         if (cli == NULL) {
 | 
|---|
| 4622 |                 d_printf("NetBIOS over TCP disabled -- no workgroup available\n");
 | 
|---|
| 4623 |                 return 1;
 | 
|---|
| 4624 |         }
 | 
|---|
| 4625 | 
 | 
|---|
| 4626 |         list_servers(lp_workgroup());
 | 
|---|
| 4627 | 
 | 
|---|
| 4628 |         cli_shutdown(cli);
 | 
|---|
| 4629 | 
 | 
|---|
| 4630 |         return(0);
 | 
|---|
| 4631 | }
 | 
|---|
| 4632 | 
 | 
|---|
| 4633 | /****************************************************************************
 | 
|---|
| 4634 |  Handle a tar operation.
 | 
|---|
| 4635 | ****************************************************************************/
 | 
|---|
| 4636 | 
 | 
|---|
| 4637 | static int do_tar_op(const char *base_directory)
 | 
|---|
| 4638 | {
 | 
|---|
| 4639 |         int ret;
 | 
|---|
| 4640 | 
 | 
|---|
| 4641 |         /* do we already have a connection? */
 | 
|---|
| 4642 |         if (!cli) {
 | 
|---|
| 4643 |                 cli = cli_cm_open(talloc_tos(), NULL,
 | 
|---|
| 4644 |                         have_ip ? dest_ss_str : desthost,
 | 
|---|
| 4645 |                         service, auth_info, true, smb_encrypt,
 | 
|---|
| 4646 |                         max_protocol, port, name_type);
 | 
|---|
| 4647 |                 if (!cli)
 | 
|---|
| 4648 |                         return 1;
 | 
|---|
| 4649 |         }
 | 
|---|
| 4650 | 
 | 
|---|
| 4651 |         recurse=true;
 | 
|---|
| 4652 | 
 | 
|---|
| 4653 |         if (base_directory && *base_directory)  {
 | 
|---|
| 4654 |                 ret = do_cd(base_directory);
 | 
|---|
| 4655 |                 if (ret) {
 | 
|---|
| 4656 |                         cli_shutdown(cli);
 | 
|---|
| 4657 |                         return ret;
 | 
|---|
| 4658 |                 }
 | 
|---|
| 4659 |         }
 | 
|---|
| 4660 | 
 | 
|---|
| 4661 |         ret=process_tar();
 | 
|---|
| 4662 | 
 | 
|---|
| 4663 |         cli_shutdown(cli);
 | 
|---|
| 4664 | 
 | 
|---|
| 4665 |         return(ret);
 | 
|---|
| 4666 | }
 | 
|---|
| 4667 | 
 | 
|---|
| 4668 | /****************************************************************************
 | 
|---|
| 4669 |  Handle a message operation.
 | 
|---|
| 4670 | ****************************************************************************/
 | 
|---|
| 4671 | 
 | 
|---|
| 4672 | static int do_message_op(struct user_auth_info *a_info)
 | 
|---|
| 4673 | {
 | 
|---|
| 4674 |         struct sockaddr_storage ss;
 | 
|---|
| 4675 |         struct nmb_name called, calling;
 | 
|---|
| 4676 |         fstring server_name;
 | 
|---|
| 4677 |         char name_type_hex[10];
 | 
|---|
| 4678 |         int msg_port;
 | 
|---|
| 4679 |         NTSTATUS status;
 | 
|---|
| 4680 | 
 | 
|---|
| 4681 |         make_nmb_name(&calling, calling_name, 0x0);
 | 
|---|
| 4682 |         make_nmb_name(&called , desthost, name_type);
 | 
|---|
| 4683 | 
 | 
|---|
| 4684 |         fstrcpy(server_name, desthost);
 | 
|---|
| 4685 |         snprintf(name_type_hex, sizeof(name_type_hex), "#%X", name_type);
 | 
|---|
| 4686 |         fstrcat(server_name, name_type_hex);
 | 
|---|
| 4687 | 
 | 
|---|
| 4688 |         zero_sockaddr(&ss);
 | 
|---|
| 4689 |         if (have_ip)
 | 
|---|
| 4690 |                 ss = dest_ss;
 | 
|---|
| 4691 | 
 | 
|---|
| 4692 |         /* we can only do messages over port 139 (to windows clients at least) */
 | 
|---|
| 4693 | 
 | 
|---|
| 4694 |         msg_port = port ? port : 139;
 | 
|---|
| 4695 | 
 | 
|---|
| 4696 |         if (!(cli=cli_initialise())) {
 | 
|---|
| 4697 |                 d_printf("Connection to %s failed\n", desthost);
 | 
|---|
| 4698 |                 return 1;
 | 
|---|
| 4699 |         }
 | 
|---|
| 4700 |         cli_set_port(cli, msg_port);
 | 
|---|
| 4701 | 
 | 
|---|
| 4702 |         status = cli_connect(cli, server_name, &ss);
 | 
|---|
| 4703 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 4704 |                 d_printf("Connection to %s failed. Error %s\n", desthost, nt_errstr(status));
 | 
|---|
| 4705 |                 return 1;
 | 
|---|
| 4706 |         }
 | 
|---|
| 4707 | 
 | 
|---|
| 4708 |         if (!cli_session_request(cli, &calling, &called)) {
 | 
|---|
| 4709 |                 d_printf("session request failed\n");
 | 
|---|
| 4710 |                 cli_shutdown(cli);
 | 
|---|
| 4711 |                 return 1;
 | 
|---|
| 4712 |         }
 | 
|---|
| 4713 | 
 | 
|---|
| 4714 |         send_message(get_cmdline_auth_info_username(a_info));
 | 
|---|
| 4715 |         cli_shutdown(cli);
 | 
|---|
| 4716 | 
 | 
|---|
| 4717 |         return 0;
 | 
|---|
| 4718 | }
 | 
|---|
| 4719 | 
 | 
|---|
| 4720 | /****************************************************************************
 | 
|---|
| 4721 |   main program
 | 
|---|
| 4722 | ****************************************************************************/
 | 
|---|
| 4723 | 
 | 
|---|
| 4724 |  int main(int argc,char *argv[])
 | 
|---|
| 4725 | {
 | 
|---|
| 4726 |         char *base_directory = NULL;
 | 
|---|
| 4727 |         int opt;
 | 
|---|
| 4728 |         char *query_host = NULL;
 | 
|---|
| 4729 |         bool message = false;
 | 
|---|
| 4730 |         static const char *new_name_resolve_order = NULL;
 | 
|---|
| 4731 |         poptContext pc;
 | 
|---|
| 4732 |         char *p;
 | 
|---|
| 4733 |         int rc = 0;
 | 
|---|
| 4734 |         fstring new_workgroup;
 | 
|---|
| 4735 |         bool tar_opt = false;
 | 
|---|
| 4736 |         bool service_opt = false;
 | 
|---|
| 4737 |         struct poptOption long_options[] = {
 | 
|---|
| 4738 |                 POPT_AUTOHELP
 | 
|---|
| 4739 | 
 | 
|---|
| 4740 |                 { "name-resolve", 'R', POPT_ARG_STRING, &new_name_resolve_order, 'R', "Use these name resolution services only", "NAME-RESOLVE-ORDER" },
 | 
|---|
| 4741 |                 { "message", 'M', POPT_ARG_STRING, NULL, 'M', "Send message", "HOST" },
 | 
|---|
| 4742 |                 { "ip-address", 'I', POPT_ARG_STRING, NULL, 'I', "Use this IP to connect to", "IP" },
 | 
|---|
| 4743 |                 { "stderr", 'E', POPT_ARG_NONE, NULL, 'E', "Write messages to stderr instead of stdout" },
 | 
|---|
| 4744 |                 { "list", 'L', POPT_ARG_STRING, NULL, 'L', "Get a list of shares available on a host", "HOST" },
 | 
|---|
| 4745 |                 { "max-protocol", 'm', POPT_ARG_STRING, NULL, 'm', "Set the max protocol level", "LEVEL" },
 | 
|---|
| 4746 |                 { "tar", 'T', POPT_ARG_STRING, NULL, 'T', "Command line tar", "<c|x>IXFqgbNan" },
 | 
|---|
| 4747 |                 { "directory", 'D', POPT_ARG_STRING, NULL, 'D', "Start from directory", "DIR" },
 | 
|---|
| 4748 |                 { "command", 'c', POPT_ARG_STRING, &cmdstr, 'c', "Execute semicolon separated commands" }, 
 | 
|---|
| 4749 |                 { "send-buffer", 'b', POPT_ARG_INT, &io_bufsize, 'b', "Changes the transmit/send buffer", "BYTES" },
 | 
|---|
| 4750 |                 { "port", 'p', POPT_ARG_INT, &port, 'p', "Port to connect to", "PORT" },
 | 
|---|
| 4751 |                 { "grepable", 'g', POPT_ARG_NONE, NULL, 'g', "Produce grepable output" },
 | 
|---|
| 4752 |                 { "browse", 'B', POPT_ARG_NONE, NULL, 'B', "Browse SMB servers using DNS" },
 | 
|---|
| 4753 |                 POPT_COMMON_SAMBA
 | 
|---|
| 4754 |                 POPT_COMMON_CONNECTION
 | 
|---|
| 4755 |                 POPT_COMMON_CREDENTIALS
 | 
|---|
| 4756 |                 POPT_TABLEEND
 | 
|---|
| 4757 |         };
 | 
|---|
| 4758 |         TALLOC_CTX *frame = talloc_stackframe();
 | 
|---|
| 4759 | 
 | 
|---|
| 4760 |         if (!client_set_cur_dir("\\")) {
 | 
|---|
| 4761 |                 exit(ENOMEM);
 | 
|---|
| 4762 |         }
 | 
|---|
| 4763 | 
 | 
|---|
| 4764 |         /* initialize the workgroup name so we can determine whether or
 | 
|---|
| 4765 |            not it was set by a command line option */
 | 
|---|
| 4766 | 
 | 
|---|
| 4767 |         set_global_myworkgroup( "" );
 | 
|---|
| 4768 |         set_global_myname( "" );
 | 
|---|
| 4769 | 
 | 
|---|
| 4770 |         /* set default debug level to 1 regardless of what smb.conf sets */
 | 
|---|
| 4771 |         setup_logging( "smbclient", true );
 | 
|---|
| 4772 |         DEBUGLEVEL_CLASS[DBGC_ALL] = 1;
 | 
|---|
| 4773 |         if ((dbf = x_fdup(x_stderr))) {
 | 
|---|
| 4774 |                 x_setbuf( dbf, NULL );
 | 
|---|
| 4775 |         }
 | 
|---|
| 4776 | 
 | 
|---|
| 4777 |         load_case_tables();
 | 
|---|
| 4778 | 
 | 
|---|
| 4779 |         auth_info = user_auth_info_init(frame);
 | 
|---|
| 4780 |         if (auth_info == NULL) {
 | 
|---|
| 4781 |                 exit(1);
 | 
|---|
| 4782 |         }
 | 
|---|
| 4783 |         popt_common_set_auth_info(auth_info);
 | 
|---|
| 4784 | 
 | 
|---|
| 4785 |         /* skip argv(0) */
 | 
|---|
| 4786 |         pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, 0);
 | 
|---|
| 4787 |         poptSetOtherOptionHelp(pc, "service <password>");
 | 
|---|
| 4788 | 
 | 
|---|
| 4789 |         lp_set_in_client(true); /* Make sure that we tell lp_load we are */
 | 
|---|
| 4790 | 
 | 
|---|
| 4791 |         while ((opt = poptGetNextOpt(pc)) != -1) {
 | 
|---|
| 4792 | 
 | 
|---|
| 4793 |                 /* if the tar option has been called previouslt, now we need to eat out the leftovers */
 | 
|---|
| 4794 |                 /* I see no other way to keep things sane --SSS */
 | 
|---|
| 4795 |                 if (tar_opt == true) {
 | 
|---|
| 4796 |                         while (poptPeekArg(pc)) {
 | 
|---|
| 4797 |                                 poptGetArg(pc);
 | 
|---|
| 4798 |                         }
 | 
|---|
| 4799 |                         tar_opt = false;
 | 
|---|
| 4800 |                 }
 | 
|---|
| 4801 | 
 | 
|---|
| 4802 |                 /* if the service has not yet been specified lets see if it is available in the popt stack */
 | 
|---|
| 4803 |                 if (!service_opt && poptPeekArg(pc)) {
 | 
|---|
| 4804 |                         service = talloc_strdup(frame, poptGetArg(pc));
 | 
|---|
| 4805 |                         if (!service) {
 | 
|---|
| 4806 |                                 exit(ENOMEM);
 | 
|---|
| 4807 |                         }
 | 
|---|
| 4808 |                         service_opt = true;
 | 
|---|
| 4809 |                 }
 | 
|---|
| 4810 | 
 | 
|---|
| 4811 |                 /* if the service has already been retrieved then check if we have also a password */
 | 
|---|
| 4812 |                 if (service_opt
 | 
|---|
| 4813 |                     && (!get_cmdline_auth_info_got_pass(auth_info))
 | 
|---|
| 4814 |                     && poptPeekArg(pc)) {
 | 
|---|
| 4815 |                         set_cmdline_auth_info_password(auth_info,
 | 
|---|
| 4816 |                                                        poptGetArg(pc));
 | 
|---|
| 4817 |                 }
 | 
|---|
| 4818 | 
 | 
|---|
| 4819 |                 switch (opt) {
 | 
|---|
| 4820 |                 case 'M':
 | 
|---|
| 4821 |                         /* Messages are sent to NetBIOS name type 0x3
 | 
|---|
| 4822 |                          * (Messenger Service).  Make sure we default
 | 
|---|
| 4823 |                          * to port 139 instead of port 445. srl,crh
 | 
|---|
| 4824 |                          */
 | 
|---|
| 4825 |                         name_type = 0x03;
 | 
|---|
| 4826 |                         desthost = talloc_strdup(frame,poptGetOptArg(pc));
 | 
|---|
| 4827 |                         if (!desthost) {
 | 
|---|
| 4828 |                                 exit(ENOMEM);
 | 
|---|
| 4829 |                         }
 | 
|---|
| 4830 |                         if( !port )
 | 
|---|
| 4831 |                                 port = 139;
 | 
|---|
| 4832 |                         message = true;
 | 
|---|
| 4833 |                         break;
 | 
|---|
| 4834 |                 case 'I':
 | 
|---|
| 4835 |                         {
 | 
|---|
| 4836 |                                 if (!interpret_string_addr(&dest_ss, poptGetOptArg(pc), 0)) {
 | 
|---|
| 4837 |                                         exit(1);
 | 
|---|
| 4838 |                                 }
 | 
|---|
| 4839 |                                 have_ip = true;
 | 
|---|
| 4840 |                                 print_sockaddr(dest_ss_str, sizeof(dest_ss_str), &dest_ss);
 | 
|---|
| 4841 |                         }
 | 
|---|
| 4842 |                         break;
 | 
|---|
| 4843 |                 case 'E':
 | 
|---|
| 4844 |                         if (dbf) {
 | 
|---|
| 4845 |                                 x_fclose(dbf);
 | 
|---|
| 4846 |                         }
 | 
|---|
| 4847 |                         dbf = x_stderr;
 | 
|---|
| 4848 |                         display_set_stderr();
 | 
|---|
| 4849 |                         break;
 | 
|---|
| 4850 | 
 | 
|---|
| 4851 |                 case 'L':
 | 
|---|
| 4852 |                         query_host = talloc_strdup(frame, poptGetOptArg(pc));
 | 
|---|
| 4853 |                         if (!query_host) {
 | 
|---|
| 4854 |                                 exit(ENOMEM);
 | 
|---|
| 4855 |                         }
 | 
|---|
| 4856 |                         break;
 | 
|---|
| 4857 |                 case 'm':
 | 
|---|
| 4858 |                         max_protocol = interpret_protocol(poptGetOptArg(pc), max_protocol);
 | 
|---|
| 4859 |                         break;
 | 
|---|
| 4860 |                 case 'T':
 | 
|---|
| 4861 |                         /* We must use old option processing for this. Find the
 | 
|---|
| 4862 |                          * position of the -T option in the raw argv[]. */
 | 
|---|
| 4863 |                         {
 | 
|---|
| 4864 |                                 int i;
 | 
|---|
| 4865 |                                 for (i = 1; i < argc; i++) {
 | 
|---|
| 4866 |                                         if (strncmp("-T", argv[i],2)==0)
 | 
|---|
| 4867 |                                                 break;
 | 
|---|
| 4868 |                                 }
 | 
|---|
| 4869 |                                 i++;
 | 
|---|
| 4870 |                                 if (!tar_parseargs(argc, argv, poptGetOptArg(pc), i)) {
 | 
|---|
| 4871 |                                         poptPrintUsage(pc, stderr, 0);
 | 
|---|
| 4872 |                                         exit(1);
 | 
|---|
| 4873 |                                 }
 | 
|---|
| 4874 |                         }
 | 
|---|
| 4875 |                         /* this must be the last option, mark we have parsed it so that we know we have */
 | 
|---|
| 4876 |                         tar_opt = true;
 | 
|---|
| 4877 |                         break;
 | 
|---|
| 4878 |                 case 'D':
 | 
|---|
| 4879 |                         base_directory = talloc_strdup(frame, poptGetOptArg(pc));
 | 
|---|
| 4880 |                         if (!base_directory) {
 | 
|---|
| 4881 |                                 exit(ENOMEM);
 | 
|---|
| 4882 |                         }
 | 
|---|
| 4883 |                         break;
 | 
|---|
| 4884 |                 case 'g':
 | 
|---|
| 4885 |                         grepable=true;
 | 
|---|
| 4886 |                         break;
 | 
|---|
| 4887 |                 case 'e':
 | 
|---|
| 4888 |                         smb_encrypt=true;
 | 
|---|
| 4889 |                         break;
 | 
|---|
| 4890 |                 case 'B':
 | 
|---|
| 4891 |                         return(do_smb_browse());
 | 
|---|
| 4892 | 
 | 
|---|
| 4893 |                 }
 | 
|---|
| 4894 |         }
 | 
|---|
| 4895 | 
 | 
|---|
| 4896 |         /* We may still have some leftovers after the last popt option has been called */
 | 
|---|
| 4897 |         if (tar_opt == true) {
 | 
|---|
| 4898 |                 while (poptPeekArg(pc)) {
 | 
|---|
| 4899 |                         poptGetArg(pc);
 | 
|---|
| 4900 |                 }
 | 
|---|
| 4901 |                 tar_opt = false;
 | 
|---|
| 4902 |         }
 | 
|---|
| 4903 | 
 | 
|---|
| 4904 |         /* if the service has not yet been specified lets see if it is available in the popt stack */
 | 
|---|
| 4905 |         if (!service_opt && poptPeekArg(pc)) {
 | 
|---|
| 4906 |                 service = talloc_strdup(frame,poptGetArg(pc));
 | 
|---|
| 4907 |                 if (!service) {
 | 
|---|
| 4908 |                         exit(ENOMEM);
 | 
|---|
| 4909 |                 }
 | 
|---|
| 4910 |                 service_opt = true;
 | 
|---|
| 4911 |         }
 | 
|---|
| 4912 | 
 | 
|---|
| 4913 |         /* if the service has already been retrieved then check if we have also a password */
 | 
|---|
| 4914 |         if (service_opt
 | 
|---|
| 4915 |             && !get_cmdline_auth_info_got_pass(auth_info)
 | 
|---|
| 4916 |             && poptPeekArg(pc)) {
 | 
|---|
| 4917 |                 set_cmdline_auth_info_password(auth_info,
 | 
|---|
| 4918 |                                                poptGetArg(pc));
 | 
|---|
| 4919 |         }
 | 
|---|
| 4920 | 
 | 
|---|
| 4921 |         /*
 | 
|---|
| 4922 |          * Don't load debug level from smb.conf. It should be
 | 
|---|
| 4923 |          * set by cmdline arg or remain default (0)
 | 
|---|
| 4924 |          */
 | 
|---|
| 4925 |         AllowDebugChange = false;
 | 
|---|
| 4926 | 
 | 
|---|
| 4927 |         /* save the workgroup...
 | 
|---|
| 4928 | 
 | 
|---|
| 4929 |            FIXME!! do we need to do this for other options as well
 | 
|---|
| 4930 |            (or maybe a generic way to keep lp_load() from overwriting
 | 
|---|
| 4931 |            everything)?  */
 | 
|---|
| 4932 | 
 | 
|---|
| 4933 |         fstrcpy( new_workgroup, lp_workgroup() );
 | 
|---|
| 4934 |         calling_name = talloc_strdup(frame, global_myname() );
 | 
|---|
| 4935 |         if (!calling_name) {
 | 
|---|
| 4936 |                 exit(ENOMEM);
 | 
|---|
| 4937 |         }
 | 
|---|
| 4938 | 
 | 
|---|
| 4939 |         if ( override_logfile )
 | 
|---|
| 4940 |                 setup_logging( lp_logfile(), false );
 | 
|---|
| 4941 | 
 | 
|---|
| 4942 |         if (!lp_load(get_dyn_CONFIGFILE(),true,false,false,true)) {
 | 
|---|
| 4943 |                 fprintf(stderr, "%s: Can't load %s - run testparm to debug it\n",
 | 
|---|
| 4944 |                         argv[0], get_dyn_CONFIGFILE());
 | 
|---|
| 4945 |         }
 | 
|---|
| 4946 | 
 | 
|---|
| 4947 |         if (get_cmdline_auth_info_use_machine_account(auth_info) &&
 | 
|---|
| 4948 |             !set_cmdline_auth_info_machine_account_creds(auth_info)) {
 | 
|---|
| 4949 |                 exit(-1);
 | 
|---|
| 4950 |         }
 | 
|---|
| 4951 | 
 | 
|---|
| 4952 |         load_interfaces();
 | 
|---|
| 4953 | 
 | 
|---|
| 4954 |         if (service_opt && service) {
 | 
|---|
| 4955 |                 size_t len;
 | 
|---|
| 4956 | 
 | 
|---|
| 4957 |                 /* Convert any '/' characters in the service name to '\' characters */
 | 
|---|
| 4958 |                 string_replace(service, '/','\\');
 | 
|---|
| 4959 |                 if (count_chars(service,'\\') < 3) {
 | 
|---|
| 4960 |                         d_printf("\n%s: Not enough '\\' characters in service\n",service);
 | 
|---|
| 4961 |                         poptPrintUsage(pc, stderr, 0);
 | 
|---|
| 4962 |                         exit(1);
 | 
|---|
| 4963 |                 }
 | 
|---|
| 4964 |                 /* Remove trailing slashes */
 | 
|---|
| 4965 |                 len = strlen(service);
 | 
|---|
| 4966 |                 while(len > 0 && service[len - 1] == '\\') {
 | 
|---|
| 4967 |                         --len;
 | 
|---|
| 4968 |                         service[len] = '\0';
 | 
|---|
| 4969 |                 }
 | 
|---|
| 4970 |         }
 | 
|---|
| 4971 | 
 | 
|---|
| 4972 |         if ( strlen(new_workgroup) != 0 ) {
 | 
|---|
| 4973 |                 set_global_myworkgroup( new_workgroup );
 | 
|---|
| 4974 |         }
 | 
|---|
| 4975 | 
 | 
|---|
| 4976 |         if ( strlen(calling_name) != 0 ) {
 | 
|---|
| 4977 |                 set_global_myname( calling_name );
 | 
|---|
| 4978 |         } else {
 | 
|---|
| 4979 |                 TALLOC_FREE(calling_name);
 | 
|---|
| 4980 |                 calling_name = talloc_strdup(frame, global_myname() );
 | 
|---|
| 4981 |         }
 | 
|---|
| 4982 | 
 | 
|---|
| 4983 |         smb_encrypt = get_cmdline_auth_info_smb_encrypt(auth_info);
 | 
|---|
| 4984 |         if (!init_names()) {
 | 
|---|
| 4985 |                 fprintf(stderr, "init_names() failed\n");
 | 
|---|
| 4986 |                 exit(1);
 | 
|---|
| 4987 |         }
 | 
|---|
| 4988 | 
 | 
|---|
| 4989 |         if(new_name_resolve_order)
 | 
|---|
| 4990 |                 lp_set_name_resolve_order(new_name_resolve_order);
 | 
|---|
| 4991 | 
 | 
|---|
| 4992 |         if (!tar_type && !query_host && !service && !message) {
 | 
|---|
| 4993 |                 poptPrintUsage(pc, stderr, 0);
 | 
|---|
| 4994 |                 exit(1);
 | 
|---|
| 4995 |         }
 | 
|---|
| 4996 | 
 | 
|---|
| 4997 |         poptFreeContext(pc);
 | 
|---|
| 4998 | 
 | 
|---|
| 4999 |         DEBUG(3,("Client started (version %s).\n", samba_version_string()));
 | 
|---|
| 5000 | 
 | 
|---|
| 5001 |         /* Ensure we have a password (or equivalent). */
 | 
|---|
| 5002 |         set_cmdline_auth_info_getpass(auth_info);
 | 
|---|
| 5003 | 
 | 
|---|
| 5004 |         if (tar_type) {
 | 
|---|
| 5005 |                 if (cmdstr)
 | 
|---|
| 5006 |                         process_command_string(cmdstr);
 | 
|---|
| 5007 |                 return do_tar_op(base_directory);
 | 
|---|
| 5008 |         }
 | 
|---|
| 5009 | 
 | 
|---|
| 5010 |         if (query_host && *query_host) {
 | 
|---|
| 5011 |                 char *qhost = query_host;
 | 
|---|
| 5012 |                 char *slash;
 | 
|---|
| 5013 | 
 | 
|---|
| 5014 |                 while (*qhost == '\\' || *qhost == '/')
 | 
|---|
| 5015 |                         qhost++;
 | 
|---|
| 5016 | 
 | 
|---|
| 5017 |                 if ((slash = strchr_m(qhost, '/'))
 | 
|---|
| 5018 |                     || (slash = strchr_m(qhost, '\\'))) {
 | 
|---|
| 5019 |                         *slash = 0;
 | 
|---|
| 5020 |                 }
 | 
|---|
| 5021 | 
 | 
|---|
| 5022 |                 if ((p=strchr_m(qhost, '#'))) {
 | 
|---|
| 5023 |                         *p = 0;
 | 
|---|
| 5024 |                         p++;
 | 
|---|
| 5025 |                         sscanf(p, "%x", &name_type);
 | 
|---|
| 5026 |                 }
 | 
|---|
| 5027 | 
 | 
|---|
| 5028 |                 return do_host_query(qhost);
 | 
|---|
| 5029 |         }
 | 
|---|
| 5030 | 
 | 
|---|
| 5031 |         if (message) {
 | 
|---|
| 5032 |                 return do_message_op(auth_info);
 | 
|---|
| 5033 |         }
 | 
|---|
| 5034 | 
 | 
|---|
| 5035 |         if (process(base_directory)) {
 | 
|---|
| 5036 |                 return 1;
 | 
|---|
| 5037 |         }
 | 
|---|
| 5038 | 
 | 
|---|
| 5039 |         TALLOC_FREE(frame);
 | 
|---|
| 5040 |         return rc;
 | 
|---|
| 5041 | }
 | 
|---|