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

📄 ar_subs.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
		ftree_sel(arcn);		if (hlk && (chk_lnk(arcn) < 0))			break;		if ((arcn->type == PAX_REG) || (arcn->type == PAX_HRG) ||		    (arcn->type == PAX_CTG)) {			/*			 * we will have to read this file. by opening it now we			 * can avoid writing a header to the archive for a file			 * we were later unable to read (we also purge it from			 * the link table).			 */			if ((fd = open(arcn->org_name, O_RDONLY, 0)) < 0) {				syswarn(1,errno, "Unable to open %s to read",					arcn->org_name);				purg_lnk(arcn);				continue;			}		}		/*		 * Now modify the name as requested by the user		 */		if ((res = mod_name(arcn)) < 0) {			/*			 * name modification says to skip this file, close the			 * file and purge link table entry			 */			rdfile_close(arcn, &fd);			purg_lnk(arcn);			break;		}		if ((res > 0) || (docrc && (set_crc(arcn, fd) < 0))) {			/*			 * unable to obtain the crc we need, close the file,			 * purge link table entry 			 */			rdfile_close(arcn, &fd);			purg_lnk(arcn);			continue;		}		if (vflag) {			(void)fputs(arcn->name, stderr);			vfpart = 1;		}		++flcnt;		/*		 * looks safe to store the file, have the format specific		 * routine write routine store the file header on the archive		 */		if ((res = (*wrf)(arcn)) < 0) {			rdfile_close(arcn, &fd);			break;		}		wr_one = 1;		if (res > 0) {			/* 			 * format write says no file data needs to be stored			 * so we are done messing with this file			 */			if (vflag && vfpart) {				(void)putc('\n', stderr);				vfpart = 0;			}			rdfile_close(arcn, &fd);			continue;		}		/*		 * Add file data to the archive, quit on write error. if we		 * cannot write the entire file contents to the archive we		 * must pad the archive to replace the missing file data		 * (otherwise during an extract the file header for the file		 * which FOLLOWS this one will not be where we expect it to		 * be).		 */		res = (*frmt->wr_data)(arcn, fd, &cnt);		rdfile_close(arcn, &fd);		if (vflag && vfpart) {			(void)putc('\n', stderr);			vfpart = 0;		}		if (res < 0)			break;		/*		 * pad as required, cnt is number of bytes not written		 */		if (((cnt > 0) && (wr_skip(cnt) < 0)) ||		    ((arcn->pad > 0) && (wr_skip(arcn->pad) < 0)))			break;	}	/*	 * tell format to write trailer; pad to block boundry; reset directory	 * mode/access times, and check if all patterns supplied by the user	 * were matched. block off signals to avoid chance for multiple entry	 * into the cleanup code	 */	if (wr_one) {		(*frmt->end_wr)();		wr_fin();	}	(void)sigprocmask(SIG_BLOCK, &s_mask, (sigset_t *)NULL);	ar_close();	if (tflag)		proc_dir();	ftree_chk();}/* * append() *	Add file to previously written archive. Archive format specified by the *	user must agree with archive. The archive is read first to collect *	modification times (if -u) and locate the archive trailer. The archive *	is positioned in front of the record with the trailer and wr_archive() *	is called to add the new members. *	PAX IMPLEMENTATION DETAIL NOTE: *	-u is implemented by adding the new members to the end of the archive. *	Care is taken so that these do not end up as links to the older  *	version of the same file already stored in the archive. It is expected *	when extraction occurs these newer versions will over-write the older *	ones stored "earlier" in the archive (this may be a bad assumption as *	it depends on the implementation of the program doing the extraction). *	It is really difficult to splice in members without either re-writing *	the entire archive (from the point were the old version was), or having *	assistance of the format specification in terms of a special update *	header that invalidates a previous archive record. The posix spec left *	the method used to implement -u unspecified. This pax is able to *	over write existing files that it creates. */#if __STDC__voidappend(void)#elsevoidappend()#endif{	register ARCHD *arcn;	register int res;	ARCHD archd;	FSUB *orgfrmt;	int udev;	off_t tlen;	arcn = &archd;	orgfrmt = frmt;	/*	 * Do not allow an append operation if the actual archive is of a	 * different format than the user specified foramt.	 */	if (get_arc() < 0)		return;	if ((orgfrmt != NULL) && (orgfrmt != frmt)) {		warn(1, "Cannot mix current archive format %s with %s",		    frmt->name, orgfrmt->name);		return;	}	/*	 * pass the format any options and start up format	 */	if (((*frmt->options)() < 0) || ((*frmt->st_rd)() < 0))		return;	/*	 * if we only are adding members that are newer, we need to save the	 * mod times for all files we see.	 */	if (uflag && (ftime_start() < 0))		return;	/*	 * some archive formats encode hard links by recording the device and	 * file serial number (inode) but copy the file anyway (multiple times)	 * to the archive. When we append, we run the risk that newly added	 * files may have the same device and inode numbers as those recorded	 * on the archive but during a previous run. If this happens, when the	 * archive is extracted we get INCORRECT hard links. We avoid this by	 * remapping the device numbers so that newly added files will never	 * use the same device number as one found on the archive. remapping	 * allows new members to safely have links among themselves. remapping	 * also avoids problems with file inode (serial number) truncations	 * when the inode number is larger than storage space in the archive	 * header. See the remap routines for more details.	 */	if ((udev = frmt->udev) && (dev_start() < 0))		return;	/*	 * reading the archive may take a long time. If verbose tell the user	 */	if (vflag) {		(void)fprintf(stderr,			"%s: Reading archive to position at the end...", argv0);		vfpart = 1;	}	/*	 * step through the archive until the format says it is done	 */	while (next_head(arcn) == 0) {		/*		 * check if this file meets user specified options.		 */		if (sel_chk(arcn) != 0) {			if (rd_skip(arcn->skip + arcn->pad) == 1)				break;			continue;		}		if (uflag) {			/*			 * see if this is the newest version of this file has			 * already been seen, if so skip.			 */			if ((res = chk_ftime(arcn)) < 0)				break;			if (res > 0) {				if (rd_skip(arcn->skip + arcn->pad) == 1)					break;				continue;			}		}		/*		 * Store this device number. Device numbers seen during the		 * read phase of append will cause newly appended files with a		 * device number seen in the old part of the archive to be		 * remapped to an unused device number.		 */		if ((udev && (add_dev(arcn) < 0)) ||		    (rd_skip(arcn->skip + arcn->pad) == 1))			break;	}	/*	 * done, finish up read and get the number of bytes to back up so we	 * can add new members. The format might have used the hard link table,	 * purge it.	 */	tlen = (*frmt->end_rd)();	lnk_end();	/*	 * try to postion for write, if this fails quit. if any error occurs,	 * we will refuse to write	 */	if (appnd_start(tlen) < 0)		return;	/*	 * tell the user we are done reading.	 */	if (vflag && vfpart) {		(void)fputs("done.\n", stderr);		vfpart = 0;	}       	/*	 * go to the writing phase to add the new members	 */	wr_archive(arcn, 1);}/* * archive() *	write a new archive */#if __STDC__voidarchive(void)#elsevoidarchive()#endif{	ARCHD archd;	/*	 * if we only are adding members that are newer, we need to save the	 * mod times for all files; set up for writing; pass the format any	 * options write the archive	 */	if ((uflag && (ftime_start() < 0)) || (wr_start() < 0))		return;	if ((*frmt->options)() < 0)		return;	wr_archive(&archd, 0);}/* * copy() *	copy files from one part of the file system to another. this does not *	use any archive storage. The EFFECT OF THE COPY IS THE SAME as if an *	archive was written and then extracted in the destination directory *	(except the files are forced to be under the destination directory). */#if __STDC__voidcopy(void)#elsevoidcopy()#endif{	register ARCHD *arcn;	register int res;	register int fddest;	register char *dest_pt;	register int dlen;	register int drem;	int fdsrc = -1;	struct stat sb;	ARCHD archd;	char dirbuf[PAXPATHLEN+1];	arcn = &archd;	/*	 * set up the destination dir path and make sure it is a directory. We	 * make sure we have a trailing / on the destination	 */	dlen = l_strncpy(dirbuf, dirptr, PAXPATHLEN);	dest_pt = dirbuf + dlen;	if (*(dest_pt-1) != '/') {		*dest_pt++ = '/';		++dlen;	}	*dest_pt = '\0';	drem = PAXPATHLEN - dlen;	if (stat(dirptr, &sb) < 0) {		syswarn(1, errno, "Cannot access destination directory %s",			dirptr);		return;	}	if (!S_ISDIR(sb.st_mode)) {		warn(1, "Destination is not a directory %s", dirptr);		return;	}	/*	 * start up the hard link table; file traversal routines and the	 * modification time and access mode database 	 */	if ((lnk_start() < 0) || (ftree_start() < 0) || (dir_start() < 0))		return;	/*	 * When we are doing interactive rename, we store the mapping of names	 * so we can fix up hard links files later in the archive.	 */	if (iflag && (name_start() < 0))		return;	/*	 * set up to cp file trees	 */	cp_start();	/*	 * while there are files to archive, process them	 */	while (next_file(arcn) == 0) {		fdsrc = -1;		/*		 * check if this file meets user specified options		 */		if (sel_chk(arcn) != 0)			continue;		/*		 * if there is already a file in the destination directory with		 * the same name and it is newer, skip the one stored on the		 * archive.		 * NOTE: this test is done BEFORE name modifications as		 * specified by pax. this can be confusing to the user who		 * might expect the test to be done on an existing file AFTER		 * the name mod. In honesty the pax spec is probably flawed in		 * this respect		 */		if (uflag || Dflag) {			/*			 * create the destination name			 */			if (*(arcn->name) == '/')				res = 1;			else				res = 0;			if ((arcn->nlen - res) > drem) {				warn(1, "Destination pathname too long %s",					arcn->name);				continue;			}			(void)strncpy(dest_pt, arcn->name + res, drem);			dirbuf[PAXPATHLEN] = '\0';			/*			 * if existing file is same age or newer skip			 */			res = lstat(dirbuf, &sb);			*dest_pt = '\0';

⌨️ 快捷键说明

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