Tidy up some missing checks for NULL in strlcpy.
[kai/samba.git] / source3 / client / clitar.c
index 084f87e3996a86d0f1d55e35c633d9ec50764763..80968a64d77ccd9c7b306ddf969603cd36c41d82 100644 (file)
@@ -35,6 +35,7 @@
 
 
 #include "includes.h"
+#include "system/filesys.h"
 #include "clitar.h"
 #include "client/client_proto.h"
 
@@ -69,7 +70,7 @@ extern struct cli_state *cli;
 #define ATTRSET 1
 #define ATTRRESET 0
 
-static uint16 attribute = aDIR | aSYSTEM | aHIDDEN;
+static uint16 attribute = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
 
 #ifndef CLIENT_TIMEOUT
 #define CLIENT_TIMEOUT (30*1000)
@@ -112,11 +113,13 @@ extern int get_total_size;
 static int blocksize=20;
 static int tarhandle;
 
-static void writetarheader(int f,  const char *aname, SMB_BIG_UINT size, time_t mtime,
+static void writetarheader(int f,  const char *aname, uint64_t size, time_t mtime,
                           const char *amode, unsigned char ftype);
-static void do_atar(const char *rname_in,char *lname,file_info *finfo1);
-static void do_tar(file_info *finfo, const char *dir);
-static void oct_it(SMB_BIG_UINT value, int ndgs, char *p);
+static NTSTATUS do_atar(const char *rname_in, char *lname,
+                   struct file_info *finfo1);
+static NTSTATUS do_tar(struct cli_state *cli_state, struct file_info *finfo,
+                  const char *dir);
+static void oct_it(uint64_t value, int ndgs, char *p);
 static void fixtarname(char *tptr, const char *fp, size_t l);
 static int dotarbuf(int f, char *b, int n);
 static void dozerobuf(int f, int n);
@@ -133,28 +136,11 @@ static void unfixtarname(char *tptr, char *fp, int l, bool first);
  * tar specific utitlities
  */
 
-/*******************************************************************
-Create  a string of size size+1 (for the null)
-*******************************************************************/
-
-static char *string_create_s(int size)
-{
-       char *tmp;
-
-       tmp = (char *)SMB_MALLOC(size+1);
-
-       if (tmp == NULL) {
-               DEBUG(0, ("Out of memory in string_create_s\n"));
-       }
-
-       return(tmp);
-}
-
 /****************************************************************************
 Write a tar header to buffer
 ****************************************************************************/
 
-static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t mtime,
+static void writetarheader(int f, const char *aname, uint64_t size, time_t mtime,
                           const char *amode, unsigned char ftype)
 {
        union hblock hb;
@@ -194,11 +180,11 @@ static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t m
        /* write out a "standard" tar format header */
 
        hb.dbuf.name[NAMSIZ-1]='\0';
-       safe_strcpy(hb.dbuf.mode, amode, sizeof(hb.dbuf.mode)-1);
-       oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.uid);
-       oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.gid);
-       oct_it((SMB_BIG_UINT) size, 13, hb.dbuf.size);
-       if (size > (SMB_BIG_UINT)077777777777LL) {
+       strlcpy(hb.dbuf.mode, amode ? amode : "", sizeof(hb.dbuf.mode));
+       oct_it((uint64_t)0, 8, hb.dbuf.uid);
+       oct_it((uint64_t)0, 8, hb.dbuf.gid);
+       oct_it((uint64_t) size, 13, hb.dbuf.size);
+       if (size > (uint64_t)077777777777LL) {
                /* This is a non-POSIX compatible extention to store files
                        greater than 8GB. */
 
@@ -207,7 +193,7 @@ static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t m
                for (i = 8, jp=(char*)&size; i; i--)
                        hb.dbuf.size[i+3] = *(jp++);
        }
-       oct_it((SMB_BIG_UINT) mtime, 13, hb.dbuf.mtime);
+       oct_it((uint64_t) mtime, 13, hb.dbuf.mtime);
        memcpy(hb.dbuf.chksum, "        ", sizeof(hb.dbuf.chksum));
        memset(hb.dbuf.linkname, 0, NAMSIZ);
        hb.dbuf.linkflag=ftype;
@@ -215,7 +201,7 @@ static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t m
        for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;)
                chk+=(0xFF & *jp++);
 
