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

📄 tar.c

📁 这是一个SIGMA方案的PMP播放器的UCLINUX程序,可播放DVD,VCD,CD MP3...有很好的参考价值.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* vi: set sw=4 ts=4: *//* * Mini tar implementation for busybox  * * Modifed to use common extraction code used by ar, cpio, dpkg-deb, dpkg *  Glenn McGrath <bug1@optushome.com.au> * * Note, that as of BusyBox-0.43, tar has been completely rewritten from the * ground up.  It still has remnents of the old code lying about, but it is * very different now (i.e., cleaner, less global variables, etc.) * * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen * Copyright (C) 1999-2002 by Erik Andersen <andersee@debian.org> * * Based in part in the tar implementation in sash *  Copyright (c) 1999 by David I. Bell *  Permission is granted to use, distribute, or modify this source, *  provided that this copyright notice remains intact. *  Permission to distribute sash derived code under the GPL has been granted. * * Based in part on the tar implementation from busybox-0.28 *  Copyright (C) 1995 Bruce Perens *  This is free software under the GNU General Public License. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */#include <fcntl.h>#include <getopt.h>#include <search.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fnmatch.h>#include <string.h>#include <errno.h>#include "unarchive.h"#include "busybox.h"#ifdef CONFIG_FEATURE_TAR_CREATE/* Tar file constants  */# define TAR_MAGIC          "ustar"        /* ustar and a null */# define TAR_VERSION        "  "           /* Be compatable with GNU tar format */# ifndef MAJOR#  define MAJOR(dev) (((dev)>>8)&0xff)#  define MINOR(dev) ((dev)&0xff)# endifstatic const int TAR_BLOCK_SIZE = 512;static const int TAR_MAGIC_LEN = 6;static const int TAR_VERSION_LEN = 2;/* POSIX tar Header Block, from POSIX 1003.1-1990  */enum { NAME_SIZE = 100 }; /* because gcc won't let me use 'static const int' */struct TarHeader{                            /* byte offset */	char name[NAME_SIZE];         /*   0-99 */	char mode[8];                 /* 100-107 */	char uid[8];                  /* 108-115 */	char gid[8];                  /* 116-123 */	char size[12];                /* 124-135 */	char mtime[12];               /* 136-147 */	char chksum[8];               /* 148-155 */	char typeflag;                /* 156-156 */	char linkname[NAME_SIZE];     /* 157-256 */	char magic[6];                /* 257-262 */	char version[2];              /* 263-264 */	char uname[32];               /* 265-296 */	char gname[32];               /* 297-328 */	char devmajor[8];             /* 329-336 */	char devminor[8];             /* 337-344 */	char prefix[155];             /* 345-499 */	char padding[12];             /* 500-512 (pad to exactly the TAR_BLOCK_SIZE) */};typedef struct TarHeader TarHeader;/*** 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;/* A nice enum with all the possible tar file content types */enum TarFileType {	REGTYPE  = '0',            /* regular file */	REGTYPE0 = '\0',           /* regular file (ancient bug compat)*/	LNKTYPE  = '1',            /* hard link */	SYMTYPE  = '2',            /* symbolic link */	CHRTYPE  = '3',            /* character special */	BLKTYPE  = '4',            /* block special */	DIRTYPE  = '5',            /* directory */	FIFOTYPE = '6',            /* FIFO special */	CONTTYPE = '7',            /* reserved */	GNULONGLINK = 'K',         /* GNU long (>100 chars) link name */	GNULONGNAME = 'L',         /* GNU long (>100 chars) file name */};typedef enum TarFileType TarFileType;/* 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);}# if defined CONFIG_FEATURE_TAR_EXCLUDEstatic int exclude_file(char **excluded_files, const char *file){	int i;	if (excluded_files == NULL)		return 0;	for (i = 0; excluded_files[i] != NULL; i++) {		if (excluded_files[i][0] == '/') {			if (fnmatch(excluded_files[i], file,						FNM_PATHNAME | FNM_LEADING_DIR) == 0)				return 1;		} else {			const char *p;			for (p = file; p[0] != '\0'; p++) {				if ((p == file || p[-1] == '/') && p[0] != '/' &&						fnmatch(excluded_files[i], p,							FNM_PATHNAME | FNM_LEADING_DIR) == 0)					return 1;			}		}	}	return 0;}#endifstatic 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);

⌨️ 快捷键说明

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