/**************************************************************************** Write a tar header to buffer ****************************************************************************/ static void writetarheader(int f, char *aname, SMB_BIG_UINT size, time_t mtime, char *amode, unsigned char ftype) { union hblock hb; int i, chk, l; char *jp; DEBUG(5, ("WriteTarHdr, Type = %c, Size= %.0f, Name = %s\n", ftype, (double)size, aname)); memset(hb.dummy, 0, sizeof(hb.dummy)); l=strlen(aname); if (l >= NAMSIZ) { /* write a GNU tar style long header */ char *b; b = (char *)malloc(l+TBLOCK+100); if (!b) { DEBUG(0,("out of memory\n")); exit(1); } writetarheader(f, "/./@LongLink", l+1, 0, " 0 \0", 'L'); memset(b, 0, l+TBLOCK+100); fixtarname(b, aname, l); i = strlen(b)+1; DEBUG(5, ("File name in tar file: %s, size=%d, \n", b, (int)strlen(b))); dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1)); free(b); } /* use l + 1 to do the null too */ fixtarname(hb.dbuf.name, aname, (l >= NAMSIZ) ? NAMSIZ : l + 1); if (lowercase) strlower(hb.dbuf.name); /* write out a "standard" tar format header */ hb.dbuf.name[NAMSIZ-1]='\0'; safe_strcpy(hb.dbuf.mode, amode, strlen(amode)); 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); oct_it((SMB_BIG_UINT) mtime, 13, hb.dbuf.mtime); memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum)); memset(hb.dbuf.linkname, 0, NAMSIZ); hb.dbuf.linkflag=ftype; 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); hb.dbuf.chksum[6] = '\0'; (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy)); }
static int padit(char *buf, int bufsize, int padsize) { int berr= 0; int bytestowrite; DEBUG(5, ("Padding with %d zeros\n", padsize)); memset(buf, 0, bufsize); while( !berr && padsize > 0 ) { bytestowrite= MIN(bufsize, padsize); berr = dotarbuf(tarhandle, buf, bytestowrite) != bytestowrite; padsize -= bytestowrite; } return berr; }
static void do_atar(char *rname,char *lname,file_info *finfo1) { int fnum; SMB_BIG_UINT nread=0; char ftype; file_info2 finfo; BOOL close_done = False; BOOL shallitime=True; char data[65520]; int read_size = 65520; int datalen=0; struct timeval tp_start; GetTimeOfDay(&tp_start); ftype = '0'; /* An ordinary file ... */ if (finfo1) { finfo.size = finfo1 -> size; finfo.mode = finfo1 -> mode; finfo.uid = finfo1 -> uid; finfo.gid = finfo1 -> gid; finfo.mtime = finfo1 -> mtime; finfo.atime = finfo1 -> atime; finfo.ctime = finfo1 -> ctime; finfo.name = finfo1 -> name; } else { finfo.size = def_finfo.size; finfo.mode = def_finfo.mode; finfo.uid = def_finfo.uid; finfo.gid = def_finfo.gid; finfo.mtime = def_finfo.mtime; finfo.atime = def_finfo.atime; finfo.ctime = def_finfo.ctime; finfo.name = def_finfo.name; } if (dry_run) { DEBUG(3,("skipping file %s of size %12.0f bytes\n", finfo.name, (double)finfo.size)); shallitime=0; ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK); ntarf++; return; } fnum = cli_open(cli, rname, O_RDONLY, DENY_NONE); dos_clean_name(rname); if (fnum == -1) { DEBUG(0,("%s opening remote file %s (%s)\n", cli_errstr(cli),rname, cur_dir)); return; } finfo.name = string_create_s(strlen(rname)); if (finfo.name == NULL) { DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n")); return; } safe_strcpy(finfo.name,rname, strlen(rname)); if (!finfo1) { if (!cli_getattrE(cli, fnum, &finfo.mode, &finfo.size, NULL, &finfo.atime, &finfo.mtime)) { DEBUG(0, ("getattrE: %s\n", cli_errstr(cli))); return; } finfo.ctime = finfo.mtime; } DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode)); if (tar_inc && !(finfo.mode & aARCH)) { DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name)); shallitime=0; } else if (!tar_system && (finfo.mode & aSYSTEM)) { DEBUG(4, ("skipping %s - system bit is set\n", finfo.name)); shallitime=0; } else if (!tar_hidden && (finfo.mode & aHIDDEN)) { DEBUG(4, ("skipping %s - hidden bit is set\n", finfo.name)); shallitime=0; } else { DEBUG(3,("getting file %s of size %.0f bytes as a tar file %s", finfo.name, (double)finfo.size, lname)); /* write a tar header, don't bother with mode - just set to 100644 */ writetarheader(tarhandle, rname, finfo.size, finfo.mtime, "100644 \0", ftype); while (nread < finfo.size && !close_done) { DEBUG(3,("nread=%.0f\n",(double)nread)); datalen = cli_read(cli, fnum, data, nread, read_size); if (datalen == -1) { DEBUG(0,("Error reading file %s : %s\n", rname, cli_errstr(cli))); break; } nread += datalen; /* if file size has increased since we made file size query, truncate read so tar header for this file will be correct. */ if (nread > finfo.size) { datalen -= nread - finfo.size; DEBUG(0,("File size change - truncating %s to %.0f bytes\n", finfo.name, (double)finfo.size)); } /* add received bits of file to buffer - dotarbuf will * write out in 512 byte intervals */ if (dotarbuf(tarhandle,data,datalen) != datalen) { DEBUG(0,("Error writing to tar file - %s\n", strerror(errno))); break; } if (datalen == 0) { DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname)); break; } datalen=0; } /* pad tar file with zero's if we couldn't get entire file */ if (nread < finfo.size) { DEBUG(0, ("Didn't get entire file. size=%.0f, nread=%d\n", (double)finfo.size, (int)nread)); if (padit(data, sizeof(data), finfo.size - nread)) DEBUG(0,("Error writing tar file - %s\n", strerror(errno))); } /* round tar file to nearest block */ if (finfo.size % TBLOCK) dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK)); ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK); ntarf++; } cli_close(cli, fnum); if (shallitime) { struct timeval 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); GetTimeOfDay(&tp_end); this_time = (tp_end.tv_sec - tp_start.tv_sec)*1000 + (tp_end.tv_usec - tp_start.tv_usec)/1000; get_total_time_ms += this_time; get_total_size += finfo.size; if (tar_noisy) { DEBUG(0, ("%12.0f (%7.1f kb/s) %s\n", (double)finfo.size, finfo.size / MAX(0.001, (1.024*this_time)), finfo.name)); } /* Thanks to Carel-Jan Engel ([email protected]) for this one */ 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)))); } }
static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t mtime, const char *amode, unsigned char ftype) { union hblock hb; int i, chk, l; char *jp; DEBUG(5, ("WriteTarHdr, Type = %c, Size= %.0f, Name = %s\n", ftype, (double)size, aname)); memset(hb.dummy, 0, sizeof(hb.dummy)); l=strlen(aname); /* We will be prepending a '.' in fixtarheader so use +2 to * take care of the . and terminating zero. JRA. */ if (l+2 >= NAMSIZ) { /* write a GNU tar style long header */ char *b; b = (char *)malloc(l+TBLOCK+100); if (!b) { DEBUG(0,("out of memory\n")); exit(1); } writetarheader(f, "/./@LongLink", l+2, 0, " 0 \0", 'L'); memset(b, 0, l+TBLOCK+100); fixtarname(b, aname, l+2); i = strlen(b)+1; DEBUG(5, ("File name in tar file: %s, size=%d, \n", b, (int)strlen(b))); dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1)); SAFE_FREE(b); } fixtarname(hb.dbuf.name, aname, (l+2 >= NAMSIZ) ? NAMSIZ : l + 2); if (lowercase) strlower_m(hb.dbuf.name); /* 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) { /* This is a non-POSIX compatible extention to store files greater than 8GB. */ memset(hb.dbuf.size, 0, 4); hb.dbuf.size[0]=128; for (i = 8, jp=(char*)&size; i; i--) hb.dbuf.size[i+3] = *(jp++); } oct_it((SMB_BIG_UINT) mtime, 13, hb.dbuf.mtime); memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum)); memset(hb.dbuf.linkname, 0, NAMSIZ); hb.dbuf.linkflag=ftype; 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); hb.dbuf.chksum[6] = '\0'; (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy)); }