📄 clitar.c
字号:
/* Unix SMB/CIFS implementation. Tar Extensions Copyright (C) Ricky Poulten 1995-1998 Copyright (C) Richard Sharpe 1998 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*//* The following changes developed by Richard Sharpe for Canon Information Systems Research Australia (CISRA) 1. Restore can now restore files with long file names 2. Save now saves directory information so that we can restore 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"#include "client/client_proto.h"static int clipfind(char **aret, int ret, char *tok);typedef struct file_info_struct file_info2;struct file_info_struct { SMB_OFF_T size; uint16 mode; uid_t uid; gid_t 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;#define SEPARATORS " \t\n\r"extern time_t newer_than;extern struct cli_state *cli;/* These defines are for the do_setrattr routine, to indicate * setting and reseting of file attributes in the function call */#define ATTRSET 1#define ATTRRESET 0static uint16 attribute = aDIR | aSYSTEM | aHIDDEN;#ifndef CLIENT_TIMEOUT#define CLIENT_TIMEOUT (30*1000)#endifstatic char *tarbuf, *buffer_p;static int tp, ntarf, tbufsiz;static double ttarf;/* Incremental mode */static BOOL tar_inc=False;/* Reset archive bit */static BOOL tar_reset=False;/* Include / exclude mode (true=include, false=exclude) */static BOOL tar_excl=True;/* use regular expressions for search on file names */static BOOL tar_re_search=False;/* Do not dump anything, just calculate sizes */static BOOL dry_run=False;/* Dump files with System attribute */static BOOL tar_system=True;/* Dump files with Hidden attribute */static BOOL tar_hidden=True;/* Be noisy - make a catalogue */static BOOL tar_noisy=True;static BOOL tar_real_noisy=False; /* Don't want to be really noisy by default */char tar_type='\0';static char **cliplist=NULL;static int clipn=0;static BOOL must_free_cliplist = False;extern file_info def_finfo;extern BOOL lowercase;extern uint16 cnum;extern BOOL readbraw_supported;extern int max_xmit;extern pstring cur_dir;extern int get_total_time_ms;extern int get_total_size;static int blocksize=20;static int tarhandle;static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t mtime, const char *amode, unsigned char ftype);static void do_atar(char *rname,char *lname,file_info *finfo1);static void do_tar(file_info *finfo);static void oct_it(SMB_BIG_UINT value, int ndgs, char *p);static void fixtarname(char *tptr, const char *fp, size_t l);static int dotarbuf(int f, char *b, int n);static void dozerobuf(int f, int n);static void dotareof(int f);static void initarbuf(void);/* restore functions */static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix);static long unoct(char *p, int ndgs);static void do_tarput(void);static void unfixtarname(char *tptr, char *fp, int l, BOOL first);/* * tar specific utitlities *//*******************************************************************Create a string of size size+1 (for the null)*******************************************************************/static char *string_create_s(int size){ char *tmp; tmp = (char *)SMB_MALLOC(size+1); if (tmp == NULL) { DEBUG(0, ("Out of memory in string_create_s\n")); } return(tmp);}/****************************************************************************Write a tar header to buffer****************************************************************************/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 *)SMB_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));}/****************************************************************************Read a tar header into a hblock structure, and validate***************************************************************************/static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix){ long chk, fchk; int i; char *jp; /* * read in a "standard" tar format header - we're not that interested * in that many fields, though */ /* check the checksum */ for (chk=0, i=sizeof(hb->dummy), jp=hb->dummy; --i>=0;) chk+=(0xFF & *jp++); if (chk == 0) return chk; /* compensate for blanks in chksum header */ for (i=sizeof(hb->dbuf.chksum), jp=hb->dbuf.chksum; --i>=0;) chk-=(0xFF & *jp++); chk += ' ' * sizeof(hb->dbuf.chksum); fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum)); 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 %ld %ld\n", fchk, chk)); dump_data(5, (char *)hb - TBLOCK, TBLOCK *3); 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); } safe_strcpy(finfo->name, prefix, strlen(prefix) + strlen(hb -> dbuf.name) + 3); /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */ unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name, strlen(hb->dbuf.name) + 1, True); /* 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", finfo->name)); } else { if (hb -> dbuf.linkflag == 'L') { /* We have a longlink */ /* Do nothing here at the moment. do_tarput will handle this as long as the longlink gets back to it, as it has to advance the buffer pointer, etc */ } else { DEBUG(0, ("this tar file appears to contain some kind \of link other than a GNUtar Longlink - ignoring\n")); return -2; } } } if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR) || (*(finfo->name+strlen(finfo->name)-1) == '\\')) { finfo->mode=aDIR; } else { finfo->mode=0; /* we don't care about mode at the moment, we'll * just make it a regular file */ } /* * Bug fix by richard@sj.co.uk * * REC: restore times correctly (as does tar) * We only get the modification time of the file; set the creation time * from the mod. time, and the access time to current time */ finfo->mtime = finfo->ctime = strtol(hb->dbuf.mtime, NULL, 8); finfo->atime = time(NULL); finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size)); return True;}/****************************************************************************Write out the tar buffer to tape or wherever****************************************************************************/static int dotarbuf(int f, char *b, int 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) { int diff; diff=tbufsiz-tp; memcpy(tarbuf + tp, b, diff); fail=fail && (1+write(f, tarbuf, tbufsiz)); n-=diff; b+=diff; tp=0; while (n >= tbufsiz) { fail=fail && (1 + write(f, b, tbufsiz)); n-=tbufsiz; b+=tbufsiz; } } if (n>0) { memcpy(tarbuf+tp, b, n); tp+=n; } return(fail ? writ : 0);}/****************************************************************************Write zeros to buffer / tape****************************************************************************/static void dozerobuf(int f, int n){ /* short routine just to write out n zeros to buffer - * 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); write(f, tarbuf, tbufsiz); memset(tarbuf, 0, (tp+=n-tbufsiz)); } else { memset(tarbuf+tp, 0, n); tp+=n; }}/****************************************************************************Malloc tape buffer****************************************************************************/static void initarbuf(void){ /* initialize tar buffer */ tbufsiz=blocksize*TBLOCK; tarbuf=SMB_MALLOC(tbufsiz); /* FIXME: We might not get the buffer */ /* reset tar buffer pointer and tar file counter and total dumped */ tp=0; ntarf=0; ttarf=0;}/****************************************************************************Write two zero blocks at end of file****************************************************************************/static void dotareof(int f){ 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 (sys_fstat(f, &stbuf) == -1) { DEBUG(0, ("Couldn't stat file handle\n")); return; } /* Could be a pipe, in which case S_ISREG should fail, * and we should write out at full size */ if (tp > 0) write(f, tarbuf, S_ISREG(stbuf.st_mode) ? tp : tbufsiz);}/****************************************************************************(Un)mangle DOS pathname, make nonabsolute****************************************************************************/static void fixtarname(char *tptr, const char *fp, size_t l){ /* add a '.' to start of file name, convert from ugly dos \'s in path * to lovely unix /'s :-} */ *tptr++='.'; l--; StrnCpy(tptr, fp, l-1); string_replace(tptr, '\\', '/');}/****************************************************************************Convert from decimal to octal string****************************************************************************/static void oct_it (SMB_BIG_UINT value, int ndgs, char *p){ /* Converts long to octal string, pads with leading zeros */ /* skip final null, but do final space */ --ndgs; p[--ndgs] = ' '; /* Loop does at least one digit */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -