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

📄 create.c

📁 unix 下tar 执行程序的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		}


		clear_buffer(tempbuf);
		count = read(fd, tempbuf, bufsize);
		bcopy(tempbuf, start->charptr, RECORDSIZE);
		if (count < 0) 	{
			msg_perror("read error at byte %ld, reading %d bytes, in file %s", 
					fullsize - *sizeleft, bufsize, name);
			return 1;
		}
/*		if (amt_read >= RECORDSIZE) {
			amt_read = 0;
			userec(start+(count-1)/RECORDSIZE);
			if (count != bufsize) {
				msg("file %s shrunk by %d bytes, padding with zeros.", name, sizeleft);
				return 1;
			}
			start = findrec();
		} else 
			amt_read += bufsize;*/
		nwritten += count; /* XXX */
		*sizeleft -= count;
		userec(start);

	}
	free(sparsearray);
	printf ("Amount actually written is (I hope) %d.\n", nwritten);
/*	userec(start+(count-1)/RECORDSIZE);*/
	return 0;

}

init_sparsearray()
{
	register int i;

	sp_array_size = 10;
	/* 
	 * Make room for our scratch space -- initially is 10 elts long
	 */
	sparsearray = (struct sp_array *) malloc(sp_array_size * sizeof(struct sp_array));
	for (i = 0; i < sp_array_size; i++) {
		sparsearray[i].offset = 0;
		sparsearray[i].numbytes = 0;
	}
}



/*
 * Okay, we've got a sparse file on our hands -- now, what we need to do is
 * make a pass through the file and carefully note where any data is, i.e.,
 * we want to find how far into the file each instance of data is, and how
 * many bytes are there.  We store this information in the sparsearray,
 * which will later be translated into header information.  For now, we use
 * the sparsearray as convenient storage.
 *
 * As a side note, this routine is a mess.  If I could have found a cleaner
 * way to do it, I would have.  If anyone wants to find a nicer way to do
 * this, feel free.
 */

/* There is little point in trimming small amounts of null data at the */
 /* head and tail of blocks -- it's ok if we only avoid dumping blocks */
 /* of complete null data */
int
deal_with_sparse(name, header, nulls_at_end)
	char		*name;
	union record 	*header;
	
{
	long	numbytes = 0;
	long	offset = 0;
	long	save_offset;
	int	fd;
	int	current_size = hstat.st_size;
	int	sparse_ind = 0,
		cc;
	char	buf[RECORDSIZE];
	int	read_last_data = 0; /* did we just read the last record? */
	int 	amidst_data = 0;
	
	header->header.isextended = 0;
	/* 
	 * Can't open the file -- this problem will be caught later on,
	 * so just return.
	 */
	if ((fd = open(name, O_RDONLY)) < 0)
		return 0;
		
	init_sparsearray();
	clear_buffer(buf);

	while ((cc = read(fd, buf, sizeof buf)) != 0) {
			
		if (sparse_ind > sp_array_size-1) {
		
		/*
		 * realloc the scratch area, since we've run out of room --
		 */
			sparsearray = (struct sp_array *) 
					realloc(sparsearray,
 						2 * sp_array_size * (sizeof(struct sp_array)));
			sp_array_size *= 2;
		}
		if (cc == sizeof buf) {
			if (zero_record(buf)) {
				if (amidst_data) {
					sparsearray[sparse_ind++].numbytes
						= numbytes;
					amidst_data = 0;
				}
			} else {  /* !zero_record(buf) */
			        if (amidst_data)
				        numbytes += cc;
				else {
				        amidst_data = 1;
					numbytes = cc;
					sparsearray[sparse_ind].offset
					  = offset;
				} 
			}
		} else if (cc < sizeof buf) {
		  /* This has to be the last bit of the file, so this */
		  /* is somewhat shorter than the above. */
		        if (!zero_record(buf)) {
				if (!amidst_data) {
				        amidst_data = 1;
					numbytes = cc;
					sparsearray[sparse_ind].offset
					  = offset;
				} else
					numbytes += cc;
			} 
		}
		offset += cc;
		clear_buffer(buf);
	}
	if (amidst_data)
	        sparsearray[sparse_ind++].numbytes = numbytes;
	close(fd);

