⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 btoa.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* btoa - binary to ascii	Authors: P. Rutter, J. Orost, & S. Parmark *//*************************************************************************     Btoa is a filter which reads binary  bytes  from  the  input     file  and generates printable ASCII characters on the output     file. It attaches a header and a checksum to the archive. It     can  also  reverse  this,  creating  a  binary file from the     archive.     Since last version of btoa/atob, several new  features  have     been  added.  The  most  obvious  one  is that atob has been     integrated with btoa. They are now the same program which is     called  with  different arguments. Another is the ability to     repair damaged archives.     The new version is compatible with the old version, that is,     it can still encode and decode old btoa files.     Btoa has an option to  decode  the  archive,  restoring  the     binary  bytes.   It  strips  the input file until it finds a     valid header, and continues decoding until the end  mark  is     found.  It  recognices  both old- and new-style headers, and     can decode both. It is possible to leave out the destination     name  when  decoding new-style archives, because the name is     stored in the header. Entering  a  name  will  override  the     autonaming function.     It is possible to leave out  the  file  names  and  redirect     stdin and stdout with '<' and '>' to the desired files. This     is to maintain compatibility with earlier versions of btoa.     Btoa now adds a single byte checksum  to  each  row  in  the     archive.   When  an  error is found, diagnosis automatically     starts and produces a diagnosis file which can  be  used  to     extract  the  damaged  part  from  an errorfree archive. The     extracted part can then  be  used  to  correct  the  damaged     archive.    Btoa  has  options  to  perform  the  reparation     automatically. This is especially  useful  when  downloading     data  converted to text files, and occasionally finding that     an archive file of considerable size turns is corrupted.FEATURES     Btoa encodes 4 binary bytes into 5 characters, expanding the     file  by  25%. As a special case 4 zeroes will be encoded as     'z' and 4 spaces as 'y'. This makes it possible to  compress     the archive a bit.EXAMPLES     Below follows a description  of  a  normal  repair  session.     Lines  beginning with 'Local>' were typed on the computer to     which the file was downloaded. Accordingly, lines  typed  on     the  connected computer will begin with 'Remote>'. Sending a     file to the other computer will be noted as 'transmit file'.     A normal repairing procedure is as follows: Local>  btoa  -a     file.btoa  btoa:  Bad checksum on line 2648.  btoa: Starting     diagnosis.  btoa: Diagnosis output  to  'btoa.dia'.   Local>     transmit btoa.dia     Remote> btoa -d file.btoa btoa: Repair output to 'btoa.rep'.     Remote> transmit btoa.rep     Local> btoa -a btoa.rep btoa: Repaired  archive  written  to     'btoa.rdy'.     You can now erase file.btoa and decode btoa.rdy using  'btoa     -a btoa.rdy'.*************************************************************************/#include <sys/types.h>#include <ctype.h>#include <string.h>#include <stdlib.h>#include <stdio.h>#define MAXPERLINE      78#define BUFSIZE         100#define TRUE            1#define FALSE           0#define USE_MACROS      TRUE#define BYTE            char#define WORD            short#define LONG            long#define ENCODE(ch)      ( (int) ((ch) + '!') )#define DECODE(ch)      ( (int) ((ch) - '!') )struct Diagnosis {  LONG startpos, endpos;	/* Line before and after erroneous area */  struct Diagnosis *next, *last;};/* Following functions have been converted to macros:  calcchecksum() */_PROTOTYPE(int main, (int argc, char **argv));_PROTOTYPE(BYTE btoa, (FILE *infile, BYTE *infilename));_PROTOTYPE(void printhelp, (void));_PROTOTYPE(void calcchecksum, (int ch));_PROTOTYPE(void wordout, (LONG codeword));_PROTOTYPE(void asciiout, (int ch));_PROTOTYPE(BYTE *truncname, (BYTE *name));_PROTOTYPE(BYTE atob, (FILE *infile));_PROTOTYPE(int nextbyte, (FILE *infile));_PROTOTYPE(BYTE new_decodefile, (FILE *infile, LONG *lastline, LONG filepos, int maxperline));_PROTOTYPE(BYTE old_decodefile, (FILE *infile, LONG *lastline));_PROTOTYPE(BYTE decode_line, (BYTE *buffer, int length));_PROTOTYPE(void producediag, (struct Diagnosis *diaglist, FILE *infile));_PROTOTYPE(void intodiaglist, (struct Diagnosis *diaglist, LONG startpos, LONG endpos));_PROTOTYPE(void outdiaglist, (struct Diagnosis *diaglist, LONG *startpos, LONG *endpos));_PROTOTYPE(BYTE copyfile, (FILE *infile, FILE *outfile, BYTE *searchstring));_PROTOTYPE(BYTE readbuffer, (BYTE *buffer, BYTE *errormsg, FILE *infile));_PROTOTYPE(FILE *fopen_read, (BYTE *filename));_PROTOTYPE(FILE *fopen_write, (BYTE *filename));_PROTOTYPE(BYTE pro_repair, (FILE *infile));_PROTOTYPE(BYTE performrepair, (FILE *infile));/* Chksum.h *//* Calcchecksum() was converted to a macro for effectivity reasons. *//* Don't (!!) give it an argument that has to be evaluated. This    *//* Is guaranteed to slow it down.                                   *//* Update file checksums. */#define calcchecksum(ch)        \{                               \  Ceor ^= ch;                   \  Csum += ch + 1;               \                                \  if (Crot & 0x80000000L)       \  {                             \    Crot <<= 1;                 \    Crot ++;                    \  }                             \  else                          \    Crot <<= 1;                 \                                \  Crot += ch;                   \}/* Btoa.c *//* Written by Paul Rutter, Joe Orost & Stefan Parmark. */#ifdef AMIGA#include <stdlib.h>#include <string.h>#endif /* AMIGA */#define VERSION  "5.2"LONG Ceor, Csum, Crot;		/* Checksums to verify archive validity. */BYTE new_version, openoutput, buffer[BUFSIZE];FILE *outfile;int main(argc, argv)int argc;char **argv;{  register BYTE openinput, error, ch, a_to_b, diag, repair;  register BYTE *infilename, *text;  register FILE *infile;#ifdef AMIGA  extern int _bufsiz;  /* Change file buffer size. */  _bufsiz = 10240;#endif /* AMIGA */  error = openinput = openoutput = a_to_b = diag = repair = FALSE;  new_version = TRUE;  infilename = NULL;  /* Scan for '-' options. The rest must be file names. */  while (!error && argc > 1 && *argv[1] == '-') {	text = &argv[1][1];	while (!error && (ch = *text++) != 0) {		switch (ch) {		    case 'a':	/* Activate atob. */			a_to_b = TRUE;			break;		    case 'd':	/* Extract missing part from				 * undamaged archive. */			diag = TRUE;			break;		    case 'h':	/* Print help and abort execution. */			error = TRUE;			break;		    case 'o':	/* Use old btoa format. */			new_version = FALSE;			break;		    case 'r':	/* Repair damaged archive. */			repair = TRUE;			break;		    default:	error = TRUE;		}	}	argv++;	argc--;  }  if (argc > 3) error = TRUE;  if (error)	printhelp();  else {	/* If file name was given, try to open file. Otherwise use stdin. */	if (argc > 1) {		infilename = argv[1];		if ((infile = fopen_read(infilename)) == NULL)			error = TRUE;		else			openinput = TRUE;	} else		infile = stdin;  }  if (!error) {	/* If file name was given, try to open file. Otherwise use stdout. */	if (argc > 2 && !diag && !repair) {		if ((outfile = fopen_write(argv[2])) == NULL)			error = TRUE;		else			openoutput = TRUE;	} else		outfile = stdout;  }  if (!error) {	if (diag)		error = pro_repair(infile);	else if (repair)		error = performrepair(infile);	else if (a_to_b)		error = atob(infile);	else		error = btoa(infile, infilename);  }  /* Close all opened files. */  if (openinput) fclose(infile);  if (openoutput) fclose(outfile);  if (error) exit(1);  return(0);}BYTE btoa(infile, infilename)register FILE *infile;register BYTE *infilename;{  register LONG codeword, filesize;  register int ch1, ch2, ch3, ch4, readbytes;  Ceor = Csum = Crot = 0;  /* Write archive header. */  if (new_version) {	fprintf(outfile, "xbtoa5 %d %s Begin\n", MAXPERLINE,		(infilename == NULL) ? "-" : truncname(infilename));  } else	fprintf(outfile, "xbtoa Begin\n");  /* Encode entire input file. */  filesize = 0;  do {	readbytes = fread(buffer, (size_t)1, (size_t)4, infile);	if (readbytes < 4) {		ch1 = (readbytes > 0) ? ((int) buffer[0] & 0xFF) : 0;		ch2 = (readbytes > 1) ? ((int) buffer[1] & 0xFF) : 0;		ch3 = (readbytes > 2) ? ((int) buffer[2] & 0xFF) : 0;		ch4 = 0;	} else {		ch1 = (int) buffer[0] & 0xFF;		ch2 = (int) buffer[1] & 0xFF;		ch3 = (int) buffer[2] & 0xFF;		ch4 = (int) buffer[3] & 0xFF;	}	if (readbytes > 0) {		if (!new_version) {			calcchecksum(ch1);			calcchecksum(ch2);			calcchecksum(ch3);			calcchecksum(ch4);		}		codeword = (ch1 << 8) | ch2;		codeword = (((codeword << 8) | ch3) << 8) | ch4;		wordout(codeword);		filesize += readbytes;	}  }  while (readbytes == 4);  asciiout(EOF);		/* Flush buffer. */  /* Filesize is written twice as crude cross check. */  fprintf(outfile, "xbtoa End N %ld %lx E %lx S %lx R %lx\n",	filesize, filesize, Ceor, Csum, Crot);  return(FALSE);		/* No errors discovered. */}/* Print help on how to use btoa. */void printhelp(){  fprintf(stderr, "              Btoa version %s\n", VERSION);  fprintf(stderr, "Written by Paul Rutter, Joe Orost & Stefan Parmark.\n");  fprintf(stderr, "\nUsage: btoa [-{adhor}] [input file] [output file]\n");  fprintf(stderr, "\nOptions:\n");  fprintf(stderr, "-h  Shows this help list.\n");  fprintf(stderr, "-a  Use atob rather than btoa.\n");  fprintf(stderr, "-o  Use old version of btoa.\n");  fprintf(stderr, "-d  Extract repair file from diag file.\n");  fprintf(stderr, "-r  Repair archive from repair file.\n");  fprintf(stderr, "\nExamples:\n");  fprintf(stderr, "  btoa -h\n");  fprintf(stderr, "  btoa [input binary file] [output archive file]\n");  fprintf(stderr, "  btoa -o [input binary file] [output archive file]\n");  fprintf(stderr, "  btoa -a [input archive file] [output binary file]\n");  fprintf(stderr, "  btoa -d [undamaged archive file]\n");  fprintf(stderr, "  btoa -r [damaged archive file]\n");}#if !USE_MACROS/* Update file checksums. */void calcchecksum(ch)register int ch;{  Ceor ^= ch;  Csum += ch + 1;  if (Crot & 0x80000000L) ch++;  Crot <<= 1;  Crot += ch;}#endif /* !USE_MACROS *//* Encode 4 binary bytes to 5 ascii bytes. */void wordout(codeword)register LONG codeword;{  register int tmp, quote;  if (codeword == 0)		/* Encode 4 zeros as a 'z'. */	asciiout('z');  else if (new_version && codeword == 0x20202020)	/* Encode 4 spaces as a 'y'. */	asciiout('y');  else {	tmp = 0;	/* Extra calculations because some machines don't support */	/* Unsigned longwords.                                    */	if (codeword < 0) {		tmp = 32;		codeword -= (LONG) (85L * 85 * 85 * 85 * 32);	}	if (codeword < 0) {		tmp = 64;		codeword -= (LONG) (85L * 85 * 85 * 85 * 32);	}	/* Write 5 ascii bytes representing 4 binary bytes. */	quote = codeword / (LONG) (85L * 85 * 85 * 85);	codeword -= quote * (LONG) (85L * 85 * 85 * 85);	asciiout(ENCODE(quote + tmp));	quote = codeword / (LONG) (85L * 85 * 85);	codeword -= quote * (LONG) (85L * 85 * 85);	asciiout(ENCODE(quote));	quote = codeword / (LONG) (85L * 85);	codeword -= quote * (LONG) (85L * 85);	asciiout(ENCODE(quote));	quote = (int) codeword / 85;	codeword -= quote * 85;	asciiout(ENCODE(quote));	asciiout(ENCODE((int) codeword));  }}/* Write ch to outfile. Write '\n' for every line. */void asciiout(ch)register int ch;{  static WORD linepos = 0;  if (ch == EOF) {		/* Signal to flush buffer. */	/* Linepos == 0 means '\n' just written in asciiout(). This */	/* Avoids bug in BITNET, which changes blank line to spaces. */	if (linepos != 0) {		if (new_version)			fputc(ENCODE(Csum % 85), outfile);	/* Checksum for every								 * line. */		fputc('\n', outfile);	}  } else {	fputc(ch, outfile);	linepos++;	if (new_version) {		calcchecksum(ch);		if (linepos >= (MAXPERLINE - 1)) {			fputc(ENCODE(Csum % 85), outfile);	/* Checksum for every								 * line. */			fputc('\n', outfile);			linepos = 0;		}	} else	 /* Old version */ if (linepos >= MAXPERLINE) {		fputc('\n', outfile);		linepos = 0;	}  }}/* Remove paths from a file name. */BYTE *truncname(name)register BYTE *name;{  register BYTE ch, *newname;  newname = name;  while ((ch = *name++) != 0)	if (ch == '/' || ch == ':') newname = name;  return(newname);}/* Atob.c *//* Written by Paul Rutter, Joe Orost & Stefan Parmark. */#ifdef AMIGA#include <stdlib.h>#include <string.h>#endif /* AMIGA */BYTE atob(infile)register FILE *infile;{  register BYTE error;  register LONG filepos;  int maxperline;  LONG n1, n2, oeor, osum, orot, lastline;  static BYTE outfilename[BUFSIZE];  error = FALSE;  /* Search for archive header. */  do {	filepos = ftell(infile);	if (readbuffer(buffer, "archive", infile)) error = TRUE;  }  while (!(error || strncmp(buffer, "xbtoa", (size_t)5) == 0));  if (!error)	if (strcmp(buffer, "xbtoa Begin\n") == 0) {		new_version = FALSE;		fprintf(stderr, "btoa: Old btoa format.\n");	} else if (sscanf(buffer, "xbtoa5 %d %s Begin\n", &maxperline, outfilename) == 2) {		new_version = TRUE;		/* Naming a file overrides the read-name-from-file		 * function. */		if (!openoutput && strcmp(outfilename, "-") != 0)			if ((outfile = fopen_write(outfilename)) == NULL)				error = TRUE;			else				openoutput = TRUE;	} else {		fprintf(stderr, "btoa: Illegal archive header.\n");		error = TRUE;	}  if (!error) {	Ceor = Csum = Crot = 0;	if (new_version)		error = new_decodefile(infile, &lastline, filepos, maxperline);	else		error = old_decodefile(infile, &lastline);  }  if (!error) {	if (sscanf(buffer, "xbtoa End N %ld %lx E %lx S %lx R %lx\n",		   &n1, &n2, &oeor, &osum, &orot) != 5) {		fprintf(stderr, "btoa: Bad format on line %ld. Can't repair file.\n",			lastline);		error = TRUE;	} else if ((n1 != n2) || (oeor != Ceor) || (osum != Csum) || (orot != Crot)) {		fprintf(stderr, "btoa: Bad file checksum. Can't repair file.\n");		error = TRUE;	} else		/* Flush last characters. */		decode_line((BYTE *) NULL, (int) ((n1 - 1) & 0x03));  }  return(error);}/* Peek at the next byte without moving the file pointer. */int nextbyte(infile)register FILE *infile;{  register int ch;  register LONG filepos;  filepos = ftell(infile);  ch = fgetc(infile);  fseek(infile, filepos, 0);  return(ch);}BYTE new_decodefile(infile, lastline, filepos, maxperline)register FILE *infile;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -