Changeset 988 for vendor/current/source3/utils/smbget.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/utils/smbget.c
r740 r988 1 1 /* 2 smbget: a wget-like utility with support for recursive downloading and3 2 smbget: a wget-like utility with support for recursive downloading of 3 smb:// urls 4 4 Copyright (C) 2003-2004 Jelmer Vernooij <jelmer@samba.org> 5 5 … … 22 22 #include "libsmbclient.h" 23 23 24 #if _FILE_OFFSET_BITS==6425 #define OFF_T_FORMAT "%lld"26 #define OFF_T_FORMAT_CAST long long27 #else28 #define OFF_T_FORMAT "%ld"29 #define OFF_T_FORMAT_CAST long30 #endif31 32 24 static int columns = 0; 33 34 static int debuglevel, update;35 static char *outputfile;36 37 25 38 26 static time_t total_start_time = 0; … … 41 29 #define SMB_MAXPATHLEN MAXPATHLEN 42 30 43 /* Number of bytes to read when checking whether local and remote file are really the same file */ 44 #define RESUME_CHECK_SIZE 512 45 #define RESUME_DOWNLOAD_OFFSET 1024 46 #define RESUME_CHECK_OFFSET RESUME_DOWNLOAD_OFFSET+RESUME_CHECK_SIZE 31 /* 32 * Number of bytes to read when checking whether local and remote file 33 * are really the same file 34 */ 35 #define RESUME_CHECK_SIZE 512 36 #define RESUME_DOWNLOAD_OFFSET 1024 37 #define RESUME_CHECK_OFFSET (RESUME_DOWNLOAD_OFFSET+RESUME_CHECK_SIZE) 47 38 /* Number of bytes to read at once */ 48 #define SMB_DEFAULT_BLOCKSIZE 64000 49 50 static const char *username = NULL, *password = NULL, *workgroup = NULL; 51 static int nonprompt = 0, quiet = 0, dots = 0, keep_permissions = 0, verbose = 0, send_stdout = 0; 52 static int blocksize = SMB_DEFAULT_BLOCKSIZE; 53 54 static int smb_download_file(const char *base, const char *name, int recursive, 55 int resume, int toplevel, char *outfile); 39 #define SMB_DEFAULT_BLOCKSIZE 64000 40 41 struct opt { 42 char *workgroup; 43 bool username_specified; 44 char *username; 45 bool password_specified; 46 char *password; 47 48 char *outputfile; 49 size_t blocksize; 50 51 bool nonprompt; 52 bool quiet; 53 bool dots; 54 bool verbose; 55 bool send_stdout; 56 bool update; 57 int debuglevel; 58 }; 59 static struct opt opt = { .blocksize = SMB_DEFAULT_BLOCKSIZE }; 60 61 static bool smb_download_file(const char *base, const char *name, 62 bool recursive, bool resume, bool toplevel, 63 char *outfile); 56 64 57 65 static int get_num_cols(void) … … 59 67 #ifdef TIOCGWINSZ 60 68 struct winsize ws; 61 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0) {69 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0) { 62 70 return 0; 63 71 } … … 66 74 #warning No support for TIOCGWINSZ 67 75 char *cols = getenv("COLUMNS"); 68 if(!cols) return 0; 76 if (!cols) { 77 return 0; 78 } 69 79 return atoi(cols); 70 80 #endif … … 85 95 snprintf(buffer, l, "%.2fkB", 1.0 * s / 1024); 86 96 } else { 87 snprintf(buffer, l, OFF_T_FORMAT"b", (OFF_T_FORMAT_CAST)s); 88 } 89 } 90 91 static void get_auth_data(const char *srv, const char *shr, char *wg, int wglen, char *un, int unlen, char *pw, int pwlen) 92 { 93 static char hasasked = 0; 94 char *wgtmp, *usertmp; 97 snprintf(buffer, l, "%jdb", (intmax_t)s); 98 } 99 } 100 101 static void get_auth_data(const char *srv, const char *shr, char *wg, int wglen, 102 char *un, int unlen, char *pw, int pwlen) 103 { 104 static bool hasasked = false; 105 static char *savedwg; 106 static char *savedun; 107 static char *savedpw; 95 108 char tmp[128]; 96 109 97 if(hasasked) return; 98 hasasked = 1; 99 100 if(!nonprompt && !username) { 110 if (hasasked) { 111 strncpy(wg, savedwg, wglen - 1); 112 strncpy(un, savedun, unlen - 1); 113 strncpy(pw, savedpw, pwlen - 1); 114 return; 115 } 116 hasasked = true; 117 118 if (!opt.nonprompt && !opt.username_specified) { 101 119 printf("Username for %s at %s [guest] ", shr, srv); 102 120 if (fgets(tmp, sizeof(tmp), stdin) == NULL) { 103 121 return; 104 122 } 105 if ((strlen(tmp) > 0) && (tmp[strlen(tmp)-1] == '\n')) { 106 tmp[strlen(tmp)-1] = '\0'; 107 } 108 strncpy(un, tmp, unlen-1); 109 } else if(username) strncpy(un, username, unlen-1); 110 111 if(!nonprompt && !password) { 112 char *prompt, *pass; 113 if (asprintf(&prompt, "Password for %s at %s: ", shr, srv) == -1) { 123 if ((strlen(tmp) > 0) && (tmp[strlen(tmp) - 1] == '\n')) { 124 tmp[strlen(tmp) - 1] = '\0'; 125 } 126 strncpy(un, tmp, unlen - 1); 127 } else if (opt.username != NULL) { 128 strncpy(un, opt.username, unlen - 1); 129 } 130 131 if (!opt.nonprompt && !opt.password_specified) { 132 char *prompt; 133 if (asprintf(&prompt, "Password for %s at %s: ", shr, srv) == 134 -1) { 114 135 return; 115 136 } 116 pass = getpass(prompt);137 (void)samba_getpass(prompt, pw, pwlen, false, false); 117 138 free(prompt); 118 strncpy(pw, pass, pwlen-1); 119 } else if(password) strncpy(pw, password, pwlen-1); 120 121 if(workgroup)strncpy(wg, workgroup, wglen-1); 122 123 wgtmp = SMB_STRNDUP(wg, wglen); 124 usertmp = SMB_STRNDUP(un, unlen); 125 if(!quiet)printf("Using workgroup %s, %s%s\n", wgtmp, *usertmp?"user ":"guest user", usertmp); 126 free(wgtmp); free(usertmp); 127 } 128 129 /* Return 1 on error, 0 on success. */ 130 131 static int smb_download_dir(const char *base, const char *name, int resume) 139 } else if (opt.password != NULL) { 140 strncpy(pw, opt.password, pwlen-1); 141 } 142 143 if (opt.workgroup != NULL) { 144 strncpy(wg, opt.workgroup, wglen-1); 145 } 146 147 /* save the values found for later */ 148 savedwg = SMB_STRDUP(wg); 149 savedun = SMB_STRDUP(un); 150 savedpw = SMB_STRDUP(pw); 151 152 if (!opt.quiet) { 153 char *wgtmp, *usertmp; 154 wgtmp = SMB_STRNDUP(wg, wglen); 155 usertmp = SMB_STRNDUP(un, unlen); 156 printf("Using workgroup %s, %s%s\n", 157 wgtmp, 158 *usertmp ? "user " : "guest user", 159 usertmp); 160 free(wgtmp); 161 free(usertmp); 162 } 163 } 164 165 static bool smb_download_dir(const char *base, const char *name, int resume) 132 166 { 133 167 char path[SMB_MAXPATHLEN]; … … 136 170 const char *relname = name; 137 171 char *tmpname; 138 struct stat remotestat; 139 int ret = 0; 140 141 snprintf(path, SMB_MAXPATHLEN-1, "%s%s%s", base, (base[0] && name[0] && name[0] != '/' && base[strlen(base)-1] != '/')?"/":"", name); 172 bool ok = false; 173 174 snprintf(path, SMB_MAXPATHLEN-1, "%s%s%s", base, 175 (base[0] && name[0] && name[0] != '/' && 176 base[strlen(base)-1] != '/') ? "/" : "", 177 name); 142 178 143 179 /* List files in directory and call smb_download_file on them */ 144 180 dirhandle = smbc_opendir(path); 145 if (dirhandle < 1) {181 if (dirhandle < 1) { 146 182 if (errno == ENOTDIR) { 147 return smb_download_file(base, name, 1, resume, 148 0, NULL); 149 } 150 fprintf(stderr, "Can't open directory %s: %s\n", path, strerror(errno)); 151 return 1; 152 } 153 154 while(*relname == '/')relname++; 183 return smb_download_file(base, name, true, resume, 184 false, NULL); 185 } 186 fprintf(stderr, "Can't open directory %s: %s\n", path, 187 strerror(errno)); 188 return false; 189 } 190 191 while (*relname == '/') { 192 relname++; 193 } 155 194 mkdir(relname, 0755); 156 195 157 196 tmpname = SMB_STRDUP(name); 158 197 159 while ((dirent = smbc_readdir(dirhandle))) {198 while ((dirent = smbc_readdir(dirhandle))) { 160 199 char *newname; 161 if(!strcmp(dirent->name, ".") || !strcmp(dirent->name, ".."))continue; 200 if (!strcmp(dirent->name, ".") || !strcmp(dirent->name, "..")) { 201 continue; 202 } 162 203 if (asprintf(&newname, "%s/%s", tmpname, dirent->name) == -1) { 163 return 1; 164 } 165 switch(dirent->smbc_type) { 204 free(tmpname); 205 return false; 206 } 207 switch (dirent->smbc_type) { 166 208 case SMBC_DIR: 167 ret= smb_download_dir(base, newname, resume);209 ok = smb_download_dir(base, newname, resume); 168 210 break; 169 211 170 212 case SMBC_WORKGROUP: 171 ret= smb_download_dir("smb://", dirent->name, resume);213 ok = smb_download_dir("smb://", dirent->name, resume); 172 214 break; 173 215 174 216 case SMBC_SERVER: 175 ret= smb_download_dir("smb://", dirent->name, resume);217 ok = smb_download_dir("smb://", dirent->name, resume); 176 218 break; 177 219 178 220 case SMBC_FILE: 179 ret = smb_download_file(base, newname, 1, resume, 0,180 NULL);221 ok = smb_download_file(base, newname, true, resume, 222 false, NULL); 181 223 break; 182 224 183 225 case SMBC_FILE_SHARE: 184 ret= smb_download_dir(base, newname, resume);226 ok = smb_download_dir(base, newname, resume); 185 227 break; 186 228 187 229 case SMBC_PRINTER_SHARE: 188 if(!quiet)printf("Ignoring printer share %s\n", dirent->name); 230 if (!opt.quiet) { 231 printf("Ignoring printer share %s\n", 232 dirent->name); 233 } 189 234 break; 190 235 191 236 case SMBC_COMMS_SHARE: 192 if(!quiet)printf("Ignoring comms share %s\n", dirent->name); 237 if (!opt.quiet) { 238 printf("Ignoring comms share %s\n", 239 dirent->name); 240 } 193 241 break; 194 242 195 243 case SMBC_IPC_SHARE: 196 if(!quiet)printf("Ignoring ipc$ share %s\n", dirent->name); 244 if (!opt.quiet) { 245 printf("Ignoring ipc$ share %s\n", 246 dirent->name); 247 } 197 248 break; 198 249 199 250 default: 200 fprintf(stderr, "Ignoring file '%s' of type '%d'\n", newname, dirent->smbc_type); 201 break; 251 fprintf(stderr, "Ignoring file '%s' of type '%d'\n", 252 newname, dirent->smbc_type); 253 break; 254 } 255 256 if (!ok) { 257 fprintf(stderr, "Failed to download %s: %s\n", 258 newname, strerror(errno)); 259 return false; 202 260 } 203 261 free(newname); … … 205 263 free(tmpname); 206 264 207 if(keep_permissions) {208 if(smbc_fstat(dirhandle, &remotestat) < 0) {209 fprintf(stderr, "Unable to get stats on %s on remote server\n", path);210 smbc_closedir(dirhandle);211 return 1;212 }213 214 if(chmod(relname, remotestat.st_mode) < 0) {215 fprintf(stderr, "Unable to change mode of local dir %s to %o\n", relname,216 (unsigned int)remotestat.st_mode);217 smbc_closedir(dirhandle);218 return 1;219 }220 }221 222 265 smbc_closedir(dirhandle); 223 return ret;266 return ok; 224 267 } 225 268 … … 228 271 static char buffer[100]; 229 272 int secs, mins, hours; 230 if (t < -1) {273 if (t < -1) { 231 274 strncpy(buffer, "Unknown", sizeof(buffer)); 232 275 return buffer; … … 236 279 mins = (int)t / 60 % 60; 237 280 hours = (int)t / (60 * 60); 238 snprintf(buffer, sizeof(buffer)-1, "%02d:%02d:%02d", hours, mins, secs); 281 snprintf(buffer, sizeof(buffer) - 1, "%02d:%02d:%02d", hours, mins, 282 secs); 239 283 return buffer; 240 284 } 241 285 242 static void print_progress(const char *name, time_t start, time_t now, off_t start_pos, off_t pos, off_t total) 286 static void print_progress(const char *name, time_t start, time_t now, 287 off_t start_pos, off_t pos, off_t total) 243 288 { 244 289 double avg = 0.0; 245 long eta = -1;290 long eta = -1; 246 291 double prcnt = 0.0; 247 292 char hpos[20], htotal[20], havg[20]; 248 293 char *status, *filename; 249 294 int len; 250 if(now - start)avg = 1.0 * (pos - start_pos) / (now - start); 295 if (now - start) { 296 avg = 1.0 * (pos - start_pos) / (now - start); 297 } 251 298 eta = (total - pos) / avg; 252 if(total)prcnt = 100.0 * pos / total; 299 if (total) { 300 prcnt = 100.0 * pos / total; 301 } 253 302 254 303 human_readable(pos, hpos, sizeof(hpos)); … … 256 305 human_readable(avg, havg, sizeof(havg)); 257 306 258 len = asprintf(&status, "%s of %s (%.2f%%) at %s/s ETA: %s", hpos, htotal, prcnt, havg, print_time(eta)); 307 len = asprintf(&status, "%s of %s (%.2f%%) at %s/s ETA: %s", hpos, 308 htotal, prcnt, havg, print_time(eta)); 259 309 if (len == -1) { 260 310 return; 261 311 } 262 312 263 if(columns) { 264 int required = strlen(name), available = columns - len - strlen("[] "); 265 if(required > available) { 266 if (asprintf(&filename, "...%s", name + required - available + 3) == -1) { 313 if (columns) { 314 int required = strlen(name), 315 available = columns - len - strlen("[] "); 316 if (required > available) { 317 if (asprintf(&filename, "...%s", 318 name + required - available + 3) == -1) { 267 319 return; 268 320 } … … 270 322 filename = SMB_STRNDUP(name, available); 271 323 } 272 } else filename = SMB_STRDUP(name); 324 } else { 325 filename = SMB_STRDUP(name); 326 } 273 327 274 328 fprintf(stderr, "\r[%s] %s", filename, status); 275 329 276 free(filename); free(status); 277 } 278 279 /* Return 1 on error, 0 on success. */ 280 281 static int smb_download_file(const char *base, const char *name, int recursive, 282 int resume, int toplevel, char *outfile) 330 free(filename); 331 free(status); 332 } 333 334 /* Return false on error, true on success. */ 335 336 static bool smb_download_file(const char *base, const char *name, 337 bool recursive, bool resume, bool toplevel, 338 char *outfile) 283 339 { 284 340 int remotehandle, localhandle; … … 288 344 char checkbuf[2][RESUME_CHECK_SIZE]; 289 345 char *readbuf = NULL; 290 off_t offset_download = 0, offset_check = 0, curpos = 0, start_offset = 0; 346 off_t offset_download = 0, offset_check = 0, curpos = 0, 347 start_offset = 0; 291 348 struct stat localstat, remotestat; 292 349 293 snprintf(path, SMB_MAXPATHLEN-1, "%s%s%s", base, (*base && *name && name[0] != '/' && base[strlen(base)-1] != '/')?"/":"", name); 350 snprintf(path, SMB_MAXPATHLEN-1, "%s%s%s", base, 351 (*base && *name && name[0] != '/' && 352 base[strlen(base)-1] != '/') ? "/" : "", 353 name); 294 354 295 355 remotehandle = smbc_open(path, O_RDONLY, 0755); 296 356 297 if(remotehandle < 0) { 298 switch(errno) { 299 case EISDIR: 300 if(!recursive) { 301 fprintf(stderr, "%s is a directory. Specify -R to download recursively\n", path); 302 return 1; 357 if (remotehandle < 0) { 358 switch (errno) { 359 case EISDIR: 360 if (!recursive) { 361 fprintf(stderr, 362 "%s is a directory. Specify -R " 363 "to download recursively\n", 364 path); 365 return false; 303 366 } 304 367 return smb_download_dir(base, name, resume); 305 368 306 369 case ENOENT: 307 fprintf(stderr, "%s can't be found on the remote server\n", path); 308 return 1; 370 fprintf(stderr, 371 "%s can't be found on the remote server\n", 372 path); 373 return false; 309 374 310 375 case ENOMEM: 311 376 fprintf(stderr, "Not enough memory\n"); 312 return 1;377 return false; 313 378 314 379 case ENODEV: 315 fprintf(stderr, "The share name used in %s does not exist\n", path); 316 return 1; 380 fprintf(stderr, 381 "The share name used in %s does not exist\n", 382 path); 383 return false; 317 384 318 385 case EACCES: 319 fprintf(stderr, "You don't have enough permissions to access %s\n", path); 320 return 1; 386 fprintf(stderr, "You don't have enough permissions " 387 "to access %s\n", 388 path); 389 return false; 321 390 322 391 default: 323 392 perror("smbc_open"); 324 return 1;325 } 326 } 327 328 if (smbc_fstat(remotehandle, &remotestat) < 0) {393 return false; 394 } 395 } 396 397 if (smbc_fstat(remotehandle, &remotestat) < 0) { 329 398 fprintf(stderr, "Can't stat %s: %s\n", path, strerror(errno)); 330 return 1; 331 } 332 333 if(outfile) newpath = outfile; 334 else if(!name[0]) { 399 return false; 400 } 401 402 if (outfile) { 403 newpath = outfile; 404 } else if (!name[0]) { 335 405 newpath = strrchr(base, '/'); 336 if(newpath)newpath++; else newpath = base; 337 } else newpath = name; 406 if (newpath) { 407 newpath++; 408 } else { 409 newpath = base; 410 } 411 } else { 412 newpath = name; 413 } 338 414 339 415 if (!toplevel && (newpath[0] == '/')) { … … 342 418 343 419 /* Open local file according to the mode */ 344 if (update) {420 if (opt.update) { 345 421 /* if it is up-to-date, skip */ 346 if (stat(newpath, &localstat) == 0 &&347 348 if (verbose)422 if (stat(newpath, &localstat) == 0 && 423 localstat.st_mtime >= remotestat.st_mtime) { 424 if (opt.verbose) { 349 425 printf("%s is up-to-date, skipping\n", newpath); 426 } 350 427 smbc_close(remotehandle); 351 return 0;428 return true; 352 429 } 353 430 /* else open it for writing and truncate if it exists */ 354 localhandle = open(newpath, O_CREAT | O_NONBLOCK | O_RDWR | O_TRUNC, 0775); 355 if(localhandle < 0) { 431 localhandle = open( 432 newpath, O_CREAT | O_NONBLOCK | O_RDWR | O_TRUNC, 0775); 433 if (localhandle < 0) { 356 434 fprintf(stderr, "Can't open %s : %s\n", newpath, 357 435 strerror(errno)); 358 436 smbc_close(remotehandle); 359 return 1;437 return false; 360 438 } 361 439 /* no offset */ 362 } else if(!send_stdout) { 363 localhandle = open(newpath, O_CREAT | O_NONBLOCK | O_RDWR | (!resume?O_EXCL:0), 0755); 364 if(localhandle < 0) { 365 fprintf(stderr, "Can't open %s: %s\n", newpath, strerror(errno)); 440 } else if (!opt.send_stdout) { 441 localhandle = open(newpath, O_CREAT | O_NONBLOCK | O_RDWR | 442 (!resume ? O_EXCL : 0), 443 0755); 444 if (localhandle < 0) { 445 fprintf(stderr, "Can't open %s: %s\n", newpath, 446 strerror(errno)); 366 447 smbc_close(remotehandle); 367 return 1;448 return false; 368 449 } 369 450 370 451 if (fstat(localhandle, &localstat) != 0) { 371 fprintf(stderr, "Can't fstat %s: %s\n", newpath, strerror(errno)); 452 fprintf(stderr, "Can't fstat %s: %s\n", newpath, 453 strerror(errno)); 372 454 smbc_close(remotehandle); 373 455 close(localhandle); 374 return 1;456 return false; 375 457 } 376 458 377 459 start_offset = localstat.st_size; 378 460 379 if(localstat.st_size && localstat.st_size == remotestat.st_size) { 380 if(verbose)fprintf(stderr, "%s is already downloaded completely.\n", path); 381 else if(!quiet)fprintf(stderr, "%s\n", path); 461 if (localstat.st_size && 462 localstat.st_size == remotestat.st_size) { 463 if (opt.verbose) { 464 fprintf(stderr, "%s is already downloaded " 465 "completely.\n", 466 path); 467 } else if (!opt.quiet) { 468 fprintf(stderr, "%s\n", path); 469 } 382 470 smbc_close(remotehandle); 383 471 close(localhandle); 384 return 0; 385 } 386 387 if(localstat.st_size > RESUME_CHECK_OFFSET && remotestat.st_size > RESUME_CHECK_OFFSET) { 388 offset_download = localstat.st_size - RESUME_DOWNLOAD_OFFSET; 472 return true; 473 } 474 475 if (localstat.st_size > RESUME_CHECK_OFFSET && 476 remotestat.st_size > RESUME_CHECK_OFFSET) { 477 offset_download = 478 localstat.st_size - RESUME_DOWNLOAD_OFFSET; 389 479 offset_check = localstat.st_size - RESUME_CHECK_OFFSET; 390 if(verbose)printf("Trying to start resume of %s at "OFF_T_FORMAT"\n" 391 "At the moment "OFF_T_FORMAT" of "OFF_T_FORMAT" bytes have been retrieved\n", 392 newpath, (OFF_T_FORMAT_CAST)offset_check, 393 (OFF_T_FORMAT_CAST)localstat.st_size, 394 (OFF_T_FORMAT_CAST)remotestat.st_size); 395 } 396 397 if(offset_check) { 480 if (opt.verbose) { 481 printf("Trying to start resume of %s at %jd\n" 482 "At the moment %jd of %jd bytes have " 483 "been retrieved\n", 484 newpath, (intmax_t)offset_check, 485 (intmax_t)localstat.st_size, 486 (intmax_t)remotestat.st_size); 487 } 488 } 489 490 if (offset_check) { 398 491 off_t off1, off2; 399 /* First, check all bytes from offset_check to offset_download */ 492 /* First, check all bytes from offset_check to 493 * offset_download */ 400 494 off1 = lseek(localhandle, offset_check, SEEK_SET); 401 if(off1 < 0) { 402 fprintf(stderr, "Can't seek to "OFF_T_FORMAT" in local file %s\n", 403 (OFF_T_FORMAT_CAST)offset_check, newpath); 404 smbc_close(remotehandle); close(localhandle); 405 return 1; 406 } 407 408 off2 = smbc_lseek(remotehandle, offset_check, SEEK_SET); 409 if(off2 < 0) { 410 fprintf(stderr, "Can't seek to "OFF_T_FORMAT" in remote file %s\n", 411 (OFF_T_FORMAT_CAST)offset_check, newpath); 412 smbc_close(remotehandle); close(localhandle); 413 return 1; 414 } 415 416 if(off1 != off2) { 417 fprintf(stderr, "Offset in local and remote files is different (local: "OFF_T_FORMAT", remote: "OFF_T_FORMAT")\n", 418 (OFF_T_FORMAT_CAST)off1, 419 (OFF_T_FORMAT_CAST)off2); 420 smbc_close(remotehandle); close(localhandle); 421 return 1; 422 } 423 424 if(smbc_read(remotehandle, checkbuf[0], RESUME_CHECK_SIZE) != RESUME_CHECK_SIZE) { 425 fprintf(stderr, "Can't read %d bytes from remote file %s\n", RESUME_CHECK_SIZE, path); 426 smbc_close(remotehandle); close(localhandle); 427 return 1; 428 } 429 430 if(read(localhandle, checkbuf[1], RESUME_CHECK_SIZE) != RESUME_CHECK_SIZE) { 431 fprintf(stderr, "Can't read %d bytes from local file %s\n", RESUME_CHECK_SIZE, name); 432 smbc_close(remotehandle); close(localhandle); 433 return 1; 434 } 435 436 if(memcmp(checkbuf[0], checkbuf[1], RESUME_CHECK_SIZE) == 0) { 437 if(verbose)printf("Current local and remote file appear to be the same. Starting download from offset "OFF_T_FORMAT"\n", (OFF_T_FORMAT_CAST)offset_download); 495 if (off1 < 0) { 496 fprintf(stderr, 497 "Can't seek to %jd in local file %s\n", 498 (intmax_t)offset_check, newpath); 499 smbc_close(remotehandle); 500 close(localhandle); 501 return false; 502 } 503 504 off2 = smbc_lseek(remotehandle, offset_check, SEEK_SET); 505 if (off2 < 0) { 506 fprintf(stderr, 507 "Can't seek to %jd in remote file %s\n", 508 (intmax_t)offset_check, newpath); 509 smbc_close(remotehandle); 510 close(localhandle); 511 return false; 512 } 513 514 if (off1 != off2) { 515 fprintf(stderr, "Offset in local and remote " 516 "files are different " 517 "(local: %jd, remote: %jd)\n", 518 (intmax_t)off1, (intmax_t)off2); 519 smbc_close(remotehandle); 520 close(localhandle); 521 return false; 522 } 523 524 if (smbc_read(remotehandle, checkbuf[0], 525 RESUME_CHECK_SIZE) != RESUME_CHECK_SIZE) { 526 fprintf(stderr, "Can't read %d bytes from " 527 "remote file %s\n", 528 RESUME_CHECK_SIZE, path); 529 smbc_close(remotehandle); 530 close(localhandle); 531 return false; 532 } 533 534 if (read(localhandle, checkbuf[1], RESUME_CHECK_SIZE) != 535 RESUME_CHECK_SIZE) { 536 fprintf(stderr, "Can't read %d bytes from " 537 "local file %s\n", 538 RESUME_CHECK_SIZE, name); 539 smbc_close(remotehandle); 540 close(localhandle); 541 return false; 542 } 543 544 if (memcmp(checkbuf[0], checkbuf[1], 545 RESUME_CHECK_SIZE) == 0) { 546 if (opt.verbose) { 547 printf("Current local and remote file " 548 "appear to be the same. " 549 "Starting download from " 550 "offset %jd\n", 551 (intmax_t)offset_download); 552 } 438 553 } else { 439 fprintf(stderr, "Local and remote file appear to be different, not doing resume for %s\n", path); 440 smbc_close(remotehandle); close(localhandle); 441 return 1; 554 fprintf(stderr, "Local and remote file appear " 555 "to be different, not " 556 "doing resume for %s\n", 557 path); 558 smbc_close(remotehandle); 559 close(localhandle); 560 return false; 442 561 } 443 562 } … … 449 568 } 450 569 451 readbuf = (char *)SMB_MALLOC( blocksize);570 readbuf = (char *)SMB_MALLOC(opt.blocksize); 452 571 if (!readbuf) { 453 return 1; 572 fprintf(stderr, "Failed to allocate %zu bytes for read " 573 "buffer (%s)", opt.blocksize, strerror(errno)); 574 if (localhandle != STDOUT_FILENO) { 575 close(localhandle); 576 } 577 return false; 454 578 } 455 579 456 580 /* Now, download all bytes from offset_download to the end */ 457 for(curpos = offset_download; curpos < remotestat.st_size; curpos+=blocksize) { 458 ssize_t bytesread = smbc_read(remotehandle, readbuf, blocksize); 581 for (curpos = offset_download; curpos < remotestat.st_size; 582 curpos += opt.blocksize) { 583 ssize_t bytesread; 584 ssize_t byteswritten; 585 586 bytesread = smbc_read(remotehandle, readbuf, opt.blocksize); 459 587 if(bytesread < 0) { 460 fprintf(stderr, "Can't read %u bytes at offset "OFF_T_FORMAT", file %s\n", (unsigned int)blocksize, (OFF_T_FORMAT_CAST)curpos, path); 588 fprintf(stderr, 589 "Can't read %zu bytes at offset %jd, file %s\n", 590 opt.blocksize, (intmax_t)curpos, path); 461 591 smbc_close(remotehandle); 462 if (localhandle != STDOUT_FILENO) close(localhandle); 592 if (localhandle != STDOUT_FILENO) { 593 close(localhandle); 594 } 463 595 free(readbuf); 464 return 1;596 return false; 465 597 } 466 598 467 599 total_bytes += bytesread; 468 600 469 if(write(localhandle, readbuf, bytesread) < 0) { 470 fprintf(stderr, "Can't write %u bytes to local file %s at offset "OFF_T_FORMAT"\n", (unsigned int)bytesread, path, (OFF_T_FORMAT_CAST)curpos); 601 byteswritten = write(localhandle, readbuf, bytesread); 602 if (byteswritten != bytesread) { 603 fprintf(stderr, 604 "Can't write %zd bytes to local file %s at " 605 "offset %jd\n", bytesread, path, 606 (intmax_t)curpos); 471 607 free(readbuf); 472 608 smbc_close(remotehandle); 473 if (localhandle != STDOUT_FILENO) close(localhandle); 474 return 1; 475 } 476 477 if(dots)fputc('.', stderr); 478 else if(!quiet) { 609 if (localhandle != STDOUT_FILENO) { 610 close(localhandle); 611 } 612 return false; 613 } 614 615 if (opt.dots) { 616 fputc('.', stderr); 617 } else if (!opt.quiet) { 479 618 print_progress(newpath, start_time, time_mono(NULL), 480 start_offset, curpos, remotestat.st_size); 619 start_offset, curpos, 620 remotestat.st_size); 481 621 } 482 622 } … … 484 624 free(readbuf); 485 625 486 if (dots){626 if (opt.dots) { 487 627 fputc('\n', stderr); 488 628 printf("%s downloaded\n", path); 489 } else if (!quiet) {629 } else if (!opt.quiet) { 490 630 int i; 491 631 fprintf(stderr, "\r%s", path); 492 if (columns) {493 for (i = strlen(path); i < columns; i++) {632 if (columns) { 633 for (i = strlen(path); i < columns; i++) { 494 634 fputc(' ', stderr); 495 635 } … … 498 638 } 499 639 500 if(keep_permissions && !send_stdout) {501 if(fchmod(localhandle, remotestat.st_mode) < 0) {502 fprintf(stderr, "Unable to change mode of local file %s to %o\n", path,503 (unsigned int)remotestat.st_mode);504 smbc_close(remotehandle);505 close(localhandle);506 return 1;507 }508 }509 510 640 smbc_close(remotehandle); 511 if (localhandle != STDOUT_FILENO) close(localhandle); 512 return 0; 641 if (localhandle != STDOUT_FILENO) { 642 close(localhandle); 643 } 644 return true; 513 645 } 514 646 … … 517 649 char bs[100]; 518 650 human_readable(total_bytes, bs, sizeof(bs)); 519 if(!quiet)fprintf(stderr, "Downloaded %s in %lu seconds\n", bs, 520 (unsigned long)(time_mono(NULL) - total_start_time)); 651 if (!opt.quiet) { 652 fprintf(stderr, "Downloaded %s in %lu seconds\n", bs, 653 (unsigned long)(time_mono(NULL) - total_start_time)); 654 } 521 655 exit(0); 522 656 } … … 532 666 int lineno = 0, i; 533 667 char var[101], val[101]; 534 char found; 535 int *intdata; char **stringdata; 536 if(!fd) { 668 bool found; 669 int *intdata; 670 char **stringdata; 671 if (!fd) { 537 672 fprintf(stderr, "Can't open RC file %s\n", name); 538 673 return 1; 539 674 } 540 675 541 while (!feof(fd)) {676 while (!feof(fd)) { 542 677 lineno++; 543 if(fscanf(fd, "%100s %100s\n", var, val) < 2) { 544 fprintf(stderr, "Can't parse line %d of %s, ignoring.\n", lineno, name); 678 if (fscanf(fd, "%100s %100s\n", var, val) < 2) { 679 fprintf(stderr, 680 "Can't parse line %d of %s, ignoring.\n", 681 lineno, name); 545 682 continue; 546 683 } 547 684 548 found = 0; 549 550 for(i = 0; long_options[i].shortName; i++) { 551 if(!long_options[i].longName)continue; 552 if(strcmp(long_options[i].longName, var)) continue; 553 if(!long_options[i].arg)continue; 554 555 switch(long_options[i].argInfo) { 685 found = false; 686 687 for (i = 0; long_options[i].argInfo; i++) { 688 if (!long_options[i].longName) { 689 continue; 690 } 691 if (strcmp(long_options[i].longName, var)) { 692 continue; 693 } 694 if (!long_options[i].arg) { 695 continue; 696 } 697 698 switch (long_options[i].argInfo) { 556 699 case POPT_ARG_NONE: 557 700 intdata = (int *)long_options[i].arg; 558 if(!strcmp(val, "on")) *intdata = 1; 559 else if(!strcmp(val, "off")) *intdata = 0; 560 else fprintf(stderr, "Illegal value %s for %s at line %d in %s\n", val, var, lineno, name); 701 if (!strcmp(val, "on")) { 702 *intdata = 1; 703 } else if (!strcmp(val, "off")) { 704 *intdata = 0; 705 } else { 706 fprintf(stderr, "Illegal value %s for " 707 "%s at line %d in %s\n", 708 val, var, lineno, name); 709 } 561 710 break; 562 711 case POPT_ARG_INT: … … 567 716 stringdata = (char **)long_options[i].arg; 568 717 *stringdata = SMB_STRDUP(val); 718 if (long_options[i].shortName == 'U') { 719 char *p; 720 opt.username_specified = true; 721 p = strchr(*stringdata, '%'); 722 if (p != NULL) { 723 *p = '\0'; 724 opt.password = p + 1; 725 opt.password_specified = true; 726 } 727 } 569 728 break; 570 729 default: 571 fprintf(stderr, "Invalid variable %s at line %d in %s\n", var, lineno, name); 730 fprintf(stderr, "Invalid variable %s at " 731 "line %d in %s\n", 732 var, lineno, name); 572 733 break; 573 734 } 574 735 575 found = 1; 576 } 577 if(!found) { 578 fprintf(stderr, "Invalid variable %s at line %d in %s\n", var, lineno, name); 736 found = true; 737 } 738 if (!found) { 739 fprintf(stderr, 740 "Invalid variable %s at line %d in %s\n", var, 741 lineno, name); 579 742 } 580 743 } … … 584 747 } 585 748 586 int main(int argc, c onst char **argv)749 int main(int argc, char **argv) 587 750 { 588 751 int c = 0; … … 592 755 int resume = 0, recursive = 0; 593 756 TALLOC_CTX *frame = talloc_stackframe(); 594 int ret = 0; 757 bool ret = true; 758 char *p; 759 const char **argv_const = discard_const_p(const char *, argv); 595 760 struct poptOption long_options[] = { 596 {"guest", 'a', POPT_ARG_NONE, NULL, 'a', "Work as user guest" },597 {"encrypt", 'e', POPT_ARG_NONE, NULL, 'e', "Encrypt SMB transport (UNIX extended servers only)" },598 {"resume", 'r', POPT_ARG_NONE, &resume, 0, "Automatically resume aborted files" },599 {"update", 'U', POPT_ARG_NONE, &update, 0, "Download only when remote file is newer than local file or local file is missing"},600 {"recursive", 'R', POPT_ARG_NONE, &recursive, 0, "Recursively download files" },601 {"username", 'u', POPT_ARG_STRING, &username, 'u', "Username to use" },602 {"password", 'p', POPT_ARG_STRING, &password, 'p', "Password to use" },603 {"workgroup", 'w', POPT_ARG_STRING, &workgroup, 'w', "Workgroup to use (optional)" },604 {"nonprompt", 'n', POPT_ARG_NONE, &nonprompt, 'n', "Don't ask anything (non-interactive)" },605 {"debuglevel", 'd', POPT_ARG_INT, &debuglevel, 'd', "Debuglevel to use" },606 {"outputfile", 'o', POPT_ARG_STRING, &outputfile, 'o', "Write downloaded data to specified file" },607 {"stdout", 'O', POPT_ARG_NONE, &send_stdout, 'O', "Write data to stdout" },608 {"dots", 'D', POPT_ARG_NONE, &dots, 'D', "Show dots as progress indication" },609 {"quiet", 'q', POPT_ARG_NONE, &quiet, 'q', "Be quiet" },610 {"verbose", 'v', POPT_ARG_NONE, &verbose, 'v', "Be verbose" },611 {"keep-permissions", 'P', POPT_ARG_NONE, &keep_permissions, 'P', "Keep permissions" },612 {"blocksize", 'b', POPT_ARG_INT, &blocksize, 'b', "Change number of bytes in a block"},613 {"rcfile", 'f', POPT_ARG_STRING, NULL, 'f', "Use specified rc file"},614 761 POPT_AUTOHELP 762 763 {"workgroup", 'w', POPT_ARG_STRING, &opt.workgroup, 'w', "Workgroup to use (optional)" }, 764 {"user", 'U', POPT_ARG_STRING, &opt.username, 'U', "Username to use" }, 765 {"guest", 'a', POPT_ARG_NONE, NULL, 'a', "Work as user guest" }, 766 767 {"nonprompt", 'n', POPT_ARG_NONE, NULL, 'n', "Don't ask anything (non-interactive)" }, 768 {"debuglevel", 'd', POPT_ARG_INT, &opt.debuglevel, 'd', "Debuglevel to use" }, 769 770 {"encrypt", 'e', POPT_ARG_NONE, NULL, 'e', "Encrypt SMB transport" }, 771 {"resume", 'r', POPT_ARG_NONE, NULL, 'r', "Automatically resume aborted files" }, 772 {"update", 'u', POPT_ARG_NONE, NULL, 'u', "Download only when remote file is newer than local file or local file is missing"}, 773 {"recursive", 'R', POPT_ARG_NONE, NULL, 'R', "Recursively download files" }, 774 {"blocksize", 'b', POPT_ARG_INT, &opt.blocksize, 'b', "Change number of bytes in a block"}, 775 776 {"outputfile", 'o', POPT_ARG_STRING, &opt.outputfile, 'o', "Write downloaded data to specified file" }, 777 {"stdout", 'O', POPT_ARG_NONE, NULL, 'O', "Write data to stdout" }, 778 {"dots", 'D', POPT_ARG_NONE, NULL, 'D', "Show dots as progress indication" }, 779 {"quiet", 'q', POPT_ARG_NONE, NULL, 'q', "Be quiet" }, 780 {"verbose", 'v', POPT_ARG_NONE, NULL, 'v', "Be verbose" }, 781 {"rcfile", 'f', POPT_ARG_STRING, NULL, 'f', "Use specified rc file"}, 782 615 783 POPT_TABLEEND 616 784 }; 617 785 poptContext pc; 618 786 619 load_case_tables();787 smb_init_locale(); 620 788 621 789 /* only read rcfile if it exists */ … … 623 791 return 1; 624 792 } 625 if (access(rcfile, F_OK) == 0)793 if (access(rcfile, F_OK) == 0) { 626 794 readrcfile(rcfile, long_options); 795 } 627 796 free(rcfile); 628 797 … … 633 802 signal(SIGTERM, signal_quit); 634 803 635 pc = poptGetContext(argv[0], argc, argv , long_options, 0);636 637 while ((c = poptGetNextOpt(pc)) >=0) {638 switch (c) {804 pc = poptGetContext(argv[0], argc, argv_const, long_options, 0); 805 806 while ((c = poptGetNextOpt(pc)) > 0) { 807 switch (c) { 639 808 case 'f': 640 809 readrcfile(poptGetOptArg(pc), long_options); 641 810 break; 642 811 case 'a': 643 username = ""; password = ""; 812 opt.username_specified = true; 813 opt.username = talloc_strdup(frame, ""); 814 opt.password_specified = true; 815 opt.password = talloc_strdup(frame, ""); 644 816 break; 645 817 case 'e': 646 818 smb_encrypt = true; 647 819 break; 648 } 649 } 650 651 if((send_stdout || resume || outputfile) && update) { 652 fprintf(stderr, "The -o, -R or -O and -U options can not be used together.\n"); 820 case 'U': 821 opt.username_specified = true; 822 opt.username = talloc_strdup(frame, opt.username); 823 p = strchr(opt.username,'%'); 824 if (p != NULL) { 825 *p = '\0'; 826 opt.password = p + 1; 827 opt.password_specified = true; 828 } 829 break; 830 case 'n': 831 opt.nonprompt = true; 832 break; 833 case 'r': 834 resume = true; 835 break; 836 case 'u': 837 opt.update = true; 838 break; 839 case 'R': 840 recursive = true; 841 break; 842 case 'O': 843 opt.send_stdout = true; 844 break; 845 case 'D': 846 opt.dots = true; 847 break; 848 case 'q': 849 opt.quiet = true; 850 break; 851 case 'v': 852 opt.verbose = true; 853 break; 854 } 855 } 856 857 if (c < -1) { 858 fprintf(stderr, "%s: %s\n", 859 poptBadOption(pc, POPT_BADOPTION_NOALIAS), 860 poptStrerror(c)); 653 861 return 1; 654 862 } 655 if((send_stdout || outputfile) && recursive) { 656 fprintf(stderr, "The -o or -O and -R options can not be used together.\n"); 863 864 if ((opt.send_stdout || resume || opt.outputfile) && opt.update) { 865 fprintf(stderr, "The -o, -R or -O and -U options can not be " 866 "used together.\n"); 657 867 return 1; 658 868 } 659 660 if(outputfile && send_stdout) {661 fprintf(stderr, "The -o and -O options cannot beused together.\n");869 if ((opt.send_stdout || opt.outputfile) && recursive) { 870 fprintf(stderr, "The -o or -O and -R options can not be " 871 "used together.\n"); 662 872 return 1; 663 873 } 664 874 665 if(smbc_init(get_auth_data, debuglevel) < 0) { 875 if (opt.outputfile && opt.send_stdout) { 876 fprintf(stderr, "The -o and -O options can not be " 877 "used together.\n"); 878 return 1; 879 } 880 881 popt_burn_cmdline_password(argc, argv); 882 883 if (smbc_init(get_auth_data, opt.debuglevel) < 0) { 666 884 fprintf(stderr, "Unable to initialize libsmbclient\n"); 667 885 return 1; … … 671 889 SMBCCTX *smb_ctx = smbc_set_context(NULL); 672 890 smbc_option_set(smb_ctx, 673 CONST_DISCARD(char *, "smb_encrypt_level"),674 "require");891 discard_const_p(char, "smb_encrypt_level"), 892 "require"); 675 893 } 676 894 … … 679 897 total_start_time = time_mono(NULL); 680 898 681 while ( (file = poptGetArg(pc))) {682 if (!recursive) 899 while ((file = poptGetArg(pc))) { 900 if (!recursive) { 683 901 ret = smb_download_file(file, "", recursive, resume, 684 1,outputfile);685 else902 true, opt.outputfile); 903 } else { 686 904 ret = smb_download_dir(file, "", resume); 905 } 687 906 } 688 907 689 908 TALLOC_FREE(frame); 690 if ( ret == 0){909 if (ret) { 691 910 clean_exit(); 692 911 } 693 return ret ;694 } 912 return ret?0:1; 913 }
Note:
See TracChangeset
for help on using the changeset viewer.