	return sparse_ind - 1;
}

/* 
 * Just zeroes out the buffer so we don't confuse ourselves with leftover
 * data.
 */
clear_buffer(buf)
	char	*buf;
{
	register int 	i;

	for (i = 0; i < RECORDSIZE; i++)
		buf[i] = '\0';
}

#if 0  /* I'm leaving this as a monument to Joy Kendall, who wrote it */
/* 
 * JK - 
 * This routine takes a character array, and tells where within that array
 * the data can be found.  It skips over any zeros, and sets the first
 * non-zero point in the array to be the "start", and continues until it
 * finds non-data again, which is marked as the "end."  This routine is 
 * mainly for 1) seeing how far into a file we must lseek to data, given
 * that we have a sparse file, and 2) determining the "real size" of the
 * file, i.e., the number of bytes in the sparse file that are data, as
 * opposed to the zeros we are trying to skip.
 */
where_is_data(from, to, buffer)
	int	*from,
		*to;
	char	*buffer;
{
	register int	i = 0;
	register int	save_to = *to;
	int	amidst_data = 0;

	
	while (!buffer[i])
		i++;
	*from = i;

	if (*from < 16)	/* don't bother */
		*from = 0;
	/* keep going to make sure there isn't more real
	   data in this record */
	while (i < RECORDSIZE) {
		if (!buffer[i]) {
			if (amidst_data) {
				save_to = i;
				amidst_data = 0;
			}
			i++;
		}
		else if (buffer[i]) {
			if (!amidst_data)
				amidst_data = 1;
			i++;
		}
	}
	if (i == RECORDSIZE)
		*to = i;
	else
		*to = save_to;
		
}
#endif

/* Note that this routine is only called if zero_record returned true */
#if 0 /* But we actually don't need it at all. */
where_is_data (from, to, buffer)
     int *from, *to;
     char *buffer;
{
  char *fp, *tp;

  for (fp = buffer; ! *fp; fp++)
    ;
  for (tp = buffer + RECORDSIZE - 1; ! *tp; tp--)
    ;
  *from = fp - buffer;
  *to = tp - buffer + 1;
}
#endif



/*
 * Takes a recordful of data and basically cruises through it to see if
 * it's made *entirely* of zeros, returning a 0 the instant it finds
 * something that is a non-zero, i.e., useful data.
 */
zero_record(buffer)
	char	*buffer;
{
	register int	i;

	for (i = 0; i < RECORDSIZE; i++)
		if (buffer[i] != '\000')
			return 0;
	return 1;
}

find_new_file_size(filesize, highest_index)
	int	*filesize;
	int	highest_index;
{
	register int 	i;

	*filesize = 0;
	for (i = 0; sparsearray[i].numbytes && i <= highest_index; i++)
		*filesize += sparsearray[i].numbytes;
}
	
/*
 * Make a header block for the file  name  whose stat info is  st .
 * Return header pointer for success, NULL if the name is too long.
 */
