#include "includes.h"
#include "clitar.h"
+static int clipfind(char **aret, int ret, char *tok);
+
typedef struct file_info_struct file_info2;
struct file_info_struct
#define CLIENT_TIMEOUT (30*1000)
#endif
-static char *tarbuf;
+static char *tarbuf, *buffer_p;
static int tp, ntarf, tbufsiz, ttarf;
/* Incremental mode */
BOOL tar_inc=False;
#ifdef HAVE_REGEX_H
regex_t *preg;
#endif
+/* Do not dump anything, just calculate sizes */
+BOOL dry_run=False;
/* Dump files with System attribute */
BOOL tar_system=True;
/* Dump files with Hidden attribute */
BOOL tar_hidden=True;
/* Be noisy - make a catalogue */
BOOL tar_noisy=True;
-BOOL tar_real_noisy=True;
+BOOL tar_real_noisy=False; /* Don't want to be really noisy by default */
char tar_type='\0';
static char **cliplist=NULL;
fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum));
- DEBUG(5, ("checksum totals chk=%d fchk=%d chksum=%s\n",
+ DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n",
chk, fchk, hb->dbuf.chksum));
if (fchk != chk)
{
- DEBUG(0, ("checksums don't match %d %d\n", fchk, chk));
-/* for (i = 0; i < sizeof(hb -> dummy); i++) {
- fprintf(stdout, "%2X ", hb -> dummy[i]);
- }
- fprintf(stdout, "\n");
- fprintf(stdout, "%s\n", hb -> dummy);
- fprintf(stdout, "Tarbuf = %X, hb = %X\n", (int)tarbuf, (int)hb);*/
+ DEBUG(0, ("checksums don't match %ld %ld\n", fchk, chk));
+ dump_data(5, (char *)hb - TBLOCK, TBLOCK *3);
return -1;
}
unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name,
strlen(hb->dbuf.name) + 1, True);
-/* can't handle some links at present */
+ /* can't handle some links at present */
if ((hb->dbuf.linkflag != '0') && (hb -> dbuf.linkflag != '5')) {
if (hb->dbuf.linkflag == 0) {
DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n",
{
int fail=1, writ=n;
+ if (dry_run) {
+ return writ;
+ }
/* This routine and the next one should be the only ones that do write()s */
if (tp + n >= tbufsiz)
{
* used to round files to nearest block
* and to do tar EOFs */
+ if (dry_run)
+ return;
+
if (n+tp >= tbufsiz)
{
memset(tarbuf+tp, 0, tbufsiz-tp);
****************************************************************************/
static void dotareof(int f)
{
- struct stat stbuf;
+ SMB_STRUCT_STAT stbuf;
/* Two zero blocks at end of file, write out full buffer */
+ if (dry_run)
+ return;
+
(void) dozerobuf(f, TBLOCK);
(void) dozerobuf(f, TBLOCK);
- if (fstat(f, &stbuf) == -1)
+ if (sys_fstat(f, &stbuf) == -1)
{
DEBUG(0, ("Couldn't stat file handle\n"));
return;
while (--ndgs)
{
- if (isdigit(*p))
+ if (isdigit((int)*p))
value = (value << 3) | (long) (*p - '0');
p++;
SSVAL(outbuf,smb_vwv0,fnum);
put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
- DEBUG(3,("Setting date to %s (0x%X)",
+ DEBUG(3,("Setting date to %s (0x%lX)",
asctime(LocalTime(&finfo.mtime)),
finfo.mtime));
return True;
}
-int padit(char *buf, int bufsize, int padsize)
+static int padit(char *buf, int bufsize, int padsize)
{
int berr= 0;
int bytestowrite;
finfo.ctime = def_finfo.ctime;
}
-
+ if (dry_run)
+ {
+ DEBUG(3,("skipping file %s of size %d bytes\n",
+ finfo.name,
+ finfo.size));
+ shallitime=0;
+ ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK);
+ ntarf++;
+ return;
+ }
+
inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
SSVAL(outbuf,smb_vwv1,PTR_DIFF(p,outbuf) - 4);
memset(p,0,200);
p -= smb_wct;
- SSVAL(p,smb_wct,10);
+ SCVAL(p,smb_wct,10);
SSVAL(p,smb_vwv0,0xFF);
SSVAL(p,smb_vwv5,MIN(max_xmit-500,finfo.size));
SSVAL(p,smb_vwv9,MIN(0xFFFF,finfo.size));
int this_time;
/* if shallitime is true then we didn't skip */
- if (tar_reset) (void) do_setrattr(finfo.name, aARCH, ATTRRESET);
+ if (tar_reset && !dry_run)
+ (void) do_setrattr(finfo.name, aARCH, ATTRRESET);
GetTimeOfDay(&tp_end);
this_time =
* dos \'s in path. Kill any absolute path names. But only if first!
*/
- DEBUG(5, ("firstb=%X, secondb=%X, len=%i\n", tptr, fp, l));
+ DEBUG(5, ("firstb=%lX, secondb=%lX, len=%i\n", (long)tptr, (long)fp, l));
if (first) {
if (*fp == '.') {
}
}
-#if 0 /* Removed to get around gcc 'defined but not used' error. */
+#ifndef OLD_DOTARPUT
/****************************************************************************
Move to the next block in the buffer, which may mean read in another set of
-blocks.
+blocks. FIXME, we should allow more than one block to be skipped.
****************************************************************************/
-static int next_block(char *ltarbuf, char *bufferp, int bufsiz)
+static int next_block(char *ltarbuf, char **bufferp, int bufsiz)
{
int bufread, total = 0;
- if (bufferp >= (ltarbuf + bufsiz)) {
-
+ DEBUG(5, ("Advancing to next block: %0x\n", (unsigned int)*bufferp));
+ *bufferp += TBLOCK;
+ total = TBLOCK;
+
+ if (*bufferp >= (ltarbuf + bufsiz)) {
+
+ DEBUG(5, ("Reading more data into ltarbuf ...\n"));
+
+ total = 0;
+
for (bufread = read(tarhandle, ltarbuf, bufsiz); total < bufsiz; total += bufread) {
if (bufread <= 0) { /* An error, return false */
}
- bufferp = ltarbuf;
+ DEBUG(5, ("Total bytes read ... %i\n", total));
- }
- else {
-
- bufferp += TBLOCK;
+ *bufferp = ltarbuf;
}
- return(0);
+ return(total);
}
-static int skip_file(int skip)
+/* Skip a file, even if it includes a long file name? */
+static int skip_file(int skipsize)
{
+ int dsize = skipsize;
- return(0);
+ DEBUG(5, ("Skiping file. Size = %i\n", skipsize));
+
+ /* FIXME, we should skip more than one block at a time */
+
+ while (dsize > 0) {
+
+ if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
+
+ DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
+ return(False);
+
+ }
+
+ dsize -= TBLOCK;
+
+ }
+
+ return(True);
}
-static int get_file(file_info2 finfo)
+/* We get a file from the tar file and store it */
+static int get_file(file_info2 finfo, char * inbuf, char * outbuf)
{
+ int fsize = finfo.size;
+ int fnum, pos = 0, dsize = 0, rsize = 0, bpos = 0;
- return(0);
+ DEBUG(5, ("get_file: file: %s, size %i\n", finfo.name, fsize));
+
+ if (ensurepath(finfo.name, inbuf, outbuf) &&
+ !smbcreat(finfo, &fnum, inbuf, outbuf))
+ {
+ DEBUG(0, ("abandoning restore\n"));
+ return(False);
+ }
+
+ /* read the blocks from the tar file and write to the remote file */
+
+ rsize = fsize; /* This is how much to write */
+
+ while (rsize > 0) {
+
+ /* We can only write up to the end of the buffer */
+
+ dsize = MIN(tbufsiz - (buffer_p - tarbuf) - bpos, max_xmit - 50); /* Calculate the size to write */
+ dsize = MIN(dsize, rsize); /* Should be only what is left */
+ DEBUG(5, ("writing %i bytes, max_xmit = %i, bpos = %i ...\n", dsize, max_xmit, bpos));
+
+ if (!smbwrite(fnum, dsize, pos, 0, fsize - pos, buffer_p + bpos, inbuf, outbuf)) {
+
+ DEBUG(0, ("Error writing remote file\n"));
+ return 0;
+
+ }
+
+ rsize -= dsize;
+ pos += dsize;
+
+ /* Now figure out how much to move in the buffer */
+
+ /* FIXME, we should skip more than one block at a time */
+
+ /* First, skip any initial part of the part written that is left over */
+ /* from the end of the first TBLOCK */
+
+ if ((bpos) && ((bpos + dsize) >= TBLOCK)) {
+
+ dsize -= (TBLOCK - bpos); /* Get rid of the end of the first block */
+ bpos = 0;
+
+ if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) { /* and skip the block */
+ DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
+ return False;
+
+ }
+
+ }
+
+ while (dsize >= TBLOCK) {
+
+ if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) {
+
+ DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
+ return False;
+
+ }
+
+ dsize -= TBLOCK;
+
+ }
+
+ bpos = dsize;
+
+ }
+
+ /* Now close the file ... */
+
+ if (!smbshut(finfo, fnum, inbuf, outbuf)) {
+
+ DEBUG(0, ("Error closing remote file\n"));
+ return(False);
+
+ }
+
+ /* Now we update the creation date ... */
+
+ DEBUG(5, ("Updating creation date on %s\n", finfo.name));
+
+ if (!do_setrtime(finfo.name, finfo.mtime, True)) {
+
+ 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 */
+ }
+ }
+
+ ntarf++;
+
+ DEBUG(0, ("restore tar file %s of size %d bytes\n", finfo.name, finfo.size));
+
+ return(True);
}
-static int get_dir(file_info2 finfo)
+/* Create a directory. We just ensure that the path exists and return as there
+ is no file associated with a directory
+*/
+static int get_dir(file_info2 finfo, char * inbuf, char * outbuf)
{
- return(0);
+ DEBUG(5, ("Creating directory: %s\n", finfo.name));
-}
+ if (!ensurepath(finfo.name, inbuf, outbuf)) {
+
+ DEBUG(0, ("Problems creating directory\n"));
+ return(False);
+
+ }
+ return(True);
+}
+/* Get a file with a long file name ... first file has file name, next file
+ has the data. We only want the long file name, as the loop in do_tarput
+ will deal with the rest.
+*/
static char * get_longfilename(file_info2 finfo)
{
+ int namesize = finfo.size + strlen(cur_dir) + 2;
+ char *longname = malloc(namesize);
+ int offset = 0, left = finfo.size;
+ BOOL first = True;
- return(NULL);
+ DEBUG(5, ("Restoring a long file name: %s\n", finfo.name));
+ DEBUG(5, ("Len = %i\n", finfo.size));
-}
+ if (longname == NULL) {
+
+ DEBUG(0, ("could not allocate buffer of size %d for longname\n",
+ finfo.size + strlen(cur_dir) + 2));
+ return(NULL);
+ }
+
+ /* First, add cur_dir to the long file name */
+
+ if (strlen(cur_dir) > 0) {
+ strncpy(longname, cur_dir, namesize);
+ offset = strlen(cur_dir);
+ }
+
+ /* Loop through the blocks picking up the name */
-static char * bufferp;
+ while (left > 0) {
-static void do_tarput2(void)
+ if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
+
+ DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
+ return(NULL);
+
+ }
+
+ unfixtarname(longname + offset, buffer_p, MIN(TBLOCK, finfo.size), first--);
+ DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname, buffer_p));
+
+ offset += TBLOCK;
+ left -= TBLOCK;
+
+ }
+
+ return(longname);
+
+}
+
+static void do_tarput(void)
{
- file_info2 finfo, *finfo2;
+ file_info2 finfo;
struct timeval tp_start;
- char *inbuf, *outbuf, *longfilename = NULL;
+ char *inbuf, *outbuf, *longfilename = NULL, linkflag;
int skip = False;
GetTimeOfDay(&tp_start);
- bufferp = tarbuf + tbufsiz; /* init this to force first read */
+ DEBUG(5, ("RJS do_tarput called ...\n"));
+
+ buffer_p = tarbuf + tbufsiz; /* init this to force first read */
+#if 0 /* Fix later ... */
if (push_dir(&dir_stack, &finfo)) {
+ file_info2 *finfo2;
finfo2 = pop_dir(&dir_stack);
inbuf = top_dir_name(&dir_stack); /* FIXME */
}
}
+#endif
inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
}
- if (next_block(tarbuf, bufferp, tbufsiz) <= 0) {
+ /* Now read through those files ... */
+
+ while (True) {
- DEBUG(0, ("Empty file or short tar file: %s\n", strerror(errno)));
+ /* Get us to the next block, or the first block first time around */
- }
+ if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) {
- /* Now read through those files ... */
+ DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno)));
- while (True) {
+ return;
- switch (readtarheader((union hblock *) bufferp, &finfo, cur_dir)) {
+ }
+
+ DEBUG(5, ("Reading the next header ...\n"));
+
+ switch (readtarheader((union hblock *) buffer_p, &finfo, cur_dir)) {
case -2: /* Hmm, not good, but not fatal */
DEBUG(0, ("Skipping %s...\n", finfo.name));
- if ((next_block(tarbuf, bufferp, tbufsiz) <= 0) &&
+ if ((next_block(tarbuf, &buffer_p, tbufsiz) <= 0) &&
!skip_file(finfo.size)) {
DEBUG(0, ("Short file, bailing out...\n"));
free(inbuf); free(outbuf);
- continue;
+ return;
}
free(inbuf); free(outbuf);
return; /* Hmmm, bad here ... */
- default:
+ default:
+ /* No action */
+
break;
}
/* Now, do we have a long file name? */
if (longfilename != NULL) {
- if (strlen(longfilename) < sizeof(finfo.name)) { /* if we have space */
- strncpy(finfo.name, longfilename, sizeof(finfo.name) - 1);
- free(longfilename);
- longfilename = NULL;
+ free(finfo.name); /* Free the space already allocated */
+ finfo.name = longfilename;
+ longfilename = NULL;
- }
- else {
+ }
- DEBUG(0, ("filename: %s too long, skipping\n", strlen(longfilename)));
- skip = True;
+ /* Well, now we have a header, process the file ... */
- }
- }
+ /* Should we skip the file? We have the long name as well here */
- /* Well, now we have a header, process the file ... */
+ skip = clipn &&
+ ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl)
+#ifdef HAVE_REGEX_H
+ || (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0)));
+#else
+ || (tar_re_search && mask_match(finfo.name, cliplist[0], True, False)));
+#endif
- /* Should we skip the file? */
+ DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip, (cliplist?cliplist[0]:NULL), finfo.name));
- if (skip) {
+ if (skip) {
- skip_file(finfo.size);
- continue;
+ skip_file(finfo.size);
+ continue;
- }
+ }
/* We only get this far if we should process the file */
+ linkflag = ((union hblock *)buffer_p) -> dbuf.linkflag;
- switch (((union hblock *)bufferp) -> dbuf.linkflag) {
+ switch (linkflag) {
case '0': /* Should use symbolic names--FIXME */
- get_file(finfo);
+
+ /* Skip to the next block first, so we can get the file, FIXME, should
+ be in get_file ... */
+
+ if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) {
+ DEBUG(0, ("Short file, bailing out...\n"));
+ free(inbuf); free(outbuf);
+ return;
+ }
+ if (!get_file(finfo, inbuf, outbuf)) {
+
+ free(inbuf); free(outbuf);
+ DEBUG(0, ("Abandoning restore\n"));
+ return;
+
+ }
break;
case '5':
- get_dir(finfo);
+ if (!get_dir(finfo, inbuf, outbuf)) {
+ free(inbuf); free(outbuf);
+ DEBUG(0, ("Abandoning restore \n"));
+ return;
+ }
break;
case 'L':
longfilename = get_longfilename(finfo);
+ if (!longfilename) {
+ free(inbuf); free(outbuf);
+ DEBUG(0, ("abandoning restore\n"));
+ return;
+
+ }
+ DEBUG(5, ("Long file name: %s\n", longfilename));
break;
default:
}
-#endif /* Removed to get around gcc 'defined but not used' error. */
+
+#else
static void do_tarput()
{
/* These should be the only reads in clitar.c */
while ((bufread=read(tarhandle, tarbuf, tbufsiz))>0) {
- char *buffer_p, *endofbuffer;
+ char *endofbuffer;
int chunk;
/* Code to handle a short read.
finfo.name = NULL;
}
- DEBUG(5, ("Tarbuf=%X, buffer=%X, endofbuf=%X\n", tarbuf, buffer_p, endofbuffer));
+ DEBUG(5, ("Tarbuf=%X, buffer=%X, endofbuf=%X\n",
+ (int)tarbuf, (int)buffer_p, (int)endofbuffer));
switch (readtarheader((union hblock *) buffer_p, &finfo, cur_dir))
{
case -2: /* something dodgy but not fatal about this */
cp = longname + strlen(cur_dir);
file_len = finfo.size;
- DEBUG(5, ("longname=%0X, cp=%0X, file_len=%i\n", longname, cp, file_len));
+ DEBUG(5, ("longname=%0X, cp=%0X, file_len=%i\n",
+ (int)longname, (int)cp, file_len));
while (file_len > 0) {
cp = cp + strlen(cp); /* Move to end of string */
buffer_p += TBLOCK;
file_len -= TBLOCK;
- DEBUG(5, ("cp=%0X, file_len=%i\n", cp, file_len));
+ DEBUG(5, ("cp=%0X, file_len=%i\n", (int)cp, file_len));
next_header = 1; /* Force read of next header */
}
}
if (fsize % TBLOCK) buffer_p+=TBLOCK - (fsize % TBLOCK);
DEBUG(5, ("buffer_p is now %d (psn=%d)\n",
- (long) buffer_p, (long)(buffer_p - tarbuf)));
+ (int) buffer_p, (int)(buffer_p - tarbuf)));
ntarf++;
fsize=0;
free(inbuf); free(outbuf);
}
+#endif
/*
* samba interactive commands
fstring buf;
int block;
- if (!next_token(NULL,buf,NULL))
+ if (!next_token(NULL,buf,NULL,sizeof(buf)))
{
DEBUG(0, ("blocksize <n>\n"));
return;
{
fstring buf;
- while (next_token(NULL,buf,NULL)) {
+ while (next_token(NULL,buf,NULL,sizeof(buf))) {
if (strequal(buf, "full"))
tar_inc=False;
else if (strequal(buf, "inc"))
attra[0] = attra[1] = 0;
- if (!next_token(NULL,buf,NULL))
+ if (!next_token(NULL,buf,NULL,sizeof(buf)))
{
DEBUG(0, ("setmode <filename> <perm=[+|-]rsha>\n"));
return;
safe_strcpy(fname, cur_dir, sizeof(pstring));
safe_strcat(fname, buf, sizeof(pstring));
- while (next_token(NULL,buf,NULL)) {
+ while (next_token(NULL,buf,NULL,sizeof(buf))) {
q=buf;
while(*q)
char **argl;
int argcl;
- if (!next_token(NULL,buf,NULL))
+ if (!next_token(NULL,buf,NULL,sizeof(buf)))
{
- DEBUG(0,("tar <c|x>[IXbga] <filename>\n"));
+ DEBUG(0,("tar <c|x>[IXbgan] <filename>\n"));
return;
}
/****************************************************************************
Find a token (filename) in a clip list
***************************************************************************/
-int clipfind(char **aret, int ret, char *tok)
+static int clipfind(char **aret, int ret, char *tok)
{
if (aret==NULL) return 0;
*/
tar_type='\0';
tar_excl=True;
+ dry_run=False;
while (*Optarg)
switch(*Optarg++) {
DEBUG(0,("Option N must be followed by valid file name\n"));
return 0;
} else {
- struct stat stbuf;
+ SMB_STRUCT_STAT stbuf;
extern time_t newer_than;
- if (sys_stat(argv[Optind], &stbuf) == 0) {
+ if (dos_stat(argv[Optind], &stbuf) == 0) {
newer_than = stbuf.st_mtime;
DEBUG(1,("Getting files newer than %s",
asctime(LocalTime(&newer_than))));
DEBUG(0, ("tar_re_search set\n"));
tar_re_search = True;
break;
+ case 'n':
+ if (tar_type == 'c') {
+ DEBUG(0, ("dry_run set\n"));
+ dry_run = True;
+ } else {
+ DEBUG(0, ("n is only meaningful when creating a tar-file\n"));
+ return 0;
+ }
+ break;
default:
DEBUG(0,("Unknown tar option\n"));
return 0;
/* Sets tar handle to either 0 or 1, as appropriate */
tarhandle=(tar_type=='c');
} else {
+ if (tar_type=='c' && (dry_run || strcmp(argv[Optind], "/dev/null")==0))
+ {
+ if (!dry_run) {
+ DEBUG(0,("Output is /dev/null, assuming dry_run"));
+ dry_run = True;
+ }
+ tarhandle=-1;
+ } else
if ((tar_type=='x' && (tarhandle = open(argv[Optind], O_RDONLY)) == -1)
|| (tar_type=='c' && (tarhandle=creat(argv[Optind], 0644)) < 0))
{