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

📄 create.c

📁 speech signal process tools
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Create a tar archive.   Copyright (C) 1988 Free Software FoundationThis file is part of GNU Tar.GNU Tar is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 1, or (at your option)any later version.GNU Tar is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Tar; see the file COPYING.  If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  *//* * Create a tar archive. * * Written 25 Aug 1985 by John Gilmore, ihnp4!hoptoad!gnu. * * @(#)create.c 1.36 11/6/87 - gnu */#include <sys/types.h>#include <sys/stat.h>#include <sys/file.h>#include <stdio.h>/* JF: this one is my fault *//* #include "utils.h" */#ifndef V7#include <fcntl.h>#endif#ifndef	MSDOS#include <pwd.h>#include <grp.h>#endif#ifdef BSD42#include <sys/dir.h>#else#ifdef MSDOS#include <sys/dir.h>#else#ifdef USG#ifdef NDIR#include <ndir.h>#else#include <dirent.h>#endif#ifndef DIRECT#define direct dirent#endif#define DP_NAMELEN(x) strlen((x)->d_name)#else/* * FIXME: On other systems there is no standard place for the header file * for the portable directory access routines.  Change the #include line * below to bring it in from wherever it is. */#include "ndir.h"#endif#endif#endif#ifndef DP_NAMELEN#define DP_NAMELEN(x)	(x)->d_namlen#endif#ifdef USG#include <sys/sysmacros.h>	/* major() and minor() defined here */#endif/* * V7 doesn't have a #define for this. */#ifndef O_RDONLY#define	O_RDONLY	0#endif/* * Most people don't have a #define for this. */#ifndef	O_BINARY#define	O_BINARY	0#endif#include "tar.h"#include "port.h"extern union record *head;		/* Points to current tape header */extern struct stat hstat;		/* Stat struct corresponding */extern int head_standard;		/* Tape header is in ANSI format */extern dev_t ar_dev;extern ino_t ar_ino;/* JF */extern struct name *gnu_list_name;/* * If there are no symbolic links, there is no lstat().  Use stat(). */#ifndef S_IFLNK#define lstat stat#endifextern char	*malloc();extern char	*strcpy();extern char	*strncpy();extern void	bzero();extern void	bcopy();extern int	errno;extern void print_header();union record *start_header();void finish_header();void finduname();void findgname();char *name_next();void to_oct();void dump_file();static nolinks;			/* Gets set if we run out of RAM *//* * "Scratch" space to store the information about a sparse file before * writing the info into the header or extended header *//* struct sp_array	 *sparsearray;*//* number of elts storable in the sparsearray *//*int 	sparse_array_size = 10;*/voidcreate_archive(){	register char	*p;	char *name_from_list();	open_archive(0);		/* Open for writing */	if(f_gnudump) {		char buf[MAXNAMLEN],*q,*bufp;		collect_and_sort_names();		while(p=name_from_list())			dump_file(p,-1);		/* if(!f_dironly) { */			blank_name_list();			while(p=name_from_list()) {				strcpy(buf,p);				if(p[strlen(p)-1]!='/')					strcat(buf,"/");				bufp=buf+strlen(buf);				for(q=gnu_list_name->dir_contents;q && *q;q+=strlen(q)+1) {					if(*q=='Y') {						strcpy(bufp,q+1);						dump_file(buf,-1);					}				}			}		/* } */		} else {		p = name_next(1);		if(!p)			dump_file(".", -1);		else {			do dump_file(p, -1);			while (p = name_next(1));		}	}	write_eot();	close_archive();	name_close();}/* * Dump a single file.  If it's a directory, recurse. * Result is 1 for success, 0 for failure. * Sets global "hstat" to stat() output for this file. */voiddump_file (p, curdev)	char	*p;			/* File name to dump */	int	curdev;			/* Device our parent dir was on */{	union record	*header;	char type;	extern char *save_name;		/* JF for multi-volume support */	extern long save_totsize;	extern long save_sizeleft;	union record	*exhdr;	char save_linkflag;	extern time_t new_time;	int sparse_ind = 0;	if(f_confirm && !confirm("add",p))		return;	/*	 * Use stat if following (rather than dumping) 4.2BSD's	 * symbolic links.  Otherwise, use lstat (which, on non-4.2	 * systems, is #define'd to stat anyway.	 */	if (0 != f_follow_links? stat(p, &hstat): lstat(p, &hstat))	{badperror:		msg_perror("can't add file %s",p);badfile:		errors++;		return;	}	/* See if we only want new files, and check if this one is too old to	   put in the archive. */	if(   f_new_files	   && !f_gnudump 	   && new_time>hstat.st_mtime 	   && (hstat.st_mode&S_IFMT)!=S_IFDIR 	   && (f_new_files>1 || new_time>hstat.st_ctime)) {		if(curdev<0) {			msg("%s: is unchanged; not dumped",p);		}		return;	}	/*	 * See if we are crossing from one file system to another,	 * and avoid doing so if the user only wants to dump one file system.	 */	if (f_local_filesys && curdev >= 0 && curdev != hstat.st_dev) {		if(f_verbose)			msg("%s: is on a different filesystem; not dumped",p);		return;	}	/* See if we are trying to dump the archive */	if(ar_dev && hstat.st_dev==ar_dev && hstat.st_ino==ar_ino) {		msg("%s is the archive; not dumped",p);		return;	}	/*	 * Check for multiple links.	 *	 * We maintain a list of all such files that we've written so	 * far.  Any time we see another, we check the list and	 * avoid dumping the data again if we've done it once already.	 */	if (hstat.st_nlink > 1) switch (hstat.st_mode & S_IFMT) {		register struct link	*lp;	case S_IFREG:			/* Regular file */#ifdef S_IFCTG	case S_IFCTG:			/* Contigous file */#endif#ifdef S_IFCHR	case S_IFCHR:			/* Character special file */#endif#ifdef S_IFBLK	case S_IFBLK:			/* Block     special file */#endif#ifdef S_IFIFO	case S_IFIFO:			/* Fifo      special file */#endif		/* First quick and dirty.  Hashing, etc later FIXME */		for (lp = linklist; lp; lp = lp->next) {			if (lp->ino == hstat.st_ino &&			    lp->dev == hstat.st_dev) {				char *link_name = lp->name;				/* We found a link. */				hstat.st_size = 0;				header = start_header(p, &hstat);				if (header == NULL) goto badfile;				while(!f_absolute_paths && *link_name == '/') {					static int link_warn = 0;					if (!link_warn) {						msg("Removing leading / from absolute links");						link_warn++;					}					link_name++;				}  				strcpy(header->header.linkname,					link_name);				header->header.linkflag = LF_LINK;				finish_header(header);		/* FIXME: Maybe remove from list after all links found? */				return;		/* We dumped it */			}		}		/* Not found.  Add it to the list of possible links. */		lp = (struct link *) malloc( (unsigned)			(strlen(p) + sizeof(struct link) - NAMSIZ));		if (!lp) {			if (!nolinks) {				msg(	"no memory for links, they will be dumped as separate files");				nolinks++;			}		}		lp->ino = hstat.st_ino;		lp->dev = hstat.st_dev;		strcpy(lp->name, p);		lp->next = linklist;		linklist = lp;	}	/*	 * This is not a link to a previously dumped file, so dump it.	 */	switch (hstat.st_mode & S_IFMT) {	case S_IFREG:			/* Regular file */#ifdef S_IFCTG	case S_IFCTG:			/* Contiguous file */#endif	{		int	f;		/* File descriptor */		long	bufsize, count;		long	sizeleft;		register union record 	*start;		int 	header_moved;		char	isextended = 0;		int 	upperbound;		int	end_nulls = 0;				header_moved = 0;#ifdef BSD42		if (f_sparse_files) {		/*	 	 * JK - This is the test for sparseness: whether the		 * "size" of the file matches the number of blocks		 * allocated for it.  If there is a smaller number		 * of blocks that would be necessary to accommodate		 * a file of this size, we have a sparse file, i.e.,		 * at least one of those records in the file is just		 * a useless hole.		 */			if (hstat.st_size - (hstat.st_blocks * RECORDSIZE) > RECORDSIZE) {				int	filesize = hstat.st_size;				register int i;								printf("File is sparse: %s\n", p);				header = start_header(p, &hstat);				if (header == NULL)					goto badfile;				header->header.linkflag = LF_SPARSE;				header_moved++;							/*			 * Call the routine that figures out the			 * layout of the sparse file in question.			 * UPPERBOUND is the index of the last			 * element of the "sparsearray," i.e.,			 * the number of elements it needed to			 * describe the file.			 */				 				upperbound = deal_with_sparse(p, header); 									/* 			 * See if we'll need an extended header			 * later			 */				if (upperbound > SPARSE_IN_HDR-1)		 			header->header.isextended++;			/*			 * We store the "real" file size so			 * we can show that in case someone wants			 * to list the archive, i.e., tar tvf <file>.			 * It might be kind of disconcerting if the			 * shrunken file size was the one that showed			 * up.			 */				 to_oct((long) hstat.st_size, 1+12, 				 		header->header.realsize);								/*			 * This will be the new "size" of the			 * file, i.e., the size of the file			 * minus the records of holes that we're			 * skipping over. 			 */				 				find_new_file_size(&filesize, upperbound);				printf("File %s is now size %d\n", 							p, filesize);				hstat.st_size = filesize;				to_oct((long) filesize, 1+12, 						header->header.size);/*				to_oct((long) end_nulls, 1+12, 						header->header.ending_blanks);*/										for (i = 0; i < SPARSE_IN_HDR; i++) {					if (!sparsearray[i].numbytes)						break;					to_oct(sparsearray[i].offset, 1+12,						header->header.sp[i].offset);					to_oct(sparsearray[i].numbytes, 1+12,						header->header.sp[i].numbytes);				}								}		}#else		upperbound=SPARSE_IN_HDR-1;#endif				sizeleft = hstat.st_size;		/* Don't bother opening empty, world readable files. */		if (sizeleft > 0 || 0444 != (0444 & hstat.st_mode)) {			f = open(p, O_RDONLY|O_BINARY);			if (f < 0) goto badperror;		} else {			f = -1;		}				/* If the file is sparse, we've already taken care of this */		if (!header_moved) {			header = start_header(p, &hstat);			if (header == NULL) {				if(f>=0)					(void)close(f);				goto badfile;			}		}#ifdef S_IFCTG		/* Mark contiguous files, if we support them */		if (f_standard && (hstat.st_mode & S_IFMT) == S_IFCTG) {			header->header.linkflag = LF_CONTIG;		}#endif		isextended = header->header.isextended;		save_linkflag = header->header.linkflag;		finish_header(header);		if (isextended) {			int	 sum = 0;			register int i;/*			register union record *exhdr;*/			int	 arraybound = SPARSE_EXT_HDR;			/* static */ int index_offset = SPARSE_IN_HDR;				extend:		exhdr = findrec();						if (exhdr == NULL) goto badfile;			bzero(exhdr->charptr, RECORDSIZE);			for (i = 0; i < SPARSE_EXT_HDR; i++) {				if (i+index_offset > upperbound)					break;				to_oct((long) sparsearray[i+index_offset].numbytes, 					1+12,					exhdr->ext_hdr.sp[i].numbytes);				to_oct((long) sparsearray[i+index_offset].offset, 					1+12,					exhdr->ext_hdr.sp[i].offset);			}			userec(exhdr);/*			sum += i;			if (sum < upperbound)				goto extend;*/			if (index_offset+i < upperbound) {				index_offset += i;				exhdr->ext_hdr.isextended++;				goto extend;			}						}		if (save_linkflag == LF_SPARSE) {			if (finish_sparse_file(f, &sizeleft, hstat.st_size, p))				goto padit;		}		else		  while (sizeleft > 0) {						if(f_multivol) {   				save_name = p;				save_sizeleft = sizeleft;				save_totsize = hstat.st_size;			}			start = findrec();			bufsize = endofrecs()->charptr - start->charptr;							if (sizeleft < bufsize) {				/* Last read -- zero out area beyond */				bufsize = (int)sizeleft;				count = bufsize % RECORDSIZE;				if (count) 					bzero(start->charptr + sizeleft,						(int)(RECORDSIZE - count));			}			count = read(f, start->charptr, bufsize);			if (count < 0) {				msg_perror("read error at byte %ld, reading\ %d bytes, in file %s",  hstat.st_size - sizeleft, bufsize,p);				goto padit;			}			sizeleft -= count;			/* This is nonportable (the type of userec's arg). */			userec(start+(count-1)/RECORDSIZE);			if (count == bufsize) continue;			msg( "file %s shrunk by %d bytes, padding with zeros.\n", p, sizeleft);			goto padit;		/* Short read */		}		if(f_multivol)			save_name = 0;		if (f >= 0)			(void)close(f);		break;		/*		 * File shrunk or gave error, pad out tape to match		 * the size we specified in the header.		 */	padit:		while(sizeleft>0) {			save_sizeleft=sizeleft;			start=findrec();			bzero(start->charptr,RECORDSIZE);			userec(start);			sizeleft-=RECORDSIZE;		}		if(f_multivol)			save_name=0;		if(f>=0)			(void)close(f);		break;/*		abort(); */	}#ifdef S_IFLNK	case S_IFLNK:			/* Symbolic link */	{		int size;		hstat.st_size = 0;		/* Force 0 size on symlink */		header = start_header(p, &hstat);		if (header == NULL) goto badfile;		size = readlink(p, header->header.linkname, NAMSIZ);		if (size < 0) goto badperror;		if (size == NAMSIZ) {			msg("symbolic link %s too long\n",p);			break;		}		header->header.linkname[size] = '\0';		header->header.linkflag = LF_SYMLINK;		finish_header(header);		/* Nothing more to do to it */	}		break;#endif	case S_IFDIR:			/* Directory */	{		register DIR *dirp;		register struct direct *d;		char namebuf[NAMSIZ+2];		register int len;		int our_device = hstat.st_dev;		/* Build new prototype name */		strncpy(namebuf, p, sizeof (namebuf));		len = strlen(namebuf);		while (len >= 1 && '/' == namebuf[len-1]) 			len--;			/* Delete trailing slashes */		namebuf[len++] = '/';		/* Now add exactly one back */		namebuf[len] = '\0';		/* Make sure null-terminated */		/*		 * Output directory header record with permissions		 * FIXME, do this AFTER files, to avoid R/O dir problems?		 * If old archive format, don't write record at all.		 */		if (!f_oldarch) {			hstat.st_size = 0;	/* Force 0 size on dir */			/*			 * If people could really read standard archives,			 * this should be:		(FIXME)			header = start_header(f_standard? p: namebuf, &hstat);			 * but since they'd interpret LF_DIR records as			 * regular files, we'd better put the / on the name.			 */			header = start_header(namebuf, &hstat);			if (header == NULL)				goto badfile;	/* eg name too long */			if (f_gnudump)				header->header.linkflag = LF_DUMPDIR;			else if (f_standard)				header->header.linkflag = LF_DIR;

⌨️ 快捷键说明

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