Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/utils/smbget.c

    r740 r988  
    11/*
    2    smbget: a wget-like utility with support for recursive downloading and
    3         smb:// urls
     2   smbget: a wget-like utility with support for recursive downloading of
     3        smb:// urls
    44   Copyright (C) 2003-2004 Jelmer Vernooij <jelmer@samba.org>
    55
     
    2222#include "libsmbclient.h"
    2323
    24 #if _FILE_OFFSET_BITS==64
    25 #define OFF_T_FORMAT "%lld"
    26 #define OFF_T_FORMAT_CAST long long
    27 #else
    28 #define OFF_T_FORMAT "%ld"
    29 #define OFF_T_FORMAT_CAST long
    30 #endif
    31 
    3224static int columns = 0;
    33 
    34 static int debuglevel, update;
    35 static char *outputfile;
    36 
    3725
    3826static time_t total_start_time = 0;
     
    4129#define SMB_MAXPATHLEN MAXPATHLEN
    4230
    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)
    4738/* 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
     41struct 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};
     59static struct opt opt = { .blocksize = SMB_DEFAULT_BLOCKSIZE };
     60
     61static bool smb_download_file(const char *base, const char *name,
     62                              bool recursive, bool resume, bool toplevel,
     63                              char *outfile);
    5664
    5765static int get_num_cols(void)
     
    5967#ifdef TIOCGWINSZ
    6068        struct winsize ws;
    61         if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0) {
     69        if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0) {
    6270                return 0;
    6371        }
     
    6674#warning No support for TIOCGWINSZ
    6775        char *cols = getenv("COLUMNS");
    68         if(!cols) return 0;
     76        if (!cols) {
     77                return 0;
     78        }
    6979        return atoi(cols);
    7080#endif
     
    8595                snprintf(buffer, l, "%.2fkB", 1.0 * s / 1024);
    8696        } 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
     101static 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;
    95108        char tmp[128];
    96109
    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) {
    101119                printf("Username for %s at %s [guest] ", shr, srv);
    102120                if (fgets(tmp, sizeof(tmp), stdin) == NULL) {
    103121                        return;
    104122                }
    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) {
    114135                        return;
    115136                }
    116                 pass = getpass(prompt);
     137                (void)samba_getpass(prompt, pw, pwlen, false, false);
    117138                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
     165static bool smb_download_dir(const char *base, const char *name, int resume)
    132166{
    133167        char path[SMB_MAXPATHLEN];
     
    136170        const char *relname = name;
    137171        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);
    142178
    143179        /* List files in directory and call smb_download_file on them */
    144180        dirhandle = smbc_opendir(path);
    145         if(dirhandle < 1) {
     181        if (dirhandle < 1) {
    146182                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        }
    155194        mkdir(relname, 0755);
    156195
    157196        tmpname = SMB_STRDUP(name);
    158197
    159         while((dirent = smbc_readdir(dirhandle))) {
     198        while ((dirent = smbc_readdir(dirhandle))) {
    160199                char *newname;
    161                 if(!strcmp(dirent->name, ".") || !strcmp(dirent->name, ".."))continue;
     200                if (!strcmp(dirent->name, ".") || !strcmp(dirent->name, "..")) {
     201                        continue;
     202                }
    162203                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) {
    166208                case SMBC_DIR:
    167                         ret = smb_download_dir(base, newname, resume);
     209                        ok = smb_download_dir(base, newname, resume);
    168210                        break;
    169211
    170212                case SMBC_WORKGROUP:
    171                         ret = smb_download_dir("smb://", dirent->name, resume);
     213                        ok = smb_download_dir("smb://", dirent->name, resume);
    172214                        break;
    173215
    174216                case SMBC_SERVER:
    175                         ret = smb_download_dir("smb://", dirent->name, resume);
     217                        ok = smb_download_dir("smb://", dirent->name, resume);
    176218                        break;
    177219
    178220                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);
    181223                        break;
    182224
    183225                case SMBC_FILE_SHARE:
    184                         ret = smb_download_dir(base, newname, resume);
     226                        ok = smb_download_dir(base, newname, resume);
    185227                        break;
    186228
    187229                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                        }
    189234                        break;
    190235
    191236                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                        }
    193241                        break;
    194242
    195243                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                        }
    197248                        break;
    198249
    199250                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;
    202260                }
    203261                free(newname);
     
    205263        free(tmpname);
    206264
    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 
    222265        smbc_closedir(dirhandle);
    223         return ret;
     266        return ok;
    224267}
    225268
     
    228271        static char buffer[100];
    229272        int secs, mins, hours;
    230         if(t < -1) {
     273        if (t < -1) {
    231274                strncpy(buffer, "Unknown", sizeof(buffer));
    232275                return buffer;
     
    236279        mins = (int)t / 60 % 60;
    237280        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);
    239283        return buffer;
    240284}
    241285
    242 static void print_progress(const char *name, time_t start, time_t now, off_t start_pos, off_t pos, off_t total)
     286static void print_progress(const char *name, time_t start, time_t now,
     287                           off_t start_pos, off_t pos, off_t total)
    243288{
    244289        double avg = 0.0;
    245         long  eta = -1;
     290        long eta = -1;
    246291        double prcnt = 0.0;
    247292        char hpos[20], htotal[20], havg[20];
    248293        char *status, *filename;
    249294        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        }
    251298        eta = (total - pos) / avg;
    252         if(total)prcnt = 100.0 * pos / total;
     299        if (total) {
     300                prcnt = 100.0 * pos / total;
     301        }
    253302
    254303        human_readable(pos, hpos, sizeof(hpos));
     
    256305        human_readable(avg, havg, sizeof(havg));
    257306
    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));
    259309        if (len == -1) {
    260310                return;
    261311        }
    262312
    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) {
    267319                                return;
    268320                        }
     
    270322                        filename = SMB_STRNDUP(name, available);
    271323                }
    272         } else filename = SMB_STRDUP(name);
     324        } else {
     325                filename = SMB_STRDUP(name);
     326        }
    273327
    274328        fprintf(stderr, "\r[%s] %s", filename, status);
    275329
    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
     336static bool smb_download_file(const char *base, const char *name,
     337                              bool recursive, bool resume, bool toplevel,
     338                              char *outfile)
    283339{
    284340        int remotehandle, localhandle;
     
    288344        char checkbuf[2][RESUME_CHECK_SIZE];
    289345        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;
    291348        struct stat localstat, remotestat;
    292349
    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);
    294354
    295355        remotehandle = smbc_open(path, O_RDONLY, 0755);
    296356
    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;
    303366                        }
    304367                        return smb_download_dir(base, name, resume);
    305368
    306369                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;
    309374
    310375                case ENOMEM:
    311376                        fprintf(stderr, "Not enough memory\n");
    312                         return 1;
     377                        return false;
    313378
    314379                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;
    317384
    318385                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;
    321390
    322391                default:
    323392                        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) {
    329398                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]) {
    335405                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        }
    338414
    339415        if (!toplevel && (newpath[0] == '/')) {
     
    342418
    343419        /* Open local file according to the mode */
    344         if(update) {
     420        if (opt.update) {
    345421                /* if it is up-to-date, skip */
    346                 if(stat(newpath, &localstat) == 0 &&
    347                                 localstat.st_mtime >= remotestat.st_mtime) {
    348                         if(verbose)
     422                if (stat(newpath, &localstat) == 0 &&
     423                    localstat.st_mtime >= remotestat.st_mtime) {
     424                        if (opt.verbose) {
    349425                                printf("%s is up-to-date, skipping\n", newpath);
     426                        }
    350427                        smbc_close(remotehandle);
    351                         return 0;
     428                        return true;
    352429                }
    353430                /* 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) {
    356434                        fprintf(stderr, "Can't open %s : %s\n", newpath,
    357                                         strerror(errno));
     435                                strerror(errno));
    358436                        smbc_close(remotehandle);
    359                         return 1;
     437                        return false;
    360438                }
    361439                /* 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));
    366447                        smbc_close(remotehandle);
    367                         return 1;
     448                        return false;
    368449                }
    369450
    370451                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));
    372454                        smbc_close(remotehandle);
    373455                        close(localhandle);
    374                         return 1;
     456                        return false;
    375457                }
    376458
    377459                start_offset = localstat.st_size;
    378460
    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                        }
    382470                        smbc_close(remotehandle);
    383471                        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;
    389479                        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) {
    398491                        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 */
    400494                        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                                }
    438553                        } 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;
    442561                        }
    443562                }
     
    449568        }
    450569
    451         readbuf = (char *)SMB_MALLOC(blocksize);
     570        readbuf = (char *)SMB_MALLOC(opt.blocksize);
    452571        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;
    454578        }
    455579
    456580        /* 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);
    459587                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);
    461591                        smbc_close(remotehandle);
    462                         if (localhandle != STDOUT_FILENO) close(localhandle);
     592                        if (localhandle != STDOUT_FILENO) {
     593                                close(localhandle);
     594                        }
    463595                        free(readbuf);
    464                         return 1;
     596                        return false;
    465597                }
    466598
    467599                total_bytes += bytesread;
    468600
    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);
    471607                        free(readbuf);
    472608                        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) {
    479618                        print_progress(newpath, start_time, time_mono(NULL),
    480                                         start_offset, curpos, remotestat.st_size);
     619                                       start_offset, curpos,
     620                                       remotestat.st_size);
    481621                }
    482622        }
     
    484624        free(readbuf);
    485625
    486         if(dots){
     626        if (opt.dots) {
    487627                fputc('\n', stderr);
    488628                printf("%s downloaded\n", path);
    489         } else if(!quiet) {
     629        } else if (!opt.quiet) {
    490630                int i;
    491631                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++) {
    494634                                fputc(' ', stderr);
    495635                        }
     
    498638        }
    499639
    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 
    510640        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;
    513645}
    514646
     
    517649        char bs[100];
    518650        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        }
    521655        exit(0);
    522656}
     
    532666        int lineno = 0, i;
    533667        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) {
    537672                fprintf(stderr, "Can't open RC file %s\n", name);
    538673                return 1;
    539674        }
    540675
    541         while(!feof(fd)) {
     676        while (!feof(fd)) {
    542677                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);
    545682                        continue;
    546683                }
    547684
    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) {
    556699                        case POPT_ARG_NONE:
    557700                                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                                }
    561710                                break;
    562711                        case POPT_ARG_INT:
     
    567716                                stringdata = (char **)long_options[i].arg;
    568717                                *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                                }
    569728                                break;
    570729                        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);
    572733                                break;
    573734                        }
    574735
    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);
    579742                }
    580743        }
     
    584747}
    585748
    586 int main(int argc, const char **argv)
     749int main(int argc, char **argv)
    587750{
    588751        int c = 0;
     
    592755        int resume = 0, recursive = 0;
    593756        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);
    595760        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"},
    614761                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
    615783                POPT_TABLEEND
    616784        };
    617785        poptContext pc;
    618786
    619         load_case_tables();
     787        smb_init_locale();
    620788
    621789        /* only read rcfile if it exists */
     
    623791                return 1;
    624792        }
    625         if(access(rcfile, F_OK) == 0)
     793        if (access(rcfile, F_OK) == 0) {
    626794                readrcfile(rcfile, long_options);
     795        }
    627796        free(rcfile);
    628797
     
    633802        signal(SIGTERM, signal_quit);
    634803
    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) {
    639808                case 'f':
    640809                        readrcfile(poptGetOptArg(pc), long_options);
    641810                        break;
    642811                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, "");
    644816                        break;
    645817                case 'e':
    646818                        smb_encrypt = true;
    647819                        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));
    653861                return 1;
    654862        }
    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");
    657867                return 1;
    658868        }
    659 
    660         if(outputfile && send_stdout) {
    661                 fprintf(stderr, "The -o and -O options cannot be used 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");
    662872                return 1;
    663873        }
    664874
    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) {
    666884                fprintf(stderr, "Unable to initialize libsmbclient\n");
    667885                return 1;
     
    671889                SMBCCTX *smb_ctx = smbc_set_context(NULL);
    672890                smbc_option_set(smb_ctx,
    673                         CONST_DISCARD(char *, "smb_encrypt_level"),
    674                         "require");
     891                                discard_const_p(char, "smb_encrypt_level"),
     892                                "require");
    675893        }
    676894
     
    679897        total_start_time = time_mono(NULL);
    680898
    681         while ( (file = poptGetArg(pc)) ) {
    682                 if (!recursive)
     899        while ((file = poptGetArg(pc))) {
     900                if (!recursive) {
    683901                        ret = smb_download_file(file, "", recursive, resume,
    684                                                 1, outputfile);
    685                 else
     902                                                true, opt.outputfile);
     903                } else {
    686904                        ret = smb_download_dir(file, "", resume);
     905                }
    687906        }
    688907
    689908        TALLOC_FREE(frame);
    690         if ( ret == 0){
     909        if (ret) {
    691910                clean_exit();
    692911        }
    693         return ret;
    694 }
     912        return ret?0:1;
     913}
Note: See TracChangeset for help on using the changeset viewer.