-       oct_it((SMB_BIG_UINT) chk, 8, hb.dbuf.chksum);
+       oct_it((uint64_t) chk, 8, hb.dbuf.chksum);
        hb.dbuf.chksum[6] = '\0';
 
        (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy));
@@ -260,12 +246,12 @@ static long readtarheader(union hblock *hb, file_info2 *finfo, const char *prefi
                return -1;
        }
 
-       if ((finfo->name = string_create_s(strlen(prefix) + strlen(hb -> dbuf.name) + 3)) == NULL) {
+       if ((finfo->name = SMB_MALLOC(strlen(prefix) + strlen(hb -> dbuf.name) + 4)) == NULL) {
                DEBUG(0, ("Out of space creating file_info2 for %s\n", hb -> dbuf.name));
                return(-1);
        }
 
-       safe_strcpy(finfo->name, prefix, strlen(prefix) + strlen(hb -> dbuf.name) + 3);
+       strlcpy(finfo->name, prefix, strlen(prefix) + strlen(hb -> dbuf.name) + 4);
 
        /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */
        unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name,
@@ -291,7 +277,7 @@ of link other than a GNUtar Longlink - ignoring\n"));
 
        if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR) ||
                                (*(finfo->name+strlen(finfo->name)-1) == '\\')) {
-               finfo->mode=aDIR;
+               finfo->mode=FILE_ATTRIBUTE_DIRECTORY;
        } else {
                finfo->mode=0; /* we don't care about mode at the moment, we'll
                                * just make it a regular file */
@@ -329,13 +315,13 @@ static int dotarbuf(int f, char *b, int n)
 
                diff=tbufsiz-tp;
                memcpy(tarbuf + tp, b, diff);
-               fail=fail && (1+write(f, tarbuf, tbufsiz));
+               fail=fail && (1+sys_write(f, tarbuf, tbufsiz));
                n-=diff;
                b+=diff;
                tp=0;
 
                while (n >= tbufsiz) {
-                       fail=fail && (1 + write(f, b, tbufsiz));
+                       fail=fail && (1 + sys_write(f, b, tbufsiz));
                        n-=tbufsiz;
                        b+=tbufsiz;
                }
@@ -364,7 +350,10 @@ static void dozerobuf(int f, int n)
 
        if (n+tp >= tbufsiz) {
                memset(tarbuf+tp, 0, tbufsiz-tp);
-               write(f, tarbuf, tbufsiz);
+               if (sys_write(f, tarbuf, tbufsiz) != tbufsiz) {
+                       DEBUG(0, ("dozerobuf: sys_write fail\n"));
+                       return;
+               }
                memset(tarbuf, 0, (tp+=n-tbufsiz));
        } else {
                memset(tarbuf+tp, 0, n);
@@ -401,15 +390,19 @@ static void dotareof(int f)
        (void) dozerobuf(f, TBLOCK);
        (void) dozerobuf(f, TBLOCK);
 
-       if (sys_fstat(f, &stbuf) == -1) {
+       if (sys_fstat(f, &stbuf, false) == -1) {
                DEBUG(0, ("Couldn't stat file handle\n"));
                return;
        }
 
        /* Could be a pipe, in which case S_ISREG should fail,
                * and we should write out at full size */
-       if (tp > 0)
-               write(f, tarbuf, S_ISREG(stbuf.st_mode) ? tp : tbufsiz);
+       if (tp > 0) {
+               size_t towrite = S_ISREG(stbuf.st_ex_mode) ? tp : tbufsiz;
+               if (sys_write(f, tarbuf, towrite) != towrite) {
+                       DEBUG(0,("dotareof: sys_write fail\n"));
+               }
+       }
 }
 
 /****************************************************************************
@@ -431,7 +424,7 @@ static void fixtarname(char *tptr, const char *fp, size_t l)
 Convert from decimal to octal string
 ****************************************************************************/
 
-static void oct_it (SMB_BIG_UINT value, int ndgs, char *p)
+static void oct_it (uint64_t value, int ndgs, char *p)
 {
        /* Converts long to octal string, pads with leading zeros */
 
@@ -511,14 +504,15 @@ static bool ensurepath(const char *fname)
        /* ensures path exists */
 
        char *partpath, *ffname;
+       size_t fnamelen = strlen(fname)+1;
        const char *p=fname;
        char *basehack;
        char *saveptr;
 
        DEBUG(5, ( "Ensurepath called with: %s\n", fname));
 
-       partpath = string_create_s(strlen(fname));
-       ffname = string_create_s(strlen(fname));
+       partpath = SMB_MALLOC(fnamelen);
+       ffname = SMB_MALLOC(fnamelen);
 
        if ((partpath == NULL) || (ffname == NULL)){
                DEBUG(0, ("Out of memory in ensurepath: %s\n", fname));
@@ -531,7 +525,7 @@ static bool ensurepath(const char *fname)
 
        /* fname copied to ffname so can strtok_r */
 
-       safe_strcpy(ffname, fname, strlen(fname));
+       strlcpy(ffname, fname, fnamelen);
 
        /* do a `basename' on ffname, so don't try and make file name directory */
        if ((basehack=strrchr_m(ffname, '\\')) == NULL) {
@@ -545,10 +539,10 @@ static bool ensurepath(const char *fname)
        p=strtok_r(ffname, "\\", &saveptr);
 
        while (p) {
-               safe_strcat(partpath, p, strlen(fname) + 1);
+               strlcat(partpath, p, fnamelen);
 
-               if (!cli_chkpath(cli, partpath)) {
-                       if (!cli_mkdir(cli, partpath)) {
+               if (!NT_STATUS_IS_OK(cli_chkpath(cli, partpath))) {
+                       if (!NT_STATUS_IS_OK(cli_mkdir(cli, partpath))) {
                                SAFE_FREE(partpath);
                                SAFE_FREE(ffname);
                                DEBUG(0, ("Error mkdir %s\n", cli_errstr(cli)));
@@ -558,7 +552,7 @@ static bool ensurepath(const char *fname)
                        }
                }
 
-               safe_strcat(partpath, "\\", strlen(fname) + 1);
+               strlcat(partpath, "\\", fnamelen);
                p = strtok_r(NULL, "/\\", &saveptr);
        }
 
@@ -567,7 +561,7 @@ static bool ensurepath(const char *fname)
        return True;
 }
 
-static int padit(char *buf, SMB_BIG_UINT bufsize, SMB_BIG_UINT padsize)
+static int padit(char *buf, uint64_t bufsize, uint64_t padsize)
 {
        int berr= 0;
        int bytestowrite;
@@ -587,7 +581,9 @@ static void do_setrattr(char *name, uint16 attr, int set)
 {
        uint16 oldattr;
 
-       if (!cli_getatr(cli, name, &oldattr, NULL, NULL)) return;
+       if (!NT_STATUS_IS_OK(cli_getatr(cli, name, &oldattr, NULL, NULL))) {
+               return;
+       }
 
        if (set == ATTRSET) {
                attr |= oldattr;
@@ -595,7 +591,7 @@ static void do_setrattr(char *name, uint16 attr, int set)
                attr = oldattr & ~attr;
        }
 
-       if (!cli_setatr(cli, name, attr, 0)) {
+       if (!NT_STATUS_IS_OK(cli_setatr(cli, name, attr, 0))) {
                DEBUG(1,("setatr failed: %s\n", cli_errstr(cli)));
        }
 }
@@ -604,10 +600,11 @@ static void do_setrattr(char *name, uint16 attr, int set)
 append one remote file to the tar file
 ***************************************************************************/
 
-static void do_atar(const char *rname_in,char *lname,file_info *finfo1)
+static NTSTATUS do_atar(const char *rname_in, char *lname,
+                   struct file_info *finfo1)
 {
-       int fnum = -1;
-       SMB_BIG_UINT nread=0;
+       uint16_t fnum = (uint16_t)-1;
+       uint64_t nread=0;
        char ftype;
        file_info2 finfo;
        bool shallitime=True;
@@ -616,14 +613,15 @@ static void do_atar(const char *rname_in,char *lname,file_info *finfo1)
        int datalen=0;
        char *rname = NULL;
        TALLOC_CTX *ctx = talloc_stackframe();
+       NTSTATUS status = NT_STATUS_OK;
+       struct timespec tp_start;
 
-       struct timeval tp_start;
-
-       GetTimeOfDay(&tp_start);
+       clock_gettime_mono(&tp_start);
 
        data = SMB_MALLOC_ARRAY(char, read_size);
        if (!data) {
                DEBUG(0,("do_atar: out of memory.\n"));
+               status = NT_STATUS_NO_MEMORY;
                goto cleanup;
        }
 
@@ -650,34 +648,33 @@ static void do_atar(const char *rname_in,char *lname,file_info *finfo1)
 
        rname = clean_name(ctx, rname_in);
        if (!rname) {
+               status = NT_STATUS_NO_MEMORY;
                goto cleanup;
        }
 
-       fnum = cli_open(cli, rname, O_RDONLY, DENY_NONE);
-
-       if (fnum == -1) {
+       status = cli_open(cli, rname, O_RDONLY, DENY_NONE, &fnum);
+       if (!NT_STATUS_IS_OK(status)) {
                DEBUG(0,("%s opening remote file %s (%s)\n",
                                cli_errstr(cli),rname, client_get_cur_dir()));
                goto cleanup;
        }
 
-       finfo.name = string_create_s(strlen(rname));
+       finfo.name = smb_xstrdup(rname);
        if (finfo.name == NULL) {
                DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n"));
+               status = NT_STATUS_NO_MEMORY;
                goto cleanup;
        }
 
-       safe_strcpy(finfo.name,rname, strlen(rname));
-
        DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode));
 
-       if (tar_inc && !(finfo.mode & aARCH)) {
+       if (tar_inc && !(finfo.mode & FILE_ATTRIBUTE_ARCHIVE)) {
                DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name));
                shallitime=0;
-       } else if (!tar_system && (finfo.mode & aSYSTEM)) {
+       } else if (!tar_system && (finfo.mode & FILE_ATTRIBUTE_SYSTEM)) {
                DEBUG(4, ("skipping %s - system bit is set\n", finfo.name));
                shallitime=0;
-       } else if (!tar_hidden && (finfo.mode & aHIDDEN)) {
+       } else if (!tar_hidden && (finfo.mode & FILE_ATTRIBUTE_HIDDEN)) {
                DEBUG(4, ("skipping %s - hidden bit is set\n", finfo.name));
                shallitime=0;
        } else {
@@ -694,6 +691,7 @@ static void do_atar(const char *rname_in,char *lname,file_info *finfo1)
 
                        if (datalen == -1) {
                                DEBUG(0,("Error reading file %s : %s\n", rname, cli_errstr(cli)));
+                               status = cli_nt_error(cli);
                                break;
                        }
 
@@ -722,10 +720,12 @@ static void do_atar(const char *rname_in,char *lname,file_info *finfo1)
 
                        if (dotarbuf(tarhandle,data,datalen) != datalen) {
                                DEBUG(0,("Error writing to tar file - %s\n", strerror(errno)));
+                               status = map_nt_error_from_unix(errno);
                                break;
                        }
 
                        if ( (datalen == 0) && (finfo.size != 0) ) {
+                               status = NT_STATUS_UNSUCCESSFUL;
                                DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname));
                                break;
                        }
@@ -738,8 +738,10 @@ static void do_atar(const char *rname_in,char *lname,file_info *finfo1)
                        if (nread < finfo.size) {
                                DEBUG(0, ("Didn't get entire file. size=%.0f, nread=%d\n",
                                                        (double)finfo.size, (int)nread));
-                               if (padit(data, (SMB_BIG_UINT)sizeof(data), finfo.size - nread))
+                               if (padit(data, (uint64_t)sizeof(data), finfo.size - nread)) {
+                                       status = map_nt_error_from_unix(errno);
                                        DEBUG(0,("Error writing tar file - %s\n", strerror(errno)));
+                               }
                        }
 
                        /* round tar file to nearest block */
@@ -751,6 +753,7 @@ static void do_atar(const char *rname_in,char *lname,file_info *finfo1)
                } else {
                        DEBUG(4, ("skipping %s - initial read failed (file was locked ?)\n", finfo.name));
                        shallitime=0;
+                       status = NT_STATUS_UNSUCCESSFUL;
                }
        }
 
@@ -758,15 +761,15 @@ static void do_atar(const char *rname_in,char *lname,file_info *finfo1)
        fnum = -1;
 
        if (shallitime) {
-               struct timeval tp_end;
+               struct timespec tp_end;
                int this_time;
 
                /* if shallitime is true then we didn't skip */
                if (tar_reset && !dry_run)
-                       (void) do_setrattr(finfo.name, aARCH, ATTRRESET);
+                       (void) do_setrattr(finfo.name, FILE_ATTRIBUTE_ARCHIVE, ATTRRESET);
 
-               GetTimeOfDay(&tp_end);
-               this_time = (tp_end.tv_sec - tp_start.tv_sec)*1000 + (tp_end.tv_usec - tp_start.tv_usec)/1000;
+               clock_gettime_mono(&tp_end);
+               this_time = (tp_end.tv_sec - tp_start.tv_sec)*1000 + (tp_end.tv_nsec - tp_start.tv_nsec)/1000000;
                get_total_time_ms += this_time;
                get_total_size += finfo.size;
 
@@ -784,24 +787,27 @@ static void do_atar(const char *rname_in,char *lname,file_info *finfo1)
 
   cleanup:
 
-       if (fnum != -1) {
+       if (fnum != (uint16_t)-1) {
                cli_close(cli, fnum);
                fnum = -1;
        }
        TALLOC_FREE(ctx);
        SAFE_FREE(data);
+       return status;
 }
 
 /****************************************************************************
 Append single file to tar file (or not)
 ***************************************************************************/
 
-static void do_tar(file_info *finfo, const char *dir)
+static NTSTATUS do_tar(struct cli_state *cli_state, struct file_info *finfo,
+                  const char *dir)
 {
        TALLOC_CTX *ctx = talloc_stackframe();
+       NTSTATUS status = NT_STATUS_OK;
 
        if (strequal(finfo->name,"..") || strequal(finfo->name,"."))
-               return;
+               return NT_STATUS_OK;
 
        /* Is it on the exclude list ? */
        if (!tar_excl && clipn) {
@@ -814,7 +820,7 @@ static void do_tar(file_info *finfo, const char *dir)
                                client_get_cur_dir(),
                                finfo->name);
                if (!exclaim) {
-                       return;
+                       return NT_STATUS_NO_MEMORY;
                }
 
                DEBUG(5, ("...tar_re_search: %d\n", tar_re_search));
@@ -823,19 +829,19 @@ static void do_tar(file_info *finfo, const char *dir)
                                (tar_re_search && mask_match_list(exclaim, cliplist, clipn, True))) {
                        DEBUG(3,("Skipping file %s\n", exclaim));
                        TALLOC_FREE(exclaim);
-                       return;
+                       return NT_STATUS_OK;
                }
                TALLOC_FREE(exclaim);
        }
 
-       if (finfo->mode & aDIR) {
+       if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
                char *saved_curdir = NULL;
                char *new_cd = NULL;
                char *mtar_mask = NULL;
 
                saved_curdir = talloc_strdup(ctx, client_get_cur_dir());
                if (!saved_curdir) {
-                       return;
+                       return NT_STATUS_NO_MEMORY;
                }
 
                DEBUG(5, ("strlen(cur_dir)=%d, \
@@ -848,7 +854,7 @@ strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n",
                                client_get_cur_dir(),
                                finfo->name);
                if (!new_cd) {
-                       return;
+                       return NT_STATUS_NO_MEMORY;
                }
                client_set_cur_dir(new_cd);
 
@@ -867,10 +873,10 @@ strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n",
                                "%s*",
                                client_get_cur_dir());
                if (!mtar_mask) {
-                       return;
+                       return NT_STATUS_NO_MEMORY;
                }
                DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask));
-               do_list(mtar_mask, attribute, do_tar, False, True);
+               status = do_list(mtar_mask, attribute, do_tar, False, True);
                client_set_cur_dir(saved_curdir);
                TALLOC_FREE(saved_curdir);
                TALLOC_FREE(new_cd);
@@ -881,11 +887,12 @@ strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n",
                                        client_get_cur_dir(),
                                        finfo->name);
                if (!rname) {
-                       return;
+                       return NT_STATUS_NO_MEMORY;
                }
-               do_atar(rname,finfo->name,finfo);
+               status = do_atar(rname,finfo->name,finfo);
                TALLOC_FREE(rname);
        }
+       return status;
 }
 
 /****************************************************************************
@@ -909,9 +916,12 @@ static void unfixtarname(char *tptr, char *fp, int l, bool first)
                        fp++;
                        l--;
                }
+               if (l <= 0) {
+                       return;
+               }
        }
 
-       safe_strcpy(tptr, fp, l);
+       strlcpy(tptr, fp, l);
        string_replace(tptr, '/', '\\');
 }
 
@@ -991,15 +1001,22 @@ static int skip_file(int skipsize)
 
 static int get_file(file_info2 finfo)
 {
-       int fnum = -1, pos = 0, dsize = 0, bpos = 0;
-       SMB_BIG_UINT rsize = 0;
+       uint16_t fnum = (uint16_t) -1;
+       int pos = 0, dsize = 0, bpos = 0;
+       uint64_t rsize = 0;
+       NTSTATUS status;
 
        DEBUG(5, ("get_file: file: %s, size %.0f\n", finfo.name, (double)finfo.size));
 
-       if (ensurepath(finfo.name) &&
-                       (fnum=cli_open(cli, finfo.name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) == -1) {
+       if (!ensurepath(finfo.name)) {
                DEBUG(0, ("abandoning restore\n"));
-               return(False);
+               return False;
+       }
+
+       status = cli_open(cli, finfo.name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE, &fnum);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("abandoning restore\n"));
+               return False;
        }
 
        /* read the blocks from the tar file and write to the remote file */
