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

📄 tar.c

📁 手机嵌入式Linux下可用的busybox源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (errorFlag==TRUE)			error_msg( "Error exit delayed from previous errors");		else			return( TRUE);	} 	return( FALSE);}#ifdef BB_FEATURE_TAR_CREATE/*** writeTarFile(),  writeFileToTarball(), and writeTarHeader() are** the only functions that deal with the HardLinkInfo structure.** Even these functions use the xxxHardLinkInfo() functions.*/typedef struct HardLinkInfo HardLinkInfo;struct HardLinkInfo{	HardLinkInfo *next;           /* Next entry in list */	dev_t dev;                    /* Device number */	ino_t ino;                    /* Inode number */	short linkCount;              /* (Hard) Link Count */	char name[1];                 /* Start of filename (must be last) */};/* Some info to be carried along when creating a new tarball */struct TarBallInfo{	char* fileName;               /* File name of the tarball */	int tarFd;                    /* Open-for-write file descriptor									 for the tarball */	struct stat statBuf;          /* Stat info for the tarball, letting									 us know the inode and device that the									 tarball lives, so we can avoid trying 									 to include the tarball into itself */	int verboseFlag;              /* Whether to print extra stuff or not */	char** excludeList;           /* List of files to not include */	HardLinkInfo *hlInfoHead;     /* Hard Link Tracking Information */	HardLinkInfo *hlInfo;         /* Hard Link Info for the current file */};typedef struct TarBallInfo TarBallInfo;/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */static voidaddHardLinkInfo (HardLinkInfo **hlInfoHeadPtr, dev_t dev, ino_t ino,		short linkCount, const char *name){	/* Note: hlInfoHeadPtr can never be NULL! */	HardLinkInfo *hlInfo;	hlInfo = (HardLinkInfo *)xmalloc(sizeof(HardLinkInfo)+strlen(name)+1);	if (hlInfo) {		hlInfo->next = *hlInfoHeadPtr;		*hlInfoHeadPtr = hlInfo;		hlInfo->dev = dev;		hlInfo->ino = ino;		hlInfo->linkCount = linkCount;		strcpy(hlInfo->name, name);	}	return;}static voidfreeHardLinkInfo (HardLinkInfo **hlInfoHeadPtr){	HardLinkInfo *hlInfo = NULL;	HardLinkInfo *hlInfoNext = NULL;	if (hlInfoHeadPtr) {		hlInfo = *hlInfoHeadPtr;		while (hlInfo) {			hlInfoNext = hlInfo->next;			free(hlInfo);			hlInfo = hlInfoNext;		}		*hlInfoHeadPtr = NULL;	}	return;}/* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */static HardLinkInfo *findHardLinkInfo (HardLinkInfo *hlInfo, dev_t dev, ino_t ino){	while(hlInfo) {		if ((ino == hlInfo->ino) && (dev == hlInfo->dev))			break;		hlInfo = hlInfo->next;	}	return(hlInfo);}/* Put an octal string into the specified buffer. * The number is zero and space padded and possibly null padded. * Returns TRUE if successful.  */ static int putOctal (char *cp, int len, long value){	int tempLength;	char tempBuffer[32];	char *tempString = tempBuffer;	/* Create a string of the specified length with an initial space,	 * leading zeroes and the octal number, and a trailing null.  */	sprintf (tempString, "%0*lo", len - 1, value);	/* If the string is too large, suppress the leading space.  */	tempLength = strlen (tempString) + 1;	if (tempLength > len) {		tempLength--;		tempString++;	}	/* If the string is still too large, suppress the trailing null.  */	if (tempLength > len)		tempLength--;	/* If the string is still too large, fail.  */	if (tempLength > len)		return FALSE;	/* Copy the string to the field.  */	memcpy (cp, tempString, len);	return TRUE;}/* Write out a tar header for the specified file/directory/whatever */static intwriteTarHeader(struct TarBallInfo *tbInfo, const char *header_name,		const char *real_name, struct stat *statbuf){	long chksum=0;	struct TarHeader header;	const unsigned char *cp = (const unsigned char *) &header;	ssize_t size = sizeof(struct TarHeader);			memset( &header, 0, size);	strncpy(header.name, header_name, sizeof(header.name)); 	putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);	putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);	putOctal(header.gid, sizeof(header.gid), statbuf->st_gid);	putOctal(header.size, sizeof(header.size), 0); /* Regular file size is handled later */	putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime);	strncpy(header.magic, TAR_MAGIC TAR_VERSION, 			TAR_MAGIC_LEN + TAR_VERSION_LEN );	/* Enter the user and group names (default to root if it fails) */	my_getpwuid(header.uname, statbuf->st_uid);	if (! *header.uname)		strcpy(header.uname, "root");	my_getgrgid(header.gname, statbuf->st_gid);	if (! *header.uname)		strcpy(header.uname, "root");	if (tbInfo->hlInfo) {		/* This is a hard link */		header.typeflag = LNKTYPE;		strncpy(header.linkname, tbInfo->hlInfo->name, sizeof(header.linkname));	} else if (S_ISLNK(statbuf->st_mode)) {		char *lpath = xreadlink(real_name);		if (!lpath) /* Already printed err msg inside xreadlink() */			return ( FALSE);		header.typeflag  = SYMTYPE;		strncpy(header.linkname, lpath, sizeof(header.linkname)); 		free(lpath);	} else if (S_ISDIR(statbuf->st_mode)) {		header.typeflag  = DIRTYPE;		strncat(header.name, "/", sizeof(header.name)); 	} else if (S_ISCHR(statbuf->st_mode)) {		header.typeflag  = CHRTYPE;		putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev));		putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev));	} else if (S_ISBLK(statbuf->st_mode)) {		header.typeflag  = BLKTYPE;		putOctal(header.devmajor, sizeof(header.devmajor), MAJOR(statbuf->st_rdev));		putOctal(header.devminor, sizeof(header.devminor), MINOR(statbuf->st_rdev));	} else if (S_ISFIFO(statbuf->st_mode)) {		header.typeflag  = FIFOTYPE;	} else if (S_ISREG(statbuf->st_mode)) {		header.typeflag  = REGTYPE;		putOctal(header.size, sizeof(header.size), statbuf->st_size);	} else {		error_msg("%s: Unknown file type", real_name);		return ( FALSE);	}	/* Calculate and store the checksum (i.e., the sum of all of the bytes of	 * the header).  The checksum field must be filled with blanks for the	 * calculation.  The checksum field is formatted differently from the	 * other fields: it has [6] digits, a null, then a space -- rather than	 * digits, followed by a null like the other fields... */	memset(header.chksum, ' ', sizeof(header.chksum));	cp = (const unsigned char *) &header;	while (size-- > 0)		chksum += *cp++;	putOctal(header.chksum, 7, chksum);		/* Now write the header out to disk */	if ((size=full_write(tbInfo->tarFd, (char*)&header, sizeof(struct TarHeader))) < 0) {		error_msg(io_error, real_name, strerror(errno)); 		return ( FALSE);	}	/* Pad the header up to the tar block size */	for (; size<TAR_BLOCK_SIZE; size++) {		write(tbInfo->tarFd, "\0", 1);	}	/* Now do the verbose thing (or not) */	if (tbInfo->verboseFlag==TRUE) {		FILE *vbFd = stdout;		if (tbInfo->tarFd == fileno(stdout))	// If the archive goes to stdout, verbose to stderr			vbFd = stderr;		fprintf(vbFd, "%s\n", header.name);	}	return ( TRUE);}static int writeFileToTarball(const char *fileName, struct stat *statbuf, void* userData){	struct TarBallInfo *tbInfo = (struct TarBallInfo *)userData;	const char *header_name;	/*	** Check to see if we are dealing with a hard link.	** If so -	** Treat the first occurance of a given dev/inode as a file while	** treating any additional occurances as hard links.  This is done	** by adding the file information to the HardLinkInfo linked list.	*/	tbInfo->hlInfo = NULL;	if (statbuf->st_nlink > 1) {		tbInfo->hlInfo = findHardLinkInfo(tbInfo->hlInfoHead, statbuf->st_dev, 				statbuf->st_ino);		if (tbInfo->hlInfo == NULL)			addHardLinkInfo (&tbInfo->hlInfoHead, statbuf->st_dev,					statbuf->st_ino, statbuf->st_nlink, fileName);	}	/* It is against the rules to archive a socket */	if (S_ISSOCK(statbuf->st_mode)) {		error_msg("%s: socket ignored", fileName);		return( TRUE);	}	/* It is a bad idea to store the archive we are in the process of creating,	 * so check the device and inode to be sure that this particular file isn't	 * the new tarball */	if (tbInfo->statBuf.st_dev == statbuf->st_dev &&			tbInfo->statBuf.st_ino == statbuf->st_ino) {		error_msg("%s: file is the archive; skipping", fileName);		return( TRUE);	}	header_name = fileName;	while (header_name[0] == '/') {		static int alreadyWarned=FALSE;		if (alreadyWarned==FALSE) {			error_msg("Removing leading '/' from member names");			alreadyWarned=TRUE;		}		header_name++;	}	if (strlen(fileName) >= NAME_SIZE) {		error_msg(name_longer_than_foo, NAME_SIZE);		return ( TRUE);	}	if (header_name[0] == '\0')		return TRUE;#if defined BB_FEATURE_TAR_EXCLUDE	if (exclude_file(tbInfo->excludeList, header_name)) {		return SKIP;	}#endif	if (writeTarHeader(tbInfo, header_name, fileName, statbuf)==FALSE) {		return( FALSE);	} 	/* Now, if the file is a regular file, copy it out to the tarball */	if ((tbInfo->hlInfo == NULL)	&&  (S_ISREG(statbuf->st_mode))) {		int  inputFileFd;		char buffer[BUFSIZ];		ssize_t size=0, readSize=0;		/* open the file we want to archive, and make sure all is well */		if ((inputFileFd = open(fileName, O_RDONLY)) < 0) {			error_msg("%s: Cannot open: %s", fileName, strerror(errno));			return( FALSE);		}				/* write the file to the archive */		while ( (size = full_read(inputFileFd, buffer, sizeof(buffer))) > 0 ) {			if (full_write(tbInfo->tarFd, buffer, size) != size ) {				/* Output file seems to have a problem */				error_msg(io_error, fileName, strerror(errno)); 				return( FALSE);			}			readSize+=size;		}		if (size == -1) {			error_msg(io_error, fileName, strerror(errno)); 			return( FALSE);		}		/* Pad the file up to the tar block size */		for (; (readSize%TAR_BLOCK_SIZE) != 0; readSize++) {			write(tbInfo->tarFd, "\0", 1);		}		close( inputFileFd);	}	return( TRUE);}static int writeTarFile(const char* tarName, int verboseFlag, char **argv,		char** excludeList){	int tarFd=-1;	int errorFlag=FALSE;	ssize_t size;	struct TarBallInfo tbInfo;	tbInfo.verboseFlag = verboseFlag;	tbInfo.hlInfoHead = NULL;	/* Make sure there is at least one file to tar up.  */	if (*argv == NULL)		error_msg_and_die("Cowardly refusing to create an empty archive");	/* Open the tar file for writing.  */	if (!strcmp(tarName, "-"))		tbInfo.tarFd = fileno(stdout);	else		tbInfo.tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0644);	if (tbInfo.tarFd < 0) {		perror_msg( "Error opening '%s'", tarName);		freeHardLinkInfo(&tbInfo.hlInfoHead);		return ( FALSE);	}	tbInfo.excludeList=excludeList;	/* Store the stat info for the tarball's file, so	 * can avoid including the tarball into itself....  */	if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0)		error_msg_and_die(io_error, tarName, strerror(errno)); 	/* Read the directory/files and iterate over them one at a time */	while (*argv != NULL) {		if (recursive_action(*argv++, TRUE, FALSE, FALSE,					writeFileToTarball, writeFileToTarball, 					(void*) &tbInfo) == FALSE) {			errorFlag = TRUE;		}	}	/* Write two empty blocks to the end of the archive */	for (size=0; size<(2*TAR_BLOCK_SIZE); size++) {		write(tbInfo.tarFd, "\0", 1);	}	/* To be pedantically correct, we would check if the tarball	 * is smaller than 20 tar blocks, and pad it if it was smaller,	 * but that isn't necessary for GNU tar interoperability, and	 * so is considered a waste of space */	/* Hang up the tools, close up shop, head home */	close(tarFd);	if (errorFlag == TRUE) {		error_msg("Error exit delayed from previous errors");		freeHardLinkInfo(&tbInfo.hlInfoHead);		return(FALSE);	}	freeHardLinkInfo(&tbInfo.hlInfoHead);	return( TRUE);}#endif

⌨️ 快捷键说明

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