@ -8,14 +8,18 @@ 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					# include  <zlib.h>  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					# include  <getopt.h>  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					# include  <stdbool.h>  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					# include  <errno.h>  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					# include  "espfsformat.h"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					# include  "heatshrink_encoder.h"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					# include  "parsing.h"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					# include  "httpd-logging.h"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					# define DEFAULT_GZIP_EXTS "html,css,js,svg,png,jpg,gif"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					void  show_version ( char  * * argv ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					void  show_help ( int  retval ,  char  * * argv ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					struct  InputFileLinkedListEntry ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					# define DEFAULT_GZIP_EXTS "css,js,svg,png,jpg,jpeg,webm,ico,gif"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					# define DEFAULT_C_VARNAME "espfs_image"  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					struct  InputFileLinkedListEntry  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  char  * name ;   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -27,7 +31,7 @@ static struct InputFileLinkedListEntry *s_inputFiles = NULL; 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					static  struct  InputFileLinkedListEntry  * s_lastInputFile  =  NULL ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					/// Output file FD
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					static  int  s_outFd  =  1 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					static  int  s_outFd  =  STDOUT_FILENO ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					/// Array of gzipped extensions, ends with a NULL pointer
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					static  char  * * s_gzipExtensions  =  NULL ;  
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -69,7 +73,7 @@ size_t compressHeatshrink(const uint8_t *in, size_t insize, uint8_t *out, size_t 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    level  =  ( level  -  1 )  /  2 ;  //level is now 0, 1, 2, 3, 4
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    heatshrink_encoder  * enc  =  heatshrink_encoder_alloc ( ws [ level ] ,  ls [ level ] ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( enc  = =  NULL )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        perror ( " allocating mem for heatshrink " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        es pfs_ error( " allocating mem for heatshrink " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    //Save encoder parms as first byte
   
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -96,7 +100,7 @@ size_t compressHeatshrink(const uint8_t *in, size_t insize, uint8_t *out, size_t 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }  while  ( insize  ! =  0 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( insize  ! =  0 )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        fprintf ( stderr ,  " Heatshrink: Bug? insize is still %d. sres=%d pres=%d \n " ,  ( int )  insize ,  sres ,  pres ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        espfs_error ( " Heatshrink: Bug? insize is still %d. sres=%d pres=%d " ,  ( int )  insize ,  sres ,  pres ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -111,10 +115,9 @@ size_t compressHeatshrink(const uint8_t *in, size_t insize, uint8_t *out, size_t 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					 *  @ param  insize  -  len  of  the  uncompressed  input   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					 *  @ param [ out ]  out  -  destination  buffer  for  the  compressed  data   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					 *  @ param  outcap  -  capacity  of  the  output  buffer   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					 *  @ param  level  -  compression  level ,  1 - 9 ;  - 1  for  default .   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					 *  @ return  actual  length  of  the  compressed  data   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					 */   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					size_t  compressGzip ( const  uint8_t  * in ,  size_t  insize ,  uint8_t  * out ,  size_t  outcap ,  int  level )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					size_t  compressGzip ( const  uint8_t  * in ,  size_t  insize ,  uint8_t  * out ,  size_t  outcap )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    z_stream  stream ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    int  zresult ;   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -127,21 +130,21 @@ size_t compressGzip(const uint8_t *in, size_t insize, uint8_t *out, size_t outca 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    stream . next_out  =  out ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    stream . avail_out  =  ( uInt )  outcap ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    // 31 -> 15 window bits + 16 for gzip
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    zresult  =  deflateInit2 ( & stream ,  level ,  Z_DEFLATED ,  31 ,  8 ,  Z_DEFAULT_STRATEGY ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    zresult  =  deflateInit2 ( & stream ,  Z_BEST_COMPRESSION  /* we want the smallest possible files */ ,  Z_DEFLATED ,  31 ,  8 ,  Z_DEFAULT_STRATEGY ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( zresult  ! =  Z_OK )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        fprintf ( stderr ,  " DeflateInit2 failed with code %d \n " ,  zresult ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        espfs_error ( " DeflateInit2 failed with code %d " ,  zresult ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    zresult  =  deflate ( & stream ,  Z_FINISH ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( zresult  ! =  Z_STREAM_END )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        fprintf ( stderr ,  " Deflate failed with code %d \n " ,  zresult ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        espfs_error ( " Deflate failed with code %d " ,  zresult ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    zresult  =  deflateEnd ( & stream ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( zresult  ! =  Z_OK )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        fprintf ( stderr ,  " DeflateEnd failed with code %d \n " ,  zresult ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        espfs_error ( " DeflateEnd failed with code %d " ,  zresult ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -239,31 +242,31 @@ int handleFile(int fd, const char *name, int compression_mode, int level, const 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            csize  =  100 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }  // enlarge buffer if this is the case
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        cdat  =  cdatbuf  =  malloc ( csize ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        csize  =  compressGzip ( fdat ,  size ,  cdat ,  csize ,  level ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        compression_mode  =  COMPRESS_NONE ;  // don't use heatshrink if gzip was already used - it would only make it bigger
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        flags  =  FLAG_GZIP ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }  else  if  ( compression_mode  = =  COMPRESS_NONE )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        csize  =  compressGzip ( fdat ,  size ,  cdat ,  csize ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        compression_mode  =  EFS_ COMPRESS_NONE;  // don't use heatshrink if gzip was already used - it would only make it bigger
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        flags  =  EFS_ FLAG_GZIP;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }  else  if  ( compression_mode  = =  EFS_ COMPRESS_NONE)  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        csize  =  size ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        cdat  =  fdat ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }  else  if  ( compression_mode  = =  COMPRESS_HEATSHRINK )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }  else  if  ( compression_mode  = =  EFS_ COMPRESS_HEATSHRINK)  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        cdat  =  cdatbuf  =  malloc ( size  *  2 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        csize  =  compressHeatshrink ( fdat ,  size ,  cdat ,  size  *  2 ,  level ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }  else  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        fprintf ( stderr ,  " Unknown compression - %d \n " ,  compression_mode ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        espfs_error ( " Unknown compression - %d " ,  compression_mode ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( csize  >  size )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        fprintf ( stderr ,  " ! Compression enbiggened %s, embed as plain \ n " ,  name ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        espfs_dbg ( " ! Compression enbiggened %s, embed as plain " ,  name ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        //Compressing enbiggened this file. Revert to uncompressed store.
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        compression_mode  =  COMPRESS_NONE ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        compression_mode  =  EFS_ COMPRESS_NONE;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        csize  =  size ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        cdat  =  fdat ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        flags  =  0 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    //Fill header data
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    h . magic  =  htole32 ( ESP FS_MAGIC ) ;  // ('E' << 0) + ('S' << 8) + ('f' << 16) + ('s' << 24);
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    h . magic  =  htole32 ( EFS_MAGIC ) ;  // ('E' << 0) + ('S' << 8) + ('f' << 16) + ('s' << 24);
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    h . flags  =  flags ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    h . compression  =  ( uint8_t )  compression_mode ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    h . nameLen  =  realNameLen  =  ( uint16_t )  strlen ( name )  +  1 ;  // zero terminator
   
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -299,10 +302,10 @@ int handleFile(int fd, const char *name, int compression_mode, int level, const 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    // debug outputs ...
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( compName  ! =  NULL )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  ( h . compression  = =  COMPRESS_HEATSHRINK )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  ( h . compression  = =  EFS_ COMPRESS_HEATSHRINK)  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            * compName  =  " heatshrink " ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }  else  if  ( h . compression  = =  COMPRESS_NONE )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            if  ( h . flags  &  FLAG_GZIP )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }  else  if  ( h . compression  = =  EFS_ COMPRESS_NONE)  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            if  ( h . flags  &  EFS_ FLAG_GZIP)  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                * compName  =  " gzip " ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            }  else  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                * compName  =  " none " ;   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -322,9 +325,9 @@ int handleFile(int fd, const char *name, int compression_mode, int level, const 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					void  finishArchive ( void )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    EspFsHeader  h ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    h . magic  =  htole32 ( ESP FS_MAGIC ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    h . flags  =  FLAG_LASTFILE ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    h . compression  =  COMPRESS_NONE ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    h . magic  =  htole32 ( EFS_MAGIC ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    h . flags  =  EFS_ FLAG_LASTFILE;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    h . compression  =  EFS_ COMPRESS_NONE;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    h . nameLen  =  0 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    h . fileLenComp  =  0 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    h . fileLenDecomp  =  0 ;   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -339,7 +342,7 @@ void finishArchive(void) 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					 */   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					void  queueInputFile ( const  char  * name )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " INFILE: %s \n " ,  name ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    espfs_dbg ( " INFILE: %s " ,  name ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    struct  InputFileLinkedListEntry  * tmp  =  malloc ( sizeof ( struct  InputFileLinkedListEntry ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    tmp - > name  =  strdup ( name ) ;   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -354,48 +357,70 @@ void queueInputFile(const char *name) 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					int  main ( int  argc ,  char  * * argv )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					enum  OpMode  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  OM_INVALID  =  0 ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  OM_PACK  =  ' P ' ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  OM_LIST  =  ' L ' ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  OM_EXTRACT  =  ' X ' ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					  OM_EMBED  =  ' M ' ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					} ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					# define BUFLEN 1024  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					int  main ( const  int  argc ,  char  * * argv )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    int  f ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    char  inputFileName [ 1024 ] ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    char  inputFileName [ BUFLEN ] ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    char  tempbuf [ BUFLEN ] ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    struct  stat  statBuf ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    int  serr ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    int  rate ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    int  err  =  0 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    int  compType ;   //default compression type - heatshrink
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    int  compLvl  =  - 1 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    bool  use_gzip  =  false ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    enum  OpMode  opmode  =  OM_INVALID ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    compType  =  COMPRESS_HEATSHRINK ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    compType  =  EFS_ COMPRESS_HEATSHRINK;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    int  c ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    char  * outfile  =  NULL ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    char  * c_outfile  =  NULL ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    char  * outFileName  =  NULL ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    char  * c_varname  =  NULL ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    char  * parseFile  =  NULL ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    char  * stripPath  =  NULL ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    char  * extractFile  =  NULL ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    char  * extractFileName  =  NULL ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    size_t  num_input_files  =  0 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    bool  read_from_stdin  =  false ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    while  ( 1 )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        int  option_index  =  0 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        static  struct  option  long_options [ ]  =  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " parse " ,       required_argument ,  0 ,  ' p ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " extract " ,     required_argument ,  0 ,  ' e ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " compress " ,    required_argument ,  0 ,  ' c ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " gzip " ,        no_argument ,        0 ,  ' z ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " gzip-all " ,    no_argument ,        0 ,  ' G ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " level " ,       required_argument ,  0 ,  ' l ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " gzip-exts " ,   required_argument ,  0 ,  ' g ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " input " ,       required_argument ,  0 ,  ' i ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " output " ,      required_argument ,  0 ,  ' o ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " c-output " ,    required_argument ,  0 ,  ' C ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " c-varname " ,   required_argument ,  0 ,  ' N ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " strip-path " ,  required_argument ,  0 ,  ' S ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                // Help
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " help " ,        no_argument ,        0 ,  ' h ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " version " ,     no_argument ,        0 ,  ' V ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                // Main operation (one at a time)
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " pack " ,        no_argument ,        0 ,  ' P ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " list " ,        no_argument ,        0 ,  ' L ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " extract " ,     required_argument ,  0 ,  ' X ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " embed " ,       no_argument ,        0 ,  ' M ' } ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                // Common options
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " input " ,       required_argument ,  0 ,  ' i ' } ,  // input file; "-" to read them as lines on stdin; can be repeated in case of --pack.
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                // Input files can also be given as stand-alone arguments at the end, e.g. as a result of glob
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " output " ,      required_argument ,  0 ,  ' o ' } ,  // output file; "-" for stdout (default)
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                // Options for --pack
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " compress " ,    required_argument ,  0 ,  ' c ' } ,  // 0 = no, 1 = heatshrink (def)
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " level " ,       required_argument ,  0 ,  ' l ' } ,  // Heatshrink compression level 1-9, -1 = default
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " gzip " ,        optional_argument ,  0 ,  ' z ' } ,  // Gzipped extensions; no arg = default, "*" = all, comma-separated list = custom exts
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " strip " ,       required_argument ,  0 ,  ' s ' } ,  // path removed from all input files, e.g. when they are in a subfolder
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                // Options for --embed
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                { " varname " ,     required_argument ,  0 ,  ' n ' } ,  // name of the array; the length variable is {varname}_len
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                {  /* end marker */  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        } ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        c  =  getopt_long ( argc ,  argv ,  " c:l:g:zGS:e:hp:C:i:o:0123456789 " ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        c  =  getopt_long ( argc ,  argv ,  " h?VPLX:Mi:o:c:l:z::s:n: " ,   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                        long_options ,  & option_index ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  ( c  = =  - 1 )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            break ;   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -403,119 +428,195 @@ int main(int argc, char **argv) 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        switch  ( c )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' h ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                goto  show_help ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' ? ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                show_help ( 0 ,  argv ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' z ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                use_gzip  =  true ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' V ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                show_version ( argv ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' 0 '  . . .  ' 9 ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                compLvl  =  c  -  ' 0 ' ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' P ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                opmode  =  OM_PACK ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' p ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                parseFile  =  strdup ( optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' L ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                opmode  =  OM_LIST ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' e ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                extractFile  =  strdup ( optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' X ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                opmode  =  OM_EXTRACT ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                if  ( extractFileName )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    espfs_error ( " can extract only one file at a time! " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                extractFileName  =  strdup ( optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' C ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                c_outfile  =  strdup ( optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' M ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                opmode  =  OM_EMBED ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' N ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                c_varname  =  strdup ( optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' i ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                if  ( 0  = =  strcmp ( optarg ,  " - " ) )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    read_from_stdin  =  true ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                }  else  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    queueInputFile ( optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                num_input_files + + ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' S ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                stripPath  =  strdup ( optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' o ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                outFileName   =  strdup ( optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' c ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                compType  =  atoi ( optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                errno  =  0 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                compType  =  ( int )  strtol ( optarg ,  NULL ,  10 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                if  ( errno  ! =  0  | |  compType  <  0  | |  compType  >  1 )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    espfs_error ( " Bad compression mode: %s " ,  optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' G ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                use_gzip  =  true ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                s_gzipAll  =  true ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' l ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                errno  =  0 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                compLvl  =  ( int )  strtol ( optarg ,  NULL ,  10 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                if  ( errno  ! =  0  | |  compLvl  <  1  | |  compLvl  >  9 )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    espfs_error ( " Bad compression level: %s " ,  optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' g ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' z ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                use_gzip  =  true ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                if  ( optarg )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    if  ( 0  = =  strcmp ( " * " ,  optarg ) )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                        s_gzipAll  =  true ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    }  else  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                        parseGzipExtensions ( optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' l ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                compLvl  =  atoi ( optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                if  ( compLvl  <  1  | |  compLvl  >  9 )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    fprintf ( stderr ,  " Bad compression level: %d \n " ,  compLvl ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    err  =  1 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    goto  show_help ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                }  else  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    parseGzipExtensions ( strdup ( DEFAULT_GZIP_EXTS ) ) ;  // memory leak! ehh
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' i ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                queueInputFile ( optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' s ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                stripPath  =  strdup ( optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' o ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                outfil e  =  strdup ( optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' n ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                c_varnam e  =  strdup ( optarg ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            case  ' ? ' :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                goto  show_help ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            default :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                fprintf ( stderr ,  " Unknown option: %c \n " ,  c ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                err  =  1 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                goto  show_help ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                espfs_error ( " Unknown option: %c " ,  c ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    FILE  * outfp  =  NULL ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( outfile  & &  0  ! =  strcmp ( " - " ,  outfile ) )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        fprintf ( stderr ,  " Writing to %s \n " ,  outfile ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        outfp  =  fopen ( outfile ,  " w+ " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  ( ! outfp )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            perror ( outfile ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            return  1 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        s_outFd  =  fileno ( outfp ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        ftruncate ( s_outFd ,  0 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }  else  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  ( outfile )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            free ( outfile ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            outfile  =  NULL ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        fprintf ( stderr ,  " Writing to stdout \n \n " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( ! use_gzip )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        s_gzipExtensions  =  NULL ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( parseFile )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        parseEspfsImage ( parseFile ,  extractFile ,  s_outFd ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        exit ( 0 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    bool  want_output ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    bool  allows_multiple_inputs ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    switch  ( opmode )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        case  OM_PACK :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            want_output  =  true ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            allows_multiple_inputs  =  true ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        case  OM_LIST :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            want_output  =  false ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            allows_multiple_inputs  =  false ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        case  OM_EXTRACT :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        case  OM_EMBED :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            want_output  =  true ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            allows_multiple_inputs  =  false ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( s_gzipExtensions  = =  NULL  & &  use_gzip )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        parseGzipExtensions ( strdup ( DEFAULT_GZIP_EXTS ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        default :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            espfs_error ( " Specify one of the operation modes: -P, -L, -X, -M " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( optind  <  argc )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    /* Input */   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    while  ( optind  <  argc )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            queueInputFile ( argv [ optind + + ] ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        char  * s  =  argv [ optind + + ] ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  ( 0  = =  strcmp ( s ,  " - " ) )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            read_from_stdin  =  true ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }  else  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            queueInputFile ( s ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            num_input_files + + ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( ! s_inputFiles )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        fprintf ( stderr ,  " Reading input file names from stdin \n " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( num_input_files  = =  0  & &  read_from_stdin  & &  opmode  = =  OM_PACK )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        read_from_stdin  =  false ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        espfs_dbg ( " Reading input file names from stdin " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        while  ( fgets ( inputFileName ,  sizeof ( inputFileName ) ,  stdin ) )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            //Kill off '\n' at the end
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            inputFileName [ strlen ( inputFileName )  -  1 ]  =  0 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            queueInputFile ( inputFileName ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            num_input_files + + ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( ! read_from_stdin )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  ( num_input_files  = =  0 )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            if  ( allows_multiple_inputs )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                espfs_error ( " Specify input file(s)! " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            }  else  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                espfs_error ( " Specify input file! " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }  else  if  ( ! allows_multiple_inputs  & &  num_input_files  >  1 )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            espfs_error ( " Mode %c requires exactly one input file! " ,  opmode ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    char  * inFileName  =  read_from_stdin  ?  NULL  :  s_inputFiles - > name ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    /* Output */   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( ! want_output  & &  outFileName )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        espfs_error ( " Output file is not allowed in %c mode! " ,  opmode ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    FILE  * outFile  =  NULL ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    bool  write_to_stdout  =  outFileName  & &  ( 0  = =  strcmp ( " - " ,  outFileName ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( outFileName  & &  ! write_to_stdout )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        espfs_dbg ( " Writing to %s " ,  outFileName ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        outFile  =  fopen ( outFileName ,  " w+ " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  ( ! outFile )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            perror ( outFileName ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            return  1 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        s_outFd  =  fileno ( outFile ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        ftruncate ( s_outFd ,  0 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }  else  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  ( outFileName )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            free ( outFileName ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            outFileName  =  NULL ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  ( want_output  & &  ! write_to_stdout )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            espfs_error ( " Specify output file! Use -o - for stdout " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    /* Do it! */   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    switch  ( opmode )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        case  OM_PACK :  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            struct  InputFileLinkedListEntry  * entry  =  s_inputFiles ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            while  ( entry )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                char  * name  =  entry - > name ;   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -525,7 +626,7 @@ int main(int argc, char **argv) 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    //Strip off './' or '/' madness.
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    char  * embeddedName  =  name ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    f  =  open ( name ,  O_RDONLY ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    if  ( f  >  0 )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                        // relative path starting with ./, remove that
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                        if  ( embeddedName [ 0 ]  = =  ' . '  & &  embeddedName [ 1 ]  = =  ' / ' )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                            embeddedName  + =  2 ;   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -537,16 +638,20 @@ int main(int argc, char **argv) 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                        // remove leading slash, if any
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                        if  ( embeddedName [ 0 ]  = =  ' / ' )  {  embeddedName + + ;  }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            if  ( f  >  0 )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                        const  char  * compName  =  " unknown " ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                        rate  =  handleFile ( f ,  embeddedName ,  compType ,  compLvl ,  & compName ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                fprintf ( stderr ,  " %s (%d%%, %s) \n " ,  embeddedName ,  rate ,  compName ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                        ( void )  rate ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                        espfs_dbg ( " %s (%d%%, %s) " ,  embeddedName ,  rate ,  compName ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                        close ( f ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    }  else  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                perror ( name ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                        snprintf ( tempbuf ,  BUFLEN ,  " Open %s for reading: %s " ,  name ,  strerror ( errno ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                        espfs_error ( " %s " ,  tempbuf ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                        exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                }  else  if  ( serr  ! =  0 )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            perror ( name ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    snprintf ( tempbuf ,  BUFLEN ,  " Stat %s: %s " ,  name ,  strerror ( errno ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    espfs_error ( " %s " ,  tempbuf ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                entry  =  entry - > next ;   
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				 
				
					@ -554,72 +659,125 @@ int main(int argc, char **argv) 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            finishArchive ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            fsync ( s_outFd ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            if  ( outFile )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                fclose ( outFile ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }  break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    if  ( outfp )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if  ( outfile  & &  c_outfile )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            const  size_t  imagelen  =  ( size_t )  lseek ( s_outFd ,  0 ,  SEEK_END ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            lseek ( s_outFd ,  0 ,  SEEK_SET ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        case  OM_LIST :  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            if  ( ! inFileName )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                espfs_error ( " Input file required! " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            parseEspfsImage ( inFileName ,  NULL ,  s_outFd ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }  break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            FILE  * coutf  =  fopen ( c_outfile ,  " w+ " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            if  ( ! coutf )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                perror ( c_outfile ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                return  1 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        case  OM_EXTRACT :  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            if  ( ! inFileName )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                espfs_error ( " Input file required! " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            parseEspfsImage ( inFileName ,  extractFileName ,  s_outFd ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }  break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        case  OM_EMBED :  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            FILE  * inFile  =  NULL ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            int  inFD  =  STDIN_FILENO ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            if  ( ! read_from_stdin )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                inFile  =  fopen ( inFileName ,  " r " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                if  ( ! inFile )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    snprintf ( tempbuf ,  BUFLEN ,  " Open %s for reading: %s " ,  inFileName ,  strerror ( errno ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    espfs_error ( " %s " ,  tempbuf ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    exit ( 1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                inFD  =  fileno ( inFile ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            int  cfd  =  fileno ( coutf ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            ftruncate ( cfd ,  0 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            if  ( ! c_varname )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                c_varname  =  strdup ( " espfs_image " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                c_varname  =  strdup ( DEFAULT_C_VARNAME ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            fprintf ( coutf ,  " unsigned char %s[%lu] = { " ,  c_varname ,  imagelen ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            for  ( size_t  i  =  0 ;  i  <  imagelen ;  i + + )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                fprintf ( coutf ,  ( i  %  16 )  ?  "   "  :  " \n    " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            size_t  len ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            len  =  ( size_t )  snprintf ( tempbuf ,  BUFLEN ,  " unsigned char %s[] = { " ,  c_varname ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            write ( s_outFd ,  tempbuf ,  len ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            uint8_t  u ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                read ( s_outFd ,  & u ,  1 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                fprintf ( coutf ,  " 0x%02x, " ,  u ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            size_t  imageLen  =  0 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            while  ( 1  = =  read ( inFD ,  & u ,  1 ) )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                len  =  ( size_t )  snprintf ( tempbuf ,  BUFLEN ,  " %s0x%02x, " ,  ( ( imageLen  %  16 )  ?  "   "  :  " \n    " ) ,  u ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                write ( s_outFd ,  tempbuf ,  len ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                imageLen + + ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            fprintf ( coutf ,  " \n }; \n unsigned int %s_len = %lu; \n " ,  c_varname ,  imagelen ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            fsync ( cfd ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            fclose ( coutf ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            len  =  ( size_t )  snprintf ( tempbuf ,  BUFLEN ,  " \n }; \n unsigned int %s_len = %lu; \n " ,  c_varname ,  imageLen ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            write ( s_outFd ,  tempbuf ,  len ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            fsync ( s_outFd ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            if  ( outFile )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                fclose ( outFile ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            if  ( inFile )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                fclose ( inFile ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }  break ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        fclose ( outfp ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        default :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            __builtin_unreachable ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    return  0 ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					__attribute__ ( ( noreturn ) )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					void  show_version ( char  * * argv )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    // to stdout
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    printf ( " %s #%s \n " ,  argv [ 0 ] ,  GIT_HASH ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    exit ( 0 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					__attribute__ ( ( noreturn ) )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					void  show_help ( int  retval ,  char  * * argv )  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					{  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    // to stderr, this can happen as a response to bad args
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    show_help :   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    //               ##########**********##########**********##########----------$$$$$$$$$$----------$$$$$$$$$$----------| 80 chars
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " %s - Program to create espfs images \n " ,  argv [ 0 ] ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " Options: \n " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " [-p|--parse FILE] \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "     Parse an espfs file and show a list of its contents. No other options apply in this mode. \n " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " [-e|--extract FILE] \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "     Extract a file with the given name from the parsed file (-p) \n " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " [-S|--strip-path PATH] \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "     Remove the given path from input file names before packing \n " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " [-c|--compress COMPRESSOR] \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "     0 - None, 1 - Heatshrink (default) \n " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " [-l|--level LEVEL] or [-0 through -9] \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "     compression level 1-9, higher is better but uses more RAM \n " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " [-z|--gzip] \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "     use gzip for files with extensions matching  " DEFAULT_GZIP_EXTS " \n " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " [-G|--gzip-all] \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "     use gzip for all files \n " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " [-g|--gzip-exts GZIPPED_EXTENSIONS] \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "     use gzip for files with custom extensions, comma-separated \n " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " [-i|--input FILE] \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "     Input file, can be multiple. Files can also be passed at the end without -i, or as lines on stdin \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "     if not specified by args \n " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " [-o|--output FILE] \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "     Output file name; if not specified or equal to  \" - \" , outputs to stdout \n " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " [-C|--c-output FILE] \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "     C embed output file name (an uint8_t array for embedding); can be used only if a binary output \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "     file is specified as well (using -o), as this reads the output file and converts it as a second step. \n " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " [-h|--help \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "     Show help. \n \n " ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    exit ( err ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " %s #%s - Program to create and parse espfs images \n " ,  argv [ 0 ] ,  GIT_HASH ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    fprintf ( stderr ,  " \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    " One main operation mode must be selected: \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "   -P, --pack              Create a binary fs image \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "   -L, --list              Read a binary fs image and show the contents \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "   -X, --extract=NAME      Read a binary fs image and extract a file with the given name \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "   -M, --embed             Read a binary file (typically the binary fs image produced by -P) and \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "                           convert it to C syntax byte array and a constant with its length. \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "   -h, -?, --help          Show this help (has precedence over other options) \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    " \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    " Additional arguments specify the input, output and parameters: \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "   -i, --input=FILE        Input file name. Can be used multiple times. For convenience with globs, \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "                           input files can be given at the end of the option string without -i. \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "                           The  \" - \"  filename means  \" read from stdin \" : \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "                            - pack: reads file names to pack from stdin (e.g. piped from `find`) \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "                            - embed: read the binary file from stdin (e.g. piped from the --pack \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "                              option, avoiding the creation of a temporary binary file) \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "                           Stdin reading is not supported for options --extract and --list. \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    " \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "   -o, --output=FILE       Output file,  \" - \"  for stdout. \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "                           Output can't be changed in --list mode. \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    " \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    " Pack options: \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "   -c, --compress=MODE     Compression mode, 0=none, 1=heatshrink (default). Not used if the file \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "                           is gzipped - additional compression wouldn't be useful. \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "   -l, --level=LEVEL       Compression level, 1-9, -1=default. 1=worst, 9=best compression, but uses \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "                           more RAM to unpack. \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "   -s, --strip=PATH        Strip a path prefix from all packed files (e.g. a subfolder name) \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "   -z, --gzip[=EXTS]       Enable gzip compression for some file types (filename extensions). \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "                           By default, enabled for  " DEFAULT_GZIP_EXTS " . \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "                           Set EXTS to * to enable gzip for all files. Custom extensions are set as \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "                           a comma-separated list. \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    " \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    " Embed options: \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "   -n, --varname=VARNAME   Set custom array name to use in the generated C code. The length constant \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    "                           is called {VARNAME}_len. The default VARNAME is  \" " DEFAULT_C_VARNAME " \" \n "   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    exit ( retval ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}