union record *
start_header(name, st)
	char	*name;
	register struct stat *st;
{
	register union record *header;

	header = (union record *) findrec();
	bzero(header->charptr, sizeof(*header)); /* XXX speed up */

	/*
	 * Check the file name and put it in the record.
	 */
	if(!f_absolute_paths) {
		static int warned_once = 0;
#ifdef __MSDOS__
		if(name[1]==':') {
			name+=2;
			if(!warned_once++)
				msg("Removing drive spec from names in the archive");
		}
#endif
		while ('/' == *name) {
			name++;				/* Force relative path */
			if (!warned_once++)
				msg("Removing leading / from absolute path names in the archive.");
		}
	}
	strncpy(header->header.name, name, NAMSIZ);
	if (header->header.name[NAMSIZ-1]) {
		char *mangled;

		/* next_mangle(header->header.name); */
		add_mangle(name,header->header.name);
		msg("%s: is too long: mangling to %s", name, header->header.name);
	}

	to_oct((long) (st->st_mode & ~S_IFMT),
					8,  header->header.mode);
	to_oct((long) st->st_uid,	8,  header->header.uid);
	to_oct((long) st->st_gid,	8,  header->header.gid);
	to_oct((long) st->st_size,	1+12, header->header.size);
	to_oct((long) st->st_mtime,	1+12, header->header.mtime);
	/* header->header.linkflag is left as null */
	if(f_gnudump) {
		to_oct((long) st->st_atime, 1+12, header->header.atime);
		to_oct((long) st->st_ctime, 1+12, header->header.ctime);
	}

#ifndef NONAMES
	/* Fill in new Unix Standard fields if desired. */
	if (f_standard) {
		header->header.linkflag = LF_NORMAL;	/* New default */
		strcpy(header->header.magic, TMAGIC);	/* Mark as Unix Std */
		finduname(header->header.uname, st->st_uid);
		findgname(header->header.gname, st->st_gid);
	}
#endif
	return header;
}

/* 
 * Finish off a filled-in header block and write it out.
 * We also print the file name and/or full info if verbose is on.
 */
void
finish_header(header)
	register union record *header;
{
	register int	i, sum;
	register char	*p;
	void bcopy();

	bcopy(CHKBLANKS, header->header.chksum, sizeof(header->header.chksum));

	sum = 0;
	p = header->charptr;
	for (i = sizeof(*header); --i >= 0; ) {
		/*
		 * We can't use unsigned char here because of old compilers,
		 * e.g. V7.
		 */
		sum += 0xFF & *p++;
	}

	/*
	 * Fill in the checksum field.  It's formatted differently
	 * from the other fields:  it has [6] digits, a null, then a
	 * space -- rather than digits, a space, then a null.
	 * We use to_oct then write the null in over to_oct's space.
	 * The final space is already there, from checksumming, and
	 * to_oct doesn't modify it.
	 *
	 * This is a fast way to do:
	 * (void) sprintf(header->header.chksum, "%6o", sum);
	 */
	to_oct((long) sum,	8,  header->header.chksum);
	header->header.chksum[6] = '\0';	/* Zap the space */

	userec(header);

	if (f_verbose) {
		extern union record *head;		/* Points to current tape header */
		extern int head_standard;		/* Tape header is in ANSI format */

		/* These globals are parameters to print_header, sigh */
		head = header;
		/* hstat is already set up */
		head_standard = f_standard;
		print_header();
	}

	return;
}


/*
 * Quick and dirty octal conversion.
 * Converts long "value" into a "digs"-digit field at "where",
 * including a trailing space and room for a null.  "digs"==3 means
 * 1 digit, a space, and room for a null.
 *
 * We assume the trailing null is already there and don't fill it in.
 * This fact is used by start_header and finish_header, so don't change it!
 *
 * This should be equivalent to:
 *	(void) sprintf(where, "%*lo ", digs-2, value);
 * except that sprintf fills in the trailing null and we don't.
 */
void
to_oct(value, digs, where)
	register long	value;
	register int	digs;
	register char	*where;
{
	
	--digs;				/* Trailing null slot is left alone */
	where[--digs] = ' ';		/* Put in the space, though */

	/* Produce the digits -- at least one */
	do {
		where[--digs] = '0' + (char)(value & 7); /* one octal digit */
		value >>= 3;
	} while (digs > 0 && value != 0);

	/* Leading spaces, if necessary */
	while (digs > 0)
		where[--digs] = ' ';

}


/*
 * Write the EOT record(s).
 * We actually zero at least one record, through the end of the block.
 * Old tar writes garbage after two zeroed records -- and PDtar used to.
 */
write_eot()
{
	union record *p;
	int bufsize;
	void bzero();

	p = findrec();
	if (p)
	  {
	    bufsize = endofrecs()->charptr - p->charptr;
	    bzero(p->charptr, bufsize);
	    userec(p);
	  }
}

⌨️ 快捷键说明

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