@@ -1013,8 +1030,12 @@ static int get_file(file_info2 finfo)
                dsize = MIN(dsize, rsize);  /* Should be only what is left */
                DEBUG(5, ("writing %i bytes, bpos = %i ...\n", dsize, bpos));
 
-               if (cli_write(cli, fnum, 0, buffer_p + bpos, pos, dsize) != dsize) {
-                       DEBUG(0, ("Error writing remote file\n"));
+               status = cli_writeall(cli, fnum, 0,
+                                     (uint8_t *)(buffer_p + bpos), pos,
+                                     dsize, NULL);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("Error writing remote file: %s\n",
+                                 nt_errstr(status)));
                        return 0;
                }
 
@@ -1061,15 +1082,16 @@ static int get_file(file_info2 finfo)
 
        /* Now close the file ... */
 
-       if (!cli_close(cli, fnum)) {
-               DEBUG(0, ("Error closing remote file\n"));
+       if (!NT_STATUS_IS_OK(cli_close(cli, fnum))) {
+               DEBUG(0, ("Error %s closing remote file\n",
+                       cli_errstr(cli)));
                return(False);
        }
 
        /* Now we update the creation date ... */
        DEBUG(5, ("Updating creation date on %s\n", finfo.name));
 
-       if (!cli_setatr(cli, finfo.name, finfo.mode, finfo.mtime_ts.tv_sec)) {
+       if (!NT_STATUS_IS_OK(cli_setatr(cli, finfo.name, finfo.mode, finfo.mtime_ts.tv_sec))) {
                if (tar_real_noisy) {
                        DEBUG(0, ("Could not set time on file: %s\n", finfo.name));
                        /*return(False); */ /* Ignore, as Win95 does not allow changes */
@@ -1133,7 +1155,8 @@ static char *get_longfilename(file_info2 finfo)
                        return(NULL);
                }
 
-               unfixtarname(longname + offset, buffer_p, MIN(TBLOCK, finfo.size), first--);
+               unfixtarname(longname + offset, buffer_p,
+                       namesize - offset, first--);
                DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname, buffer_p));
 
                offset += TBLOCK;
@@ -1146,13 +1169,13 @@ static char *get_longfilename(file_info2 finfo)
 static void do_tarput(void)
 {
        file_info2 finfo;
-       struct timeval tp_start;
+       struct timespec tp_start;
        char *longfilename = NULL, linkflag;
        int skip = False;
 
        ZERO_STRUCT(finfo);
 
-       GetTimeOfDay(&tp_start);
+       clock_gettime_mono(&tp_start);
        DEBUG(5, ("RJS do_tarput called ...\n"));
 
        buffer_p = tarbuf + tbufsiz;  /* init this to force first read */
@@ -1174,16 +1197,19 @@ static void do_tarput(void)
                                DEBUG(0, ("Skipping %s...\n", finfo.name));
                                if ((next_block(tarbuf, &buffer_p, tbufsiz) <= 0) && !skip_file(finfo.size)) {
                                        DEBUG(0, ("Short file, bailing out...\n"));
+                                       SAFE_FREE(longfilename);
                                        return;
                                }
                                break;
 
                        case -1:
                                DEBUG(0, ("abandoning restore, -1 from read tar header\n"));
+                               SAFE_FREE(longfilename);
                                return;
 
                        case 0: /* chksum is zero - looks like an EOF */
                                DEBUG(0, ("tar: restored %d files and directories\n", ntarf));
+                               SAFE_FREE(longfilename);
                                return;        /* Hmmm, bad here ... */
 
                        default: 
@@ -1365,16 +1391,16 @@ int cmd_setmode(void)
                                        direct=0;
                                        break;
                                case 'r':
-                                       attra[direct]|=aRONLY;
+                                       attra[direct]|=FILE_ATTRIBUTE_READONLY;
                                        break;
                                case 'h':
-                                       attra[direct]|=aHIDDEN;
+                                       attra[direct]|=FILE_ATTRIBUTE_HIDDEN;
                                        break;
                                case 's':
-                                       attra[direct]|=aSYSTEM;
+                                       attra[direct]|=FILE_ATTRIBUTE_SYSTEM;
                                        break;
                                case 'a':
-                                       attra[direct]|=aARCH;
+                                       attra[direct]|=FILE_ATTRIBUTE_ARCHIVE;
                                        break;
                                default:
                                        DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
@@ -1506,6 +1532,7 @@ int process_tar(void)
 
                                        if (strrchr_m(cliplist[i], '\\')) {
                                                char *p;
+                                               char saved_char;
                                                char *saved_dir = talloc_strdup(ctx,
                                                                        client_get_cur_dir());
                                                if (!saved_dir) {
@@ -1524,13 +1551,28 @@ int process_tar(void)
                                                if (!tarmac) {
                                                        return 1;
                                                }
+                                               /*
+                                                * Strip off the last \\xxx
+                                                * xxx element of tarmac to set
+                                                * it as current directory.
+                                                */
                                                p = strrchr_m(tarmac, '\\');
                                                if (!p) {
                                                        return 1;
                                                }
+                                               saved_char = p[1];
                                                p[1] = '\0';
+
                                                client_set_cur_dir(tarmac);
 
+                                               /*
+                                                * Restore the character we
+                                                * just replaced to
+                                                * put the pathname
+                                                * back as it was.
+                                                */
+                                               p[1] = saved_char;
+
                                                DEBUG(5, ("process_tar, do_list with tarmac: %s\n", tarmac));
                                                do_list(tarmac,attribute,do_tar, False, True);
 
@@ -1665,7 +1707,7 @@ static int read_inclusion_file(char *filename)
                        }
                }
 
-               safe_strcpy(inclusion_buffer + inclusion_buffer_sofar, buf, inclusion_buffer_size - inclusion_buffer_sofar);
+               strlcpy(inclusion_buffer + inclusion_buffer_sofar, buf, inclusion_buffer_size - inclusion_buffer_sofar);
                inclusion_buffer_sofar += strlen(buf) + 1;
                clipn++;
        }
@@ -1767,8 +1809,10 @@ int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind)
                                } else {
                                        SMB_STRUCT_STAT stbuf;
 
-                                       if (sys_stat(argv[Optind], &stbuf) == 0) {
-                                               newer_than = stbuf.st_mtime;
+                                       if (sys_stat(argv[Optind], &stbuf,
+                                                    false) == 0) {
+                                               newer_than = convert_timespec_to_time_t(
+                                                       stbuf.st_ex_mtime);
                                                DEBUG(1,("Getting files newer than %s",
                                                        time_to_asc(newer_than)));
                                                newOptind++;
@@ -1896,7 +1940,7 @@ int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind)
                 * tar output
                 */
                if (tarhandle == 1)  {
-                       dbf = x_stderr;
+                       setup_logging("smbclient", DEBUG_STDERR);
                }
                if (!argv[Optind]) {
                        DEBUG(0,("Must specify tar filename\n"));