From 38b8e524ea2911384a193e230ab66b0c77519e25 Mon Sep 17 00:00:00 2001 From: Richard Sharpe Date: Tue, 5 May 1998 13:03:44 +0000 Subject: Added bug fixes to clitar to ensure proper longfile name restores occur. Also getting ready for setting directory dates correctly (This used to be commit fc0cad9035f9cbb5d8a5ee0221c342a3f90cf201) --- source3/client/clitar.c | 407 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 382 insertions(+), 25 deletions(-) (limited to 'source3/client/clitar.c') diff --git a/source3/client/clitar.c b/source3/client/clitar.c index 32731200b0..3169c37962 100644 --- a/source3/client/clitar.c +++ b/source3/client/clitar.c @@ -27,13 +27,47 @@ directory creation times 3. tar now accepts both UNIX path names and DOS path names. I prefer those lovely /'s to those UGLY \'s :-) + 4. the files to exclude can be specified as a regular expression by adding + an r flag to the other tar flags. Eg: + -TcrX file.tar "*.(obj|exe)" + + will skip all .obj and .exe files */ #include "includes.h" #include "clitar.h" +#ifdef HAVE_REGEX_H #include +#endif + +typedef struct file_info_struct file_info2; + +struct file_info_struct +{ + int size; + int mode; + int uid; + int gid; + /* These times are normally kept in GMT */ + time_t mtime; + time_t atime; + time_t ctime; + char *name; /* This is dynamically allocate */ + + file_info2 *next, *prev; /* Used in the stack ... */ + +}; + +typedef struct +{ + file_info2 *top; + int items; + +} stack; + +stack dir_stack = {NULL, 0}; /* Want an empty stack */ extern BOOL recurse; @@ -60,6 +94,11 @@ BOOL tar_inc=False; BOOL tar_reset=False; /* Include / exclude mode (true=include, false=exclude) */ BOOL tar_excl=True; +/* use regular expressions for search on file names */ +BOOL tar_re_search=False; +#ifdef HAVE_REGEX_H +regex_t *preg; +#endif /* Dump files with System attribute */ BOOL tar_system=False; /* Dump files with Hidden attribute */ @@ -86,18 +125,85 @@ int tarhandle; static void writetarheader(int f, char *aname, int size, time_t mtime, char *amode, unsigned char ftype); - -/* Forward references. */ +static void do_atar(); +static void do_tar(); +static void oct_it(long value, int ndgs, char *p); static void fixtarname(char *tptr, char *fp, int l); static int dotarbuf(int f, char *b, int n); -static void oct_it (long value, int ndgs, char *p); +static void dozerobuf(); +static void dotareof(); +static void initarbuf(); +static int do_setrattr(); + +/* restore functions */ +static long readtarheader(); static long unoct(char *p, int ndgs); +static void do_tarput(); static void unfixtarname(char *tptr, char *fp, int l); /* * tar specific utitlities */ +/* + * Stack routines, push_dir, pop_dir, top_dir_name + */ + +BOOL push_dir(stack *dir_stack, file_info2 *dir) +{ + dir -> next = dir_stack -> top; + dir -> prev = NULL; + dir_stack -> items++; + dir_stack -> top = dir; + return(True); + +} + +file_info2 *pop_dir(stack *dir_stack) +{ + file_info2 *ptr; + + ptr = dir_stack -> top; + if (dir_stack -> top != NULL) { + + dir_stack -> top = dir_stack -> top -> next; + dir_stack -> items--; + + } + + return ptr; + +} + +char *top_dir_name(stack *dir_stack) +{ + + return(dir_stack -> top != NULL?dir_stack -> top -> name:NULL); + +} + +BOOL sub_dir(char *dir1, char *dir2) +{ + +} + +/* Create a string of size size+1 (for the null) */ +char * string_create_s(int size) +{ + char *tmp; + + tmp = (char *)malloc(size+1); + + if (tmp == NULL) { + + DEBUG(0, ("Out of memory in string_create_s\n")); + + } + + return(tmp); + +} + /**************************************************************************** Write a tar header to buffer ****************************************************************************/ @@ -108,7 +214,7 @@ static void writetarheader(int f, char *aname, int size, time_t mtime, int i, chk, l; char *jp; - DEBUG(5, ("WriteTarHdr, Type = %c, Name = %s\n", ftype, aname)); + DEBUG(5, ("WriteTarHdr, Type = %c, Size= %i, Name = %s\n", ftype, size, aname)); memset(hb.dummy, 0, sizeof(hb.dummy)); @@ -125,6 +231,7 @@ static void writetarheader(int f, char *aname, int size, time_t mtime, memset(b, 0, l+TBLOCK+100); fixtarname(b, aname, l+1); i = strlen(b)+1; + DEBUG(5, ("File name in tar file: %s, size=%i, \n", b, strlen(b))); dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1)); free(b); } @@ -158,7 +265,7 @@ static void writetarheader(int f, char *aname, int size, time_t mtime, /**************************************************************************** Read a tar header into a hblock structure, and validate ***************************************************************************/ -static long readtarheader(union hblock *hb, file_info *finfo, char *prefix) +static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix) { long chk, fchk; int i; @@ -192,6 +299,13 @@ static long readtarheader(union hblock *hb, file_info *finfo, char *prefix) return -1; } + if ((finfo->name = string_create_s(strlen(prefix) + strlen(hb -> dbuf.name) + 3)) == NULL) { + + DEBUG(0, ("Out of space creating file_info2 for %s\n", hb -> dbuf.name)); + return(-1); + + } + strcpy(finfo->name, prefix); /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */ @@ -298,7 +412,7 @@ static void dozerobuf(int f, int n) /**************************************************************************** Malloc tape buffer ****************************************************************************/ -static void initarbuf(void) +static void initarbuf() { /* initialize tar buffer */ tbufsiz=blocksize*TBLOCK; @@ -447,6 +561,8 @@ static int do_setrtime(char *fname, int mtime) char *inbuf, *outbuf, *p; char *name; + DEBUG(5, ("Setting time on: %s, fnlen=%i.\n", fname, strlen(fname))); + name = (char *)malloc(strlen(fname) + 1 + 1); if (name == NULL) { @@ -600,7 +716,7 @@ static int do_setrattr(char *fname, int attr, int setit) /**************************************************************************** Create a file on a share ***************************************************************************/ -static BOOL smbcreat(file_info finfo, int *fnum, char *inbuf, char *outbuf) +static BOOL smbcreat(file_info2 finfo, int *fnum, char *inbuf, char *outbuf) { char *p; /* *must* be called with buffer ready malloc'ed */ @@ -680,7 +796,7 @@ static BOOL smbwrite(int fnum, int n, int low, int high, int left, /**************************************************************************** Close a file on a share ***************************************************************************/ -static BOOL smbshut(file_info finfo, int fnum, char *inbuf, char *outbuf) +static BOOL smbshut(file_info2 finfo, int fnum, char *inbuf, char *outbuf) { /* *must* be called with buffer ready malloc'ed */ @@ -775,11 +891,21 @@ static BOOL ensurepath(char *fname, char *inbuf, char *outbuf) /* *must* be called with buffer ready malloc'ed */ /* ensures path exists */ - pstring partpath, ffname; + char *partpath, *ffname; char *p=fname, *basehack; DEBUG(5, ( "Ensurepath called with: %s\n", fname)); + partpath = string_create_s(strlen(fname)); + ffname = string_create_s(strlen(fname)); + + if ((partpath == NULL) || (ffname == NULL)){ + + DEBUG(0, ("Out of memory in ensurepath: %s\n", fname)); + return(False); + + } + *partpath = 0; /* fname copied to ffname so can strtok */ @@ -821,7 +947,7 @@ int padit(char *buf, int bufsize, int padsize) int berr= 0; int bytestowrite; - DEBUG(0, ("Padding with %d zeros\n", padsize)); + DEBUG(5, ("Padding with %d zeros\n", padsize)); memset(buf, 0, bufsize); while( !berr && padsize > 0 ) { bytestowrite= MIN(bufsize, padsize); @@ -965,7 +1091,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1) datalen = 0; } - DEBUG(2,("getting file %s of size %d bytes as a tar file %s", + DEBUG(3,("getting file %s of size %d bytes as a tar file %s", finfo.name, finfo.size, lname)); @@ -1230,7 +1356,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1) get_total_size += finfo.size; /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */ - DEBUG(2,("(%g kb/s) (average %g kb/s)\n", + DEBUG(3,("(%g kb/s) (average %g kb/s)\n", finfo.size / MAX(0.001, (1.024*this_time)), get_total_size / MAX(0.001, (1.024*get_total_time_ms)))); if (tar_noisy) @@ -1265,7 +1391,14 @@ static void do_tar(file_info *finfo) strcat(exclaim, "\\"); strcat(exclaim, finfo->name); - if (clipfind(cliplist, clipn, exclaim)) { + DEBUG(5, ("...tar_re_search: %d\n", tar_re_search)); + + if ((!tar_re_search && clipfind(cliplist, clipn, exclaim)) || +#ifdef HAVE_REGEX_H + (tar_re_search && !regexec(preg, exclaim, 0, NULL, 0))) { +#else + (tar_re_search && mask_match(exclaim, cliplist[0], True, False))) { +#endif DEBUG(3,("Skipping file %s\n", exclaim)); return; } @@ -1345,9 +1478,178 @@ static void unfixtarname(char *tptr, char *fp, int l) } } -static void do_tarput(void) +/**************************************************************************** +Move to the next block in the buffer, which may mean read in another set of +blocks. +****************************************************************************/ +int next_block(char *tarbuf, char *bufferp, int bufsiz) { - file_info finfo; + int bufread, total = 0; + + if (bufferp >= (tarbuf + bufsiz)) { + + for (bufread = read(tarhandle, tarbuf, bufsiz); total += bufread; total < bufsiz) { + + if (bufread <= 0) { /* An error, return false */ + return (total > 0 ? -2 : bufread); + } + + } + + bufferp = tarbuf; + + } + else { + + bufferp += TBLOCK; + + } + +} + +int skip_file() +{ + +} + +int get_file(file_info2 finfo) +{ + + +} + +int get_dir(file_info2 finfo) +{ + +} + +char * get_longfilename(file_info2 finfo) +{ + +} + +static char * bufferp; + +static void do_tarput2() +{ + file_info2 finfo; + struct timeval tp_start; + char *inbuf, *outbuf, *longfilename = NULL; + int skip = False; + + GetTimeOfDay(&tp_start); + + bufferp = tarbuf + tbufsiz; /* init this to force first read */ + + inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); + + if (!inbuf || !outbuf) { + + DEBUG(0, ("Out of memory during allocate of inbuf and outbuf!\n")); + return; + + } + + if (next_block(tarbuf, bufferp, tbufsiz) <= 0) { + + DEBUG(0, ("Empty file or short tar file: %s\n", strerror(errno))); + + } + + /* Now read through those files ... */ + + while (True) { + + switch (readtarheader((union hblock *) bufferp, &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) && + !skip_file(finfo.size)) { + + DEBUG(0, ("Short file, bailing out...\n")); + free(inbuf); free(outbuf); + continue; + + } + + break; + + case -1: + DEBUG(0, ("abandoning restore, -1 from read tar header\n")); + free(inbuf); free(outbuf); + return; + + case 0: /* chksum is zero - looks like an EOF */ + DEBUG(0, ("total of %d tar files restored to share\n", ntarf)); + free(inbuf); free(outbuf); + return; /* Hmmm, bad here ... */ + + default: + 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; + + } + 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? */ + + if (skip) { + + skip_file(finfo); + continue; + + } + + /* We only get this far if we should process the file */ + + switch (((union hblock *)bufferp) -> dbuf.linkflag) { + + case '0': /* Should use symbolic names--FIXME */ + get_file(finfo); + break; + + case '5': + get_dir(finfo); + break; + + case 'L': + longfilename = get_longfilename(finfo); + break; + + default: + skip_file(finfo); /* Don't handle these yet */ + break; + + } + + } + + +} + +static void do_tarput() +{ + file_info2 finfo; int nread=0, bufread; char *inbuf,*outbuf, *longname = NULL; int fsize=0; @@ -1355,6 +1657,8 @@ static void do_tarput(void) struct timeval tp_start; BOOL tskip=False; /* We'll take each file as it comes */ + finfo.name = NULL; /* No name in here ... */ + GetTimeOfDay(&tp_start); inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN); @@ -1422,6 +1726,13 @@ static void do_tarput(void) } next_header = 0; /* Don't want the next one ... */ + + if (finfo.name != NULL) { /* Free the space */ + + free(finfo.name); + finfo.name = NULL; + + } switch (readtarheader((union hblock *) bufferp, &finfo, cur_dir)) { case -2: /* something dodgy but not fatal about this */ @@ -1451,7 +1762,10 @@ static void do_tarput(void) if (longname != NULL) { - strncpy(finfo.name, longname, sizeof(pstring) - 1); + free(finfo.name); /* Free the name in the finfo */ + finfo.name = string_create_s(strlen(longname) + 2); + strncpy(finfo.name, longname, strlen(longname) + 1); + DEBUG(5, ("Long name = \"%s\", filename=\"%s\"\n", longname, finfo.name)); free(longname); longname = NULL; @@ -1466,6 +1780,7 @@ static void do_tarput(void) fix the name and skip the name. Hmmm, what about end of buffer??? */ + DEBUG(5, ("Buffer size = %i\n", finfo.size + strlen(cur_dir) +1)); longname = malloc(finfo.size + strlen(cur_dir) + 1); if (longname == NULL) { @@ -1488,8 +1803,9 @@ static void do_tarput(void) } - strncpy(longname, cur_dir, strlen(cur_dir)); + strncpy(longname, cur_dir, strlen(cur_dir) + 1); unfixtarname(longname+strlen(cur_dir), bufferp, finfo.size); + DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname, bufferp)); /* Next rounds up to next TBLOCK and takes care of us being right on a TBLOCK boundary */ @@ -1500,7 +1816,12 @@ static void do_tarput(void) } } tskip=clipn - && (clipfind(cliplist, clipn, finfo.name) ^ tar_excl); + && ((!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 if (tskip) { bufferp+=TBLOCK; if (finfo.mode & aDIR) @@ -1522,9 +1843,10 @@ static void do_tarput(void) if (finfo.mode & aDIR) { + + DEBUG(5, ("Creating directory: %s\n", finfo.name)); + if (!ensurepath(finfo.name, inbuf, outbuf)) -/* if (!smbchkpath(finfo.name, inbuf, outbuf) - && !smbmkdir(finfo.name, inbuf, outbuf))*/ { DEBUG(0, ("abandoning restore, problems ensuring path\n")); free(inbuf); free(outbuf); @@ -1534,7 +1856,7 @@ static void do_tarput(void) { /* Now we update the creation date ... */ - DEBUG(5, ("Updating creation date on %s\n", finfo.name)); + DEBUG(0, ("Updating creation date on %s\n", finfo.name)); if (!do_setrtime(finfo.name, finfo.mtime)) { @@ -1562,13 +1884,13 @@ static void do_tarput(void) DEBUG(0 ,("restore tar file %s of size %d bytes\n", finfo.name,finfo.size)); - if (!finfo.size) { + /* if (!finfo.size) { if (!smbshut(finfo, fnum, inbuf, outbuf)){ DEBUG(0, ("Error closing remote file of length 0: %s\n", finfo.name)); free(inbuf);free(outbuf); return; } - } + } */ nread=0; if ((bufferp+=TBLOCK) >= endofbuffer) break; @@ -1614,6 +1936,7 @@ static void do_tarput(void) (long) bufferp, (long)(bufferp - tarbuf))); ntarf++; fsize=0; + } } while (bufferp < endofbuffer); } @@ -1791,7 +2114,7 @@ int process_tar(char *inbuf, char *outbuf) pstring tarmac; for (i=0; i=argc || !strcmp(argv[Optind], "-")) { /* Sets tar handle to either 0 or 1, as appropriate */ tarhandle=(tar_type=='c'); -- cgit