Description: Adds a tarmode compatible with BackupPC Adds a tarmode that restores behavior present in samba 3.5, that is required for successful backups with BackupPC Author: Alan Bowler Origin: other Bug: https://bugzilla.samba.org/show_bug.cgi?id=10605 Reviewed-by: Aurimas FiĊĦeras --- This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ --- a/docs/manpages/smbclient.1 +++ b/docs/manpages/smbclient.1 @@ -1020,9 +1020,11 @@ Blocksize\&. Must be followed by a valid \fIblocksize\fR*TBLOCK (usually 512 byte) blocks\&. .RE .PP -tarmode +tarmode .RS 4 Changes tar\*(Aqs behavior with regard to archive bits\&. In full mode, tar will back up everything regardless of the archive bit setting (this is the default mode)\&. In incremental mode, tar will only back up files with the archive bit set\&. In reset mode, tar will reset the archive bit on all files it backs up (implies read/write share)\&. +.P errorskip +Normally, when access to a file is denied (no permission, busy, etc.), tar will stop processing any further entries from that directory and resume at the next element of the parent directory\&. \*(Aqerrorskip\*(Aq makes it skip just the file that had the access error\&. .RE .PP timeout --- a/source3/client/client.c +++ b/source3/client/client.c @@ -4706,7 +4706,9 @@ static struct { {"stat",cmd_stat," Do a UNIX extensions stat call on a file",{COMPL_REMOTE,COMPL_NONE}}, {"symlink",cmd_symlink," create a UNIX symlink",{COMPL_REMOTE,COMPL_REMOTE}}, {"tar",cmd_tar,"tar [IXFqbgNan] current directory to/from ",{COMPL_NONE,COMPL_NONE}}, - {"tarmode",cmd_tarmode," tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}}, + {"tarmode",cmd_tarmode, + "\n" + " tar's behaviour towards archive bits, and access errors", {COMPL_NONE,COMPL_NONE}}, {"timeout",cmd_timeout,"timeout - set the per-operation timeout in seconds (default 20)",{COMPL_NONE,COMPL_NONE}}, {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}}, {"unlock",cmd_unlock,"unlock : remove a POSIX lock",{COMPL_REMOTE,COMPL_REMOTE}}, --- a/source3/client/clitar.c +++ b/source3/client/clitar.c @@ -79,6 +79,8 @@ static int tp, ntarf, tbufsiz; static double ttarf; /* Incremental mode */ static bool tar_inc=False; +/* Backup mode, (skip NT files that can't be opened, and continue with directory) */ +static bool tar_errskip=False; /* Reset archive bit */ static bool tar_reset=False; /* Include / exclude mode (true=include, false=exclude) */ @@ -99,6 +101,7 @@ char tar_type='\0'; static char **cliplist=NULL; static int clipn=0; static bool must_free_cliplist = False; +static long tarskip = 0; /* count of files skipped */ extern char *cmd_ptr; extern bool lowercase; @@ -668,19 +671,26 @@ static NTSTATUS do_atar(const char *rnam if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("%s opening remote file %s (%s)\n", nt_errstr(status),rname, client_get_cur_dir())); - goto cleanup; + if (!tar_errskip) { + goto cleanup; /* return bad status, and leave directory */ + } + ++tarskip; + DEBUG(0, ("Skipping %s fnum=%d\n", rname, (int16_t)fnum)); + shallitime = 0; } 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; + goto cleanup; /* return bad status, and leave directory */ } - + DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode)); - - if (tar_inc && !(finfo.mode & FILE_ATTRIBUTE_ARCHIVE)) { + + if (!shallitime) { /* are we skipping this file ? */ + status = NT_STATUS_OK; /* Yes, treat as successful */ + } else 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 & FILE_ATTRIBUTE_SYSTEM)) { @@ -769,7 +779,10 @@ static NTSTATUS do_atar(const char *rnam } } - cli_close(cli, fnum); + if ((uint16_t)-1 != fnum) { /* did we actually open a file */ + cli_close(cli, fnum); /* Yes, close it */ + } + fnum = -1; if (shallitime) { @@ -1360,17 +1373,22 @@ int cmd_tarmode(void) tar_noisy=True; else if (strequal(buf, "quiet") || strequal(buf, "noverbose")) tar_noisy=False; + else if (strequal(buf, "errorskip")) + tar_errskip = True; + else if (strequal(buf, "noerrorskip")) + tar_errskip = False; else DEBUG(0, ("tarmode: unrecognised option %s\n", buf)); TALLOC_FREE(buf); } - DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n", + DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s, %s\n", tar_inc ? "incremental" : "full", tar_system ? "system" : "nosystem", tar_hidden ? "hidden" : "nohidden", tar_reset ? "reset" : "noreset", - tar_noisy ? "verbose" : "quiet")); + tar_noisy ? "verbose" : "quiet", + tar_errskip ? "errorskip" : "noerrorskip")); return 0; } @@ -1528,6 +1546,8 @@ int process_tar(void) { TALLOC_CTX *ctx = talloc_tos(); int rc = 0; + tarskip = 0; + initarbuf(); switch(tar_type) { case 'x': @@ -1631,6 +1651,10 @@ int process_tar(void) if (ntarf) { dotareof(tarhandle); } + /* After tarhandle is closed, BACKUPPC ignores DEBUG messaages */ + if (0 != tarskip) { + DEBUG(0, (" %d files skipped on access errors\n", tarskip)); + } close(tarhandle); SAFE_FREE(tarbuf);