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

📄 jar.c

📁 kaffe Java 解释器语言,源码,Java的子集系统,开放源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	copy32le(sig[0], buf, 0);	/*	 * We're instantiating this structure in multiple stages so we don't	 * move the file pointer.	 */	return( 0 );}/* * Read a JAR header from the file and check it's signature. */static int readJarHeader(jarFile *jf, uint32 sig, void *buf, size_t len){	int retval = 0;	assert(jf != 0);	assert((sig == CENTRAL_HEADER_SIGNATURE) ||		(sig == LOCAL_HEADER_SIGNATURE) ||		(sig == CENTRAL_END_SIGNATURE));	assert(buf != 0);		if( jarRead(jf, buf, len, instantiateSignature) == len )	{		/* Check the signature */		if( sig == ((uint32 *)buf)[0] )		{			retval = 1;		}		else		{			jf->error = JAR_ERROR_BAD_SIGNATURE;		}	}	return( retval );}/* * Add a jarEntry to the given jarFile. */static void addJarEntry(jarFile *jf, jarEntry *je){	unsigned int hash;	assert(jf != 0);	assert(jf->table != 0);	assert(je != 0);	assert(je->fileName != 0);		hash = hashName(je->fileName);	hash = hash % jf->tableSize;	je->next = jf->table[hash];	jf->table[hash] = je;}/* * Create a jarEntry structure for the current central directory record in * the file. */static int initJarEntry(jarFile *jf, jarEntry *je, char **name_strings){	jarCentralDirectoryRecord cdr;	int retval = 0;	assert(jf != 0);	assert(je != 0);	assert(name_strings != 0);	assert(*name_strings != 0);	/* Read the header */	if( readJarHeader(jf, CENTRAL_HEADER_SIGNATURE, &cdr,			  FILE_SIZEOF_CENTRALDIR) )	{		int read_size;		/* Instantiate the header */		jarInstantiate(jf, (uint8 *)&cdr, instantiateCentralDir);		je->next = 0;		/* Allocate space for our name */		(*name_strings) -= cdr.fileNameLength + 1;		je->fileName = *name_strings;		/* Copy whatever we care about from the file record */		je->dosTime = (cdr.lastModifiedDate << 16) |			cdr.lastModifiedTime;		je->localHeaderOffset = cdr.relativeLocalHeaderOffset;		je->uncompressedSize = cdr.uncompressedSize;		je->compressedSize = cdr.compressedSize;		je->compressionMethod = cdr.compressionMethod;		/* Read the file name */		if( (read_size = jarRead(jf,					 (uint8*) je->fileName,					 cdr.fileNameLength,					 0)) >= 0 )		{			/* Make sure its terminated */			je->fileName[cdr.fileNameLength] = 0;			/*			 * Skip the extra field and comment, we should			 * now be positioned at the next directory			 * record, if there is one.			 */			if( jarSeek(jf,				    cdr.extraFieldLength +				    cdr.fileCommentLength,				    SEEK_CUR) > 0 )			{				retval = 1;				assert(strlen(je->fileName) ==				       cdr.fileNameLength);			}		}	}	else	{		jf->error = JAR_ERROR_BAD_CENTRAL_RECORD_SIGNATURE;	}	return( retval );}/* * Find the central directory end, find out the number of central directory * entries and seek to the start of them. */static int getCentralDirCount(jarFile *jf, unsigned int *out_dir_size){	int pos, retval = -1;	assert(jf != 0);	assert(out_dir_size != 0);		/* The central directory end is at the end of the file */	if( (pos = jarSeek(jf, -FILE_SIZEOF_CENTRALEND, SEEK_END)) > 0 )	{		jarCentralDirectoryEnd cde;		if( readJarHeader(jf, CENTRAL_END_SIGNATURE,				  &cde, FILE_SIZEOF_CENTRALEND) )		{			jarInstantiate(jf, (uint8 *)&cde,				       instantiateCentralDirEnd);			if( cde.nrOfEntriesInDirectory >			    (cde.sizeOfDirectory / FILE_SIZEOF_CENTRALDIR) )			{				jf->error = JAR_ERROR_ENTRY_COUNT_MISMATCH;			}			else if( cde.sizeOfDirectory > pos )			{				jf->error = JAR_ERROR_IMPOSSIBLY_LARGE_DIRECTORY;			}			else if( jarSeek(jf,					 cde.offsetOfDirectory,					 SEEK_SET) >= 0 )			{				*out_dir_size = cde.sizeOfDirectory;				retval = cde.nrOfEntriesInDirectory;			}		}		else		{			jf->error = JAR_ERROR_NO_END;		}	}	return( retval );}/* * Read the central directory records from the file */static int readJarEntries(jarFile *jf){	unsigned int dir_size;	int retval = 0;	assert(jf != 0);		if( (jf->count = getCentralDirCount(jf, &dir_size)) >= 0 )	{		unsigned int table_size;		/*		 * Compute a sensible size for the hash table base on the		 * number of entries in the jar.		 */		jf->tableSize = (jf->count + 3) / 4;		/*		 * We want a single block of memory for all jarEntry's and		 * their names.		 */		/* Hash table buckets */		table_size = sizeof(jarEntry *) * jf->tableSize;		/* Add the total size of the central directory records */		table_size += dir_size;		/* ... however, we don't read the whole central dir struct */		table_size -= jf->count * FILE_SIZEOF_CENTRALDIR;		/* ... we use jarEntry's */		table_size += jf->count * sizeof(jarEntry);		/* ... with NULL terminated name strings. */		table_size += jf->count * 1;		if( (jf->table = gc_malloc(table_size, GC_ALLOC_JAR)) )		{			char *name_strings;			jarEntry *je;			int lpc;			/* jarEntry's are right after the table */			je = (jarEntry *)(jf->table + jf->tableSize);			/* names are at the end of the memory block */			name_strings = ((char *)jf->table) + table_size;			retval = 1;			/*			 * Read in the central directory records and add them			 * to the hash table.			 */			for( lpc = 0; (lpc < jf->count) && retval; lpc++ )			{				if( initJarEntry(jf, je, &name_strings) )				{					addJarEntry(jf, je);					je++;				}				else				{					retval = 0;				}			}					}		else		{			jf->error = JAR_ERROR_OUT_OF_MEMORY;		}	}	else if( jf->error )	{	}	else	{		retval = 1;	}	return( retval );}/* * Simple function to handle uncompressing the file data. */static uint8 *inflateJarData(jarFile *jf, jarEntry *je,			     jarLocalHeader *lh, uint8 *buf){	uint8 *retval = 0;	assert(jf != 0);	assert(je != 0);	assert(lh != 0);	assert(buf != 0);		switch( je->compressionMethod )	{	case COMPRESSION_STORED:		retval = buf;		break;	case COMPRESSION_DEFLATED:		if( je->uncompressedSize == 0 )		{			/* XXX What to do? */			retval = gc_malloc(8, GC_ALLOC_JAR);		}		else if( (retval = gc_malloc(je->uncompressedSize,					     GC_ALLOC_JAR)) )		{			if( inflate_oneshot(buf,					    je->compressedSize,					    retval,					    je->uncompressedSize) == 0 )			{				addToCounter(&jarmem, "vmmem-jar files",					     1, GCSIZEOF(retval));			}			else			{				jf->error = JAR_ERROR_DECOMPRESSION_FAILED;				gc_free(retval);				retval = 0;			}		}		else		{			jf->error = JAR_ERROR_OUT_OF_MEMORY;		}		gc_free(buf);		break;	default:		jf->error = JAR_ERROR_UNSUPPORTED_COMPRESSION;		gc_free(buf);		break;	}	return( retval );}uint8 *getDataJarFile(jarFile *jf, jarEntry *je){	uint8 *buf = 0, *retval = 0;	jarLocalHeader lh;#if !defined(KAFFEH)	int iLockRoot;#endif	assert(jf != 0);	assert(je != 0);	lockMutex(jf);	/* Move to the local header in the file and read it. */	if( !jf->error &&	    (jarSeek(jf, je->localHeaderOffset, SEEK_SET) >= 0) &&	    readJarHeader(jf, LOCAL_HEADER_SIGNATURE, &lh,			  FILE_SIZEOF_LOCALHEADER) )	{		jarInstantiate(jf, (uint8 *)&lh, instantiateLocalHeader);		/* Skip the local file name and extra fields */		jarSeek(jf,			lh.fileNameLength + lh.extraFieldLength,			SEEK_CUR);		/* Allocate some memory and read in the file data */		if( (buf = (uint8 *)gc_malloc(je->compressedSize,					      GC_ALLOC_JAR)) )		{			if( jarRead(jf, buf, je->compressedSize, 0) < 0 )			{				gc_free(buf);				buf = 0;				jf->error = JAR_ERROR_IO;			}		}		else		{			jf->error = JAR_ERROR_OUT_OF_MEMORY;		}	}	unlockMutex(jf);	if( buf )	{	        /* Try to decompress it */	        retval = inflateJarData(jf, je, &lh, buf);	}	return( retval );}/* * If a jarFile is cached it may be closed before it is used again so we might * have to reopen the file. */static jarFile *delayedOpenJarFile(jarFile *jf){	jarFile *retval = 0;	int fd, rc;	assert(jf != 0);	/* Open the file and check for a different modified time */	if( !(rc = KOPEN(jf->fileName, O_RDONLY|O_BINARY, 0, &fd)) )	{#if !defined(STATIC_JAR_FILES)		struct stat jar_stat;		if( !(rc = KFSTAT(fd, &jar_stat)) )		{			if( jar_stat.st_mtime == jf->lastModified )			{#endif /* !defined(STATIC_JAR_FILES) */#if !defined(KAFFEH)				int iLockRoot;#endif								/* Only set the fd in the structure here */				lockMutex(jf);				if( jf->fd == -1 )					jf->fd = fd; /* We're first */				else					KCLOSE(fd); /* Someone else set it */				unlockMutex(jf);				retval = jf;#if !defined(STATIC_JAR_FILES)			}			else			{				KCLOSE(fd);				/* The file was changed, reopen it. */				removeJarFile(jf);				retval = openJarFile(jf->fileName);			}		}		else		{			KCLOSE(fd);		}#endif /* !defined(STATIC_JAR_FILES) */	}	/*	 * The file either disappeared, or a new one was made, get rid of the	 * old one.	 */	if( retval != jf )	{		removeJarFile(jf);		closeJarFile(jf);	}	return( retval );}jarFile *openJarFile(char *name){	jarFile *retval = 0;	assert(name != 0);		/* Look for it in the cache first */	if( (retval = findJarFile(name)) )	{		/* Check if we need to reopen the file */		if( (retval->fd == -1)#ifdef HAVE_MMAP		    && (retval->data == MAP_FAILED)#endif		    )		{			retval = delayedOpenJarFile(retval);		}	}	/*	 * If a cached file wasn't found or its broken then try to make a new	 * one.	 */	if( !retval &&	    (retval = (jarFile *)gc_malloc(sizeof(jarFile) +					   strlen(name) +					   1,					   GC_ALLOC_JAR)) )	{		int rc, error = 0;		retval->fileName = (char *)(retval + 1);		strcpy(retval->fileName, name);		retval->users = 1;		retval->lastModified = 0;		retval->count = 0;		retval->error = 0;		retval->fd = -1;		retval->table = 0;		retval->tableSize = 0;#ifdef HAVE_MMAP 		retval->data = MAP_FAILED;#endif /* HAVE_MMAP */		if( (rc = KOPEN(name, O_RDONLY|O_BINARY, 0, &retval->fd)) )		{			/* Error opening the file */			error = 1;		}		else		{			struct stat jar_stat;						if( KFSTAT(retval->fd, &jar_stat) == 0 ) 			{				if( (jar_stat.st_mode & S_IFDIR) )				{					/* Its a directory! */					error = 1;				}				else				{					retval->lastModified =						jar_stat.st_mtime;#ifdef HAVE_MMAP					/*					 * Setup the mmap members in the					 * jarFile structure					 */					retval->size = jar_stat.st_size;					retval->data = mmap(NULL,							    retval->size,							    PROT_READ,							    MAP_SHARED,							    retval->fd,							    0);					if( retval->data == MAP_FAILED )					{						/*						 * Unsuccessful mmap, fallback						 * to the FD for now.						 */					}					else					{						/*						 * Successful mmap, close the						 * FD						 */						KCLOSE(retval->fd);						retval->fd = -1;						retval->offset = 0;					}#endif				}			}			else			{				error = 1;			}			/*			 * If everythings a go, figure out how many directory			 * entries there are and read them in.			 */			if( !error && !readJarEntries(retval) )			{				error = 1;			}		}		if( !error )		{			addToCounter(&jarmem, "vmmem-jar files",				     1, GCSIZEOF(retval));			if( retval->table ) {				addToCounter(&jarmem, "vmmem-jar files",					     1, GCSIZEOF(retval->table));			}			/*			 * No errors, so we cache the file.  If someone else			 * beat us to the cache we'll use theirs instead.			 */			retval = cacheJarFile(retval);		}		else		{			/* Something went wrong, cleanup our mess */			retval->users = 0;			collectJarFile(retval);			retval = 0;		}	}	return( retval );}void closeJarFile(jarFile *jf){	if( jf )	{#if !defined(KAFFEH)		int iLockRoot;#endif		lockStaticMutex(&jarCache.lock);		jf->users--;		if( jf->users == 0 )		{			if( jarCache.count <= JAR_FILE_CACHE_MAX )			{				/*				 * The cache isn't full so if its in there				 * we can leave it.				 */#ifdef HAVE_MMAP				if( jf->data != MAP_FAILED )				{					/*					 * Unmap the object and force FD I/O					 * from now on.					 */					munmap(jf->data, jf->size);					jf->data = MAP_FAILED;				}				else#endif				{					KCLOSE(jf->fd);				}				jf->fd = -1;			}			else			{				/* Too many files in the cache, remove it */				removeJarFile(jf);			}			if( !(jf->flags & JFF_CACHED) )			{				/*				 * Not cached anymore and this was the last				 * reference so collect the file.				 */				collectJarFile(jf);			}		}		unlockStaticMutex(&jarCache.lock);	}}jarEntry *lookupJarFile(jarFile *jf, char *entry_name){	jarEntry *retval = 0;	assert(jf != 0);	assert(entry_name != 0);		/*	 * No need to visit the kernel here since we're just walking the	 * structure.	 */	if( jf->tableSize )	{		unsigned int hash;		jarEntry *je;		hash = hashName(entry_name);		hash = hash % jf->tableSize;		je = jf->table[hash];		while( je && !retval )		{			if( !strcmp(je->fileName, entry_name) )				retval = je;			je = je->next;		}	}	return( retval );}

⌨️ 快捷键说明

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