summaryrefslogtreecommitdiff
path: root/source3/client/clitar.c
diff options
context:
space:
mode:
authorRichard Sharpe <sharpe@samba.org>1998-05-05 13:03:44 +0000
committerRichard Sharpe <sharpe@samba.org>1998-05-05 13:03:44 +0000
commit38b8e524ea2911384a193e230ab66b0c77519e25 (patch)
treeee401438e4c0d5df9c683475c8b410683f23b261 /source3/client/clitar.c
parentf601e6e0484d77d2c43eab05f80bccf28c9055aa (diff)
downloadsamba-38b8e524ea2911384a193e230ab66b0c77519e25.tar.gz
samba-38b8e524ea2911384a193e230ab66b0c77519e25.tar.bz2
samba-38b8e524ea2911384a193e230ab66b0c77519e25.zip
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)
Diffstat (limited to 'source3/client/clitar.c')
-rw-r--r--source3/client/clitar.c407
1 files changed, 382 insertions, 25 deletions
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 <regex.h>
+#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<clipn; i++) {
- DEBUG(0,("arg %d = %s\n", i, cliplist[i]));
+ DEBUG(5,("arg %d = %s\n", i, cliplist[i]));
if (*(cliplist[i]+strlen(cliplist[i])-1)=='\\') {
*(cliplist[i]+strlen(cliplist[i])-1)='\0';
@@ -1932,6 +2255,10 @@ int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
}
tar_clipfl='X';
break;
+ case 'r':
+ DEBUG(0, ("tar_re_search set\n"));
+ tar_re_search = True;
+ break;
default:
DEBUG(0,("Unknown tar option\n"));
return 0;
@@ -1943,7 +2270,8 @@ int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
}
tar_excl=tar_clipfl!='X';
- if (Optind+1<argc) {
+
+ if (Optind+1<argc && !tar_re_search) { /* For backwards compatibility */
char *tmpstr;
char **tmplist;
int clipcount;
@@ -1977,6 +2305,35 @@ int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
}
cliplist = tmplist;
}
+
+ if (Optind+1<argc && tar_re_search) { /* Doing regular expression seaches */
+#ifdef HAVE_REGEX_H
+ int errcode;
+
+ if ((preg = (regex_t *)malloc(65536)) == NULL) {
+
+ DEBUG(0, ("Could not allocate buffer for regular expression search\n"));
+ return;
+
+ }
+
+ if (errcode = regcomp(preg, argv[Optind + 1], REG_EXTENDED)) {
+ char errstr[1024];
+ size_t errlen;
+
+ errlen = regerror(errcode, preg, errstr, sizeof(errstr) - 1);
+
+ DEBUG(0, ("Could not compile pattern buffer for re search: %s\n%s\n", argv[Optind + 1], errstr));
+ return;
+
+ }
+#endif
+
+ clipn=argc-Optind-1;
+ cliplist=argv+Optind+1;
+
+ }
+
if (Optind>=argc || !strcmp(argv[Optind], "-")) {
/* Sets tar handle to either 0 or 1, as appropriate */
tarhandle=(tar_type=='c');