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

📄 tarlib.c

📁 VXWORKS源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* tarLib.c - UNIX tar compatible library *//* Copyright 1993-2002 Wind River Systems, Inc. *//* Copyright (c) 1993, 1994 RST Software Industries Ltd. *//*modification history--------------------01i,20sep01,jkf  SPR#69031, common code for both AE & 5.x.01h,26dec99,jkf  T3 KHEAP_ALLOC03g,11nov99,jkf  need to fill all eight bytes with 0x20 for the checksum                  calc correct for MKS toolkit 6.2 generated tar file.03f,31jul99,jkf  T2 merge, tidiness & spelling.03e,30jul98,lrn  partial doc cleanup03b,24jun98,lrn  fixed bug causing 0-size files to be extracted as dirs,		 improved tarHelp to list parameters03a,07jun98,lrn  derived from RST usrTapeLib.c, cleaned all tape related stuff02f,15jan95,rst  adding TarToc functionality02d,28mar94,rst  added Tar utilities.*//*DESCRIPTIONThis library implements functions for archiving, extracting and listingof UNIX-compatible "tar" file archives.It can be used to archive and extract entire file hierarchiesto/from archive files on local or remote disks, or directly to/frommagnetic tapes.SEE ALSO: dosFsLibCURRENT LIMITATIONSThis Tar utility does not handle MS-DOS file attributes,when used in conjunction with the MS-DOS file system.The maximum subdirectory depth supported by this library is 16,while the total maximum path name that can be handled by tar is limited at 100 characters.*/#include "vxWorks.h"#include "stdlib.h"#include "ioLib.h"#include "errnoLib.h"#include "string.h"#include "stdio.h"#include "private/dosFsVerP.h"#include "dosFsLib.h"#include "dirent.h"#include "stat.h"#include "tarLib.h"/* data types *//* * VxWorks Tar Utility, part of usrTapeLib (for now). * UNIX tar(1) tape format - header definition */#define TBLOCK		512	/* TAR Tape block size, part of TAR format */#define NAMSIZ		100	/* size of file name in TAR tape header */#define	MAXLEVEL	16	/* max. # of subdirectory levels, arbitrary */#define	NULLDEV		"/null"	/* data sink */typedef union hblock    {    char dummy[TBLOCK];    struct header	{	char name[NAMSIZ];	char mode[8];	char uid[8];	char gid[8];	char size[12];	char mtime[12];	char chksum[8];	char linkflag;	char linkname[NAMSIZ];    	}    dbuf;    } MT_HBLOCK ;/* Control structure used internally for reentrancy etc. */typedef struct    {    int 	fd ;			/* current tape file descriptor */    int		bFactor;		/* current blocking factor */    int		bValid;			/* number of valid blocks in buffer */    int		recurseCnt;		/* recusrion counter */    MT_HBLOCK *	pBuf;			/* working buffer */    MT_HBLOCK *	pBnext;			/* ptr to next block to return */    } MT_TAR_SOFT ;/* globals */char *TAPE = "/archive0.tar" ;	/* default archive name *//* locals */LOCAL char	bZero[ TBLOCK ] ; /* zeroed block *//********************************************************************************* tarHelp - print help information about TAR archive functions.** NOMANUAL*/void tarHelp    (    void    )    {    int i ;    const char * help_msg[] = {    "Help information on TAR archival functions:\n",    "\n",    " Archive any directory: \n",    "    tarArchive( archFile, bfactor, verbose, dirName )\n",    " Extract from TAR archive into current directory:\n",    "    tarExtract( archFile, bfactor, verbose )\n",    " List contents of TAR archive\n",    "    tarToc( archFile, bfactor)\n",    "      if <dirName> is NULL, archive current directory\n",    "\n", NULL     };    for(i = 0; help_msg[i] != NULL ; i++ )	printf(help_msg[i]);    printf(" if <archFile> is NULL,\n"	"current default archive file \"%s\" will be used,\n", TAPE);    printf(" change the TAPE variable to set a different name.\n\n");    }/********************************************************************************* mtChecksum - calculate checksums for tar header blocks** RETURNS: the checksum value*/LOCAL int mtChecksum    (    void *	pBuf,    unsigned	size    )    {    register int sum = 0 ;    register unsigned char *p = pBuf ;    while( size > 0 )	{	sum += *p++;	size -= sizeof(*p);	}    return(sum);    }/********************************************************************************* tarRdBlks - read <nBlocks> blocks from tape** RETURNS: number of blocks actually got, or ERROR.*/LOCAL int tarRdBlks    (    MT_TAR_SOFT *pCtrl,		/* control structure */    MT_HBLOCK **ppBlk,		/* where to return buffer address */    unsigned int nBlocks	/* how many blocks to get */    )    {    register int rc ;    if (pCtrl->bValid <= 0)	{	/* buffer empty, read more blocks from tape */	rc = read(pCtrl->fd, pCtrl->pBuf->dummy, pCtrl->bFactor * TBLOCK);	if ( rc == ERROR )	    return ERROR ;	else if( rc == 0 )	    return 0 ;	else if( (rc % TBLOCK) != 0 )	    {	    printErr("tarRdBlks: tape block not multiple of %d\n", TBLOCK);	    return ERROR;	    }		pCtrl->bValid = rc / TBLOCK ;	pCtrl->pBnext = pCtrl->pBuf ;	}    rc = min((ULONG)pCtrl->bValid, nBlocks) ;    *ppBlk = pCtrl->pBnext ;    pCtrl->bValid -= rc ;    pCtrl->pBnext += rc ;    return( rc ) ;    }/********************************************************************************* mtAccess - check existence of path for a new file or directory <name>** RETURNS: OK or ERROR*/LOCAL STATUS mtAccess    (    const char *name    )    {    char tmpName [ NAMSIZ ] ;    struct stat st ;    int i ;    static char slash = '/' ;    register char *pSlash ;    strncpy( tmpName, name, NAMSIZ ) ;    pSlash = tmpName ;    for(i=0; i<MAXLEVEL; i++)	{	if ( (pSlash = strchr(pSlash, slash)) == NULL )	    return OK;	*pSlash = '\0' ;	if ( stat( tmpName, &st ) == OK )	    {	    if( S_ISDIR(st.st_mode ) == 0)		{		printErr("Path %s is not a directory\n", tmpName);		return ERROR;		}	    }	else	    {	    mkdir( tmpName );	    }	*pSlash = slash ;	/* restore slash position */	pSlash++;	}    printErr("Path too long %s\n", name );    return ERROR;    }/********************************************************************************* tarExtractFile - extract one file or directory from tar tape** Called from tarExtract for every file/dir found on tape.** RETURNS: OK or ERROR*/LOCAL STATUS tarExtractFile    (    MT_TAR_SOFT	*pCtrl,		/* control structure */    MT_HBLOCK	*pBlk,		/* header block */    BOOL	verbose		/* verbose */    )    {    register int rc, fd ;    int		sum = -1 ;		/* checksum */    int		size = 0 ;		/* file size in bytes */    int		nblks = 0;		/* file size in TBLOCKs */    int		mode ;    char *	fn ;			/* file/dir name */    /* Check the checksum of this header */    rc = sscanf( pBlk->dbuf.chksum, "%o", &sum ) ;	/* extract checksum */    bfill( pBlk->dbuf.chksum, 8, ' ');		/* fill blanks */    if( mtChecksum( pBlk->dummy, TBLOCK ) != sum )	{	printErr("bad checksum %d != %d\n", mtChecksum(		pBlk->dummy, TBLOCK), sum );	return ERROR;	}    /* Parse all fields of header that we need, and store them safely */    sscanf( pBlk->dbuf.mode, "%o", &mode );    sscanf( pBlk->dbuf.size, "%12o", &size );    fn = pBlk->dbuf.name ;    /* Handle directory */    if( (size == 0) && ( fn[ strlen(fn) - 1 ] == '/' ) )	{	if( strcmp(fn, "./") == 0)	    return OK;	if ( fn[ strlen(fn) - 1 ] == '/' )	/* cut the slash */	    fn[ strlen(fn) - 1 ] = '\0' ;	/* Must make sure that parent exists for this new directory */	if ( mtAccess(fn) == ERROR )	    {	    return ERROR;	    }	fd = open (fn, O_RDWR | O_CREAT, FSTAT_DIR | (mode & 0777) );	if (( fd == ERROR ) && (errnoGet() == S_dosFsLib_FILE_EXISTS))	    {	    printErr("Warning: directory %s already exists\n", fn );	    return OK;	    }	else if (fd == ERROR)	    {	    printErr("failed to create directory %s, %s, continuing\n",		     fn, strerror(errnoGet()));	    return OK;	    }	if(verbose)	    printErr("created directory %s.\n", fn );	return (close (fd));	}    /* non-empty file has a trailing slash, we better treat it as file and */    if ( fn[ strlen(fn) - 1 ] == '/' )	/* cut a trailing slash */	fn[ strlen(fn) - 1 ] = '\0' ;    /* Filter out links etc */    if ((pBlk->dbuf.linkflag != '\0') &&    	(pBlk->dbuf.linkflag != '0') &&	(pBlk->dbuf.linkflag != ' '))	{	printErr("we do not support links, %s skipped\n", fn );	return OK;	}    /* Handle Regular File - calculate number of blocks */    if( size > 0 )	nblks = ( size / TBLOCK ) +  ((size % TBLOCK)? 1 : 0 ) ;    /* Must make sure that directory exists for this new file */    if ( mtAccess(fn) == ERROR )	{	return ERROR;	}    /* Create file */    fd = open( fn, O_RDWR | O_CREAT, mode & 0777 ) ;    if( fd == ERROR )	{	printErr("failed to create file %s, %s, skipping!\n",		fn, strerror(errnoGet()));	fd = open( NULLDEV, O_RDWR, 0) ;	}    if(verbose)	printErr("extracting file %s, size %d bytes, %d blocks\n",		fn, size, nblks );    /* Loop until entire file extracted */    while (size > 0)	{	MT_HBLOCK *pBuf;	register int wc ;	rc = tarRdBlks( pCtrl, &pBuf, nblks) ;	if ( rc < 0 )	    {	    printErr("error reading tape\n");	    close(fd);	    return ERROR;	    }	wc = write( fd, pBuf->dummy, min( rc*TBLOCK, size ) ) ;	if( wc == ERROR )	    {	    printErr("error writing file\n");	    break;	    }	size -= rc*TBLOCK ;	nblks -= rc ;	}    /* Close the newly created file */    return( close(fd) ) ;    }/********************************************************************************* tarExtract - extract all files from a tar formatted tape** This is a UNIX-tar compatible utility that extracts entire* file hierarchies from tar-formatted archive.* The files are extracted with their original names and modes.* In some cases a file cannot be created on disk, for example if* the name is too long for regular DOS file name conventions,* in such cases entire files are skipped, and this program will* continue with the next file. Directories are created in order* to be able to create all files on tape.** The <tape> argument may be any tape device name or file name* that contains a tar formatted archive. If <tape> is equal "-",* standard input is used. If <tape> is NULL (or unspecified from Shell)* the default archive file name stored in global variable <TAPE> is used.** The <bfactor> dictates the blocking factor the tape was written with.* If 0, or unspecified from the shell, a default of 20 is used.** The <verbose> argument is a boolean, if set to 1, will cause informative* messages to be printed to standard error whenever an action is taken,* otherwise, only errors are reported.** All informative and error message are printed to standard error.** There is no way to selectively extract tar archives with this* utility. It extracts entire archives.*/STATUS tarExtract    (    char *	pTape,		/* tape device name */    int		bfactor,	/* requested blocking factor */    BOOL	verbose		/* if TRUE print progress info */    )    {    register 	int rc ;		/* return codes */    MT_TAR_SOFT	ctrl ;		/* control structure */    STATUS	retval = OK;    /* Set defaults */    if( pTape == NULL )	pTape = TAPE ;    if( bfactor == 0 )	bfactor = 20 ;    if( verbose )	printErr("Extracting from %s\n", pTape );    bzero( (char *)&ctrl, sizeof(ctrl) );    bzero( bZero, sizeof(bZero) );	/* not harmful for reentrancy */    /* Open tape device and initialize control structure */    if( strcmp(pTape, "-") == 0)	ctrl.fd = STD_IN;    else	ctrl.fd = open( pTape, O_RDONLY, 0) ;    if ( ctrl.fd < 0 )	{	printErr("Failed to open tape: %s\n", strerror(errnoGet()) );	return ERROR;	}        ctrl.bFactor = bfactor ;    ctrl.pBuf = KHEAP_ALLOC( bfactor * TBLOCK ) ;    if ( ctrl.pBuf == NULL )	{	printErr("Not enough memory, exiting.\n" );	if ( ctrl.fd != STD_IN )	    close( ctrl.fd );	return ERROR ;	}    /* all exits from now via goto in order to free the buffer */    /* Read the first block and adjust blocking factor */    rc = read( ctrl.fd, ctrl.pBuf->dummy, ctrl.bFactor*TBLOCK ) ;    if ( rc == ERROR )	{	printErr("read error at the beginning of tape, exiting.\n" );	retval = ERROR ;	goto finish;	}    else if( rc == 0 )	{	printErr("empty tape file, exiting.\n" );	goto finish;	}    else if( (rc % TBLOCK) != 0 )	{	printErr("tape block not multiple of %d, exiting.\n", TBLOCK);	retval = ERROR ;	goto finish;	}    ctrl.bValid = rc / TBLOCK ;    ctrl.pBnext = ctrl.pBuf ;    if ( ctrl.bFactor != ctrl.bValid )	{	if( verbose )	    printErr("adjusting blocking factor to %d\n", ctrl.bValid );	ctrl.bFactor = ctrl.bValid ;	}    /* End of overture, start processing files until end of tape */    FOREVER	{	MT_HBLOCK *	pBlk ;	if ( tarRdBlks( &ctrl, &pBlk, 1) != 1 )	    {	    retval = ERROR ;	    goto finish;	    }	if ( bcmp( pBlk->dummy, bZero, TBLOCK) == 0 )	    {	    if(verbose)		printErr("end of tape encountered, read until eof...\n");	    while( tarRdBlks( &ctrl, &pBlk, 1) > 0) ;	    if(verbose)		printErr("done.\n");	    retval = OK ;	    goto finish;	    }	if ( tarExtractFile( &ctrl, pBlk, verbose) == ERROR )	    {	    retval = ERROR;	    goto finish;	    }	} /* end of FOREVER */    finish:	if ( ctrl.fd != STD_IN )	    close( ctrl.fd );	KHEAP_FREE((char *)ctrl.pBuf );	return( retval );    }/********************************************************************************* tarWrtBlks - write <nBlocks> blocks to tape** Receives any number of blocks, and handles the blocking factor* mechanism using the pCtrl->pBuf internal buffer and associated* counters.** RETURNS: OK or ERROR;*/LOCAL STATUS tarWrtBlks    (    MT_TAR_SOFT *pCtrl,		/* control structure */    char *pBuf,			/* data to write */    unsigned int nBlocks	/* how many blocks to get */    )    {    register int rc ;    while( nBlocks > 0 )	{	if ((pCtrl->bValid <= 0) && (nBlocks >= (unsigned int)pCtrl->bFactor))	    {	    /* internal buffer empty, write directly */	    rc = write( pCtrl->fd, pBuf, pCtrl->bFactor*TBLOCK ) ;	    if ( rc == ERROR )		return ERROR ;	    /* adjust count and pointer */	    pBuf += TBLOCK * pCtrl->bFactor ;	    nBlocks -= pCtrl->bFactor ;	    }	else 	    {	    register int cnt ;	    /* internal buffer partially full, fill it up */

⌨️ 快捷键说明

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