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

📄 tar.c

📁 手机嵌入式Linux下可用的busybox源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* vi: set sw=4 ts=4: *//* * Mini tar implementation for busybox  * * 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 <stdio.h>#include <dirent.h>#include <errno.h>#include <fcntl.h>#include <signal.h>#include <time.h>#include <utime.h>#include <sys/types.h>#include <sys/sysmacros.h>#include <getopt.h>#include <fnmatch.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include "busybox.h"/* Tar file constants  */#ifndef MAJOR#define MAJOR(dev) (((dev)>>8)&0xff)#define MINOR(dev) ((dev)&0xff)#endifenum { NAME_SIZE = 100 }; /* because gcc won't let me use 'static const int' *//* POSIX tar Header Block, from POSIX 1003.1-1990  */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;/* A few useful constants */#define TAR_MAGIC          "ustar"        /* ustar and a null */#define TAR_VERSION        "  "           /* Be compatable with GNU tar format */static const int TAR_MAGIC_LEN = 6;static const int TAR_VERSION_LEN = 2;static const int TAR_BLOCK_SIZE = 512;/* 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;/* This struct ignores magic, non-numeric user name,  * non-numeric group name, and the checksum, since * these are all ignored by BusyBox tar. */ struct TarInfo{	int              tarFd;          /* An open file descriptor for reading from the tarball */	char *           name;           /* File name */	mode_t           mode;           /* Unix mode, including device bits. */	uid_t            uid;            /* Numeric UID */	gid_t            gid;            /* Numeric GID */	size_t           size;           /* Size of file */	time_t           mtime;          /* Last-modified time */	enum TarFileType type;           /* Regular, directory, link, etc. */	char *           linkname;       /* Name for symbolic and hard links */	long             devmajor;       /* Major number for special device */	long             devminor;       /* Minor number for special device */};typedef struct TarInfo TarInfo;/* Local procedures to restore files from a tar file.  */static int readTarFile(int tarFd, int extractFlag, int listFlag, 		int tostdoutFlag, int verboseFlag, char** extractList,		char** excludeList);#ifdef BB_FEATURE_TAR_CREATE/* Local procedures to save files into a tar file.  */static int writeTarFile(const char* tarName, int verboseFlag, char **argv,		char** excludeList);#endif#if defined BB_FEATURE_TAR_EXCLUDEstatic struct option longopts[] = {	{ "exclude", 1, NULL, 'e' },	{ NULL, 0, NULL, 0 }};#endifextern int tar_main(int argc, char **argv){	char** excludeList=NULL;	char** extractList=NULL;	const char *tarName="-";	const char *cwd=NULL;#if defined BB_FEATURE_TAR_EXCLUDE	int excludeListSize=0;	FILE *fileList;	char file[256];#endif#if defined BB_FEATURE_TAR_GZIP	FILE *comp_file = NULL;	int unzipFlag    = FALSE;#endif	int listFlag     = FALSE;	int extractFlag  = FALSE;	int createFlag   = FALSE;	int verboseFlag  = FALSE;	int tostdoutFlag = FALSE;	int status       = FALSE;	int opt;#if defined BB_FEATURE_TAR_GZIP	pid_t pid;#endif	if (argc <= 1)		show_usage();	if (argv[1][0] != '-') {		char *tmp = xmalloc(strlen(argv[1]) + 2);		tmp[0] = '-';		strcpy(tmp + 1, argv[1]);		argv[1] = tmp;	}	while (#ifndef BB_FEATURE_TAR_EXCLUDE			(opt = getopt(argc, argv, "cxtzvOf:pC:"))#else			(opt = getopt_long(argc, argv, "cxtzvOf:X:pC:", longopts, NULL))#endif			> 0) {		switch (opt) {			case 'c':				if (extractFlag == TRUE || listFlag == TRUE)					goto flagError;				createFlag = TRUE;				break;			case 'x':				if (listFlag == TRUE || createFlag == TRUE)					goto flagError;				extractFlag = TRUE;				break;			case 't':				if (extractFlag == TRUE || createFlag == TRUE)					goto flagError;				listFlag = TRUE;				break;#ifdef BB_FEATURE_TAR_GZIP			case 'z':				unzipFlag = TRUE;				break;#endif			case 'v':				verboseFlag = TRUE;				break;			case 'O':				tostdoutFlag = TRUE;				break;			case 'f':				if (*tarName != '-')					error_msg_and_die( "Only one 'f' option allowed");				tarName = optarg;				break;#if defined BB_FEATURE_TAR_EXCLUDE			case 'e':				excludeList=xrealloc( excludeList,						sizeof(char *) * (excludeListSize+2));				excludeList[excludeListSize] = optarg;				/* Tack a NULL onto the end of the list */				excludeList[++excludeListSize] = NULL;			case 'X':				fileList = xfopen(optarg, "r");				while (fgets(file, sizeof(file), fileList) != NULL) {					excludeList = xrealloc(excludeList,							sizeof(char *) * (excludeListSize+2));					chomp(file);					excludeList[excludeListSize] = xstrdup(file);					/* Tack a NULL onto the end of the list */					excludeList[++excludeListSize] = NULL;				}				fclose(fileList);				break;#endif			case 'p':				break;			case 'C':				cwd = xgetcwd((char *)cwd);				if (chdir(optarg)) {					printf("cd: %s: %s\n", optarg, strerror(errno));					return EXIT_FAILURE;				}				break;			default:					show_usage();		}	}	/*	 * Do the correct type of action supplying the rest of the	 * command line arguments as the list of files to process.	 */	if (createFlag == TRUE) {#ifndef BB_FEATURE_TAR_CREATE		error_msg_and_die( "This version of tar was not compiled with tar creation support.");#else#ifdef BB_FEATURE_TAR_GZIP		if (unzipFlag==TRUE)			error_msg_and_die("Creation of compressed not internally support by tar, pipe to busybox gunzip");#endif		status = writeTarFile(tarName, verboseFlag, argv + optind, excludeList);#endif	}	if (listFlag == TRUE || extractFlag == TRUE) {		int tarFd;		if (argv[optind])			extractList = argv + optind;		/* Open the tar file for reading.  */		if (!strcmp(tarName, "-"))			tarFd = fileno(stdin);		else			tarFd = open(tarName, O_RDONLY);		if (tarFd < 0)			perror_msg_and_die("Error opening '%s'", tarName);#ifdef BB_FEATURE_TAR_GZIP			/* unzip tarFd in a seperate process */		if (unzipFlag == TRUE) {			comp_file = fdopen(tarFd, "r");			/* set the buffer size */			setvbuf(comp_file, NULL, _IOFBF, 0x8000);			if ((tarFd = fileno(gz_open(comp_file, &pid))) == EXIT_FAILURE) {				error_msg_and_die("Couldnt unzip file");			}		}#endif					status = readTarFile(tarFd, extractFlag, listFlag, tostdoutFlag,					verboseFlag, extractList, excludeList);		close(tarFd);#ifdef BB_FEATURE_TAR_GZIP			if (unzipFlag == TRUE) {			gz_close(pid);			fclose(comp_file);		}#endif				}	if (cwd)		chdir(cwd);	if (status == TRUE)		return EXIT_SUCCESS;	else		return EXIT_FAILURE;  flagError:	error_msg_and_die( "Exactly one of 'c', 'x' or 't' must be specified");}					static voidfixUpPermissions(TarInfo *header){	struct utimbuf t;	/* Now set permissions etc. for the new file */	chown(header->name, header->uid, header->gid);	chmod(header->name, header->mode);	/* Reset the time */	t.actime = time(0);	t.modtime = header->mtime;	utime(header->name, &t);}				static inttarExtractRegularFile(TarInfo *header, int extractFlag, int tostdoutFlag){	size_t  writeSize;	size_t  readSize;	size_t  actualWriteSz;	char    buffer[20 * TAR_BLOCK_SIZE];	size_t  size = header->size;	int outFd=fileno(stdout);	/* Open the file to be written, if a file is supposed to be written */	if (extractFlag==TRUE && tostdoutFlag==FALSE) {		/* Create the path to the file, just in case it isn't there...		 * This should not screw up path permissions or anything. */		char *buf, *dir;		buf = xstrdup (header->name);		dir = dirname (buf);		make_directory (dir, -1, FILEUTILS_RECUR);		free (buf);		if ((outFd=open(header->name, O_CREAT|O_TRUNC|O_WRONLY, 						header->mode & ~S_IFMT)) < 0) {			error_msg(io_error, header->name, strerror(errno)); 			return( FALSE);		}	}	/* Write out the file, if we are supposed to be doing that */	while ( size > 0 ) {		actualWriteSz=0;		if ( size > sizeof(buffer) )			writeSize = readSize = sizeof(buffer);		else {			int mod = size % TAR_BLOCK_SIZE;			if ( mod != 0 )				readSize = size + (TAR_BLOCK_SIZE - mod);			else				readSize = size;			writeSize = size;		}		if ( (readSize = full_read(header->tarFd, buffer, readSize)) <= 0 ) {			/* Tarball seems to have a problem */			error_msg("Unexpected EOF in archive"); 			return( FALSE);		}		if ( readSize < writeSize )			writeSize = readSize;		/* Write out the file, if we are supposed to be doing that */		if (extractFlag==TRUE) {			if ((actualWriteSz=full_write(outFd, buffer, writeSize)) != writeSize ) {				/* Output file seems to have a problem */				error_msg(io_error, header->name, strerror(errno)); 

⌨️ 快捷键说明

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