🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

1 total messages Started by Jeff Moskow Thu, 29 Oct 1992 13:55
tar enhancement.
#19
Author: Jeff Moskow
Date: Thu, 29 Oct 1992 13:55
249 lines
7181 bytes
On SYSV systems, it is not possible to easily detect sparse files, yet
they do exist and it would be nice to tar/untar them efficiently.  Here
is a patch which implements --sparse-file and --sparse-list commands to
allow users to tell tar which files to treat as "sparse".  It seems to
meet most of our needs and you may want to include it in tar 1.12

Jeff Moskow
jeff@rtr.com

Here's the patch:

-------------------------cut here--------------------------------------
*** create.c.orig	Mon Sep 14 17:19:28 1992
--- create.c	Wed Oct 28 12:58:36 1992
***************
*** 373,379 ****
  		
  		header_moved = 0;
  
- #ifdef BSD42
  		if (f_sparse_files) {
  		/*
  	 	 * JK - This is the test for sparseness: whether the
--- 373,378 ----
***************
*** 384,393 ****
  		 * at least one of those records in the file is just
  		 * a useless hole.
  		 */
  #ifdef hpux	/* Nice of HPUX to gratuitiously change it, huh?  - mib */
! 		        if (hstat.st_size - (hstat.st_blocks * 1024) > 1024 )
  #else
! 			if (hstat.st_size - (hstat.st_blocks * RECORDSIZE) > RECORDSIZE)
  #endif
  			  {
  				int	filesize = hstat.st_size;
--- 383,398 ----
  		 * at least one of those records in the file is just
  		 * a useless hole.
  		 */
+ #ifdef BSD42
  #ifdef hpux	/* Nice of HPUX to gratuitiously change it, huh?  - mib */
! 		        if (hstat.st_size - (hstat.st_blocks * 1024) > 1024 
! #else
! 			if (hstat.st_size - (hstat.st_blocks * RECORDSIZE) > RECORDSIZE
! #endif
!                             || check_sparse(p))
  #else
!                         if (check_sparse(p))
! 
  #endif
  			  {
  				int	filesize = hstat.st_size;
***************
*** 455,463 ****
--- 460,470 ----
  					
  			}
  		}
+ /*
  #else
  		upperbound=SPARSE_IN_HDR-1;
  #endif
+ */
  		
  		sizeleft = hstat.st_size;
  		/* Don't bother opening empty, world readable files. */
*** tar.c.orig	Mon Sep 14 17:31:38 1992
--- tar.c	Wed Oct 28 13:33:15 1992
***************
*** 92,97 ****
--- 92,100 ----
  
  extern FILE *msg_file;
  
+ int	check_sparse();
+ void	add_sparse();
+ void	add_sparse_file();
  int	check_exclude();
  void	add_exclude();
  void	add_exclude_file();
***************
*** 184,189 ****
--- 187,194 ----
  	{"portability",		0,	0,			'o'},
  	{"compress",		0,	&f_compress,		1},
  	{"compress-block",	0,	&f_compress,		2},
+ 	{"sparse-list",		1,	0,			18},
+ 	{"sparse-file",		1,	0,			19},
  	{"sparse",		0,	&f_sparse_files,	1},
  	{"tape-length",		1,	0,			'L'},
  	{"remove-files",	0,	&f_remove_files,	1},
***************
*** 358,363 ****
--- 363,378 ----
  			f_volno_file = optarg;
  			break;
  			
+ 		case 18:
+ 			f_sparse_files++;
+ 			add_sparse_file(optarg);
+ 			break;
+ 			
+ 		case 19:
+ 			f_sparse_files++;
+ 			add_sparse(optarg);
+ 			break;
+ 			
  		case 'g':	/* We are making a GNU dump; save
  				   directories at the beginning of
  				   the archive, and include in each
***************
*** 704,709 ****
--- 719,726 ----
      --preserve-order	list of names to extract is sorted to match archive\n\
  --same-owner		create extracted files with the same ownership \n\
  -S, --sparse		handle sparse files efficiently\n\
+ --sparse-file FILE	treat FILE as sparse (implicit -S as well)\n\
+ --sparse-list FILE	treat files listed in FILE as sparse (implicit -S)\n\
  -T, --files-from F	get names to extract or create from file F\n\
  --null			-T reads null-terminated names, disable -C\n\
  --totals			print total bytes written with --create\n\
***************
*** 1394,1399 ****
--- 1411,1534 ----
  		if(   (str=strstr(name,exclude[n]))
   		   && (str==name || str[-1]=='/')
  		   && str[strlen(exclude[n])]=='\0')
+ 			return 1;
+ 	}
+ 	return 0;
+ }
+ 
+ char *s_buffer = 0;
+ int size_s_buffer;
+ int free_s_buffer;
+ 
+ char **sparse = 0;
+ int size_sparse = 0;
+ int free_sparse = 0;
+ 
+ char **re_sparse = 0;
+ int size_re_sparse = 0;
+ int free_re_sparse = 0;
+ 
+ void
+ add_sparse(name)
+ char *name;
+ {
+ /*	char *rname;*/
+ /*	char **tmp_ptr;*/
+ 	int size_buf;
+ 
+ 	un_quote_string(name);
+ 	size_buf = strlen(name);
+ 
+ 	if(s_buffer==0) {
+ 		s_buffer = (char *)ck_malloc(size_buf+1024);
+ 		free_s_buffer=1024;
+ 	} else if(free_s_buffer<=size_buf) {
+ 		char *old_s_buffer;
+ 		char **tmp_ptr;
+ 
+ 		old_s_buffer = s_buffer;
+ 		s_buffer = (char *)ck_realloc(s_buffer,size_s_buffer+1024);
+ 		free_s_buffer = 1024;
+ 		for(tmp_ptr=sparse;tmp_ptr<sparse+size_sparse;tmp_ptr++)
+ 			*tmp_ptr= s_buffer + ((*tmp_ptr) - old_s_buffer);
+ 		for(tmp_ptr=re_sparse;tmp_ptr<re_sparse+size_re_sparse;tmp_ptr++)
+ 			*tmp_ptr= s_buffer + ((*tmp_ptr) - old_s_buffer);
+ 	}
+ 
+ 	if(is_regex(name)) {
+ 		if(free_re_sparse==0) {
+ 			re_sparse= (char **)(re_sparse ? ck_realloc(re_sparse,(size_re_sparse+32)*sizeof(char *)) : ck_malloc(sizeof(char *)*32));
+ 			free_re_sparse+=32;
+ 		}
+ 		re_sparse[size_re_sparse]=s_buffer+size_s_buffer;
+ 		size_re_sparse++;
+ 		free_re_sparse--;
+ 	} else {
+ 		if(free_sparse==0) {
+ 			sparse=(char **)(sparse ? ck_realloc(sparse,(size_sparse+32)*sizeof(char *)) : ck_malloc(sizeof(char *)*32));
+ 			free_sparse+=32;
+ 		}
+ 		sparse[size_sparse]=s_buffer+size_s_buffer;
+ 		size_sparse++;
+ 		free_sparse--;
+ 	}
+ 	strcpy(s_buffer+size_s_buffer,name);
+ 	size_s_buffer+=size_buf+1;
+ 	free_s_buffer-=size_buf+1;
+ }
+ 
+ void
+ add_sparse_file(file)
+ char *file;
+ {
+ 	FILE *fp;
+ 	char buf[1024];
+ 
+ 	if(strcmp(file, "-"))
+ 		fp=fopen(file,"r");
+ 	else
+ 		/* Let's hope the person knows what they're doing. */
+ 		/* Using -X - -T - -f - will get you *REALLY* strange
+ 		   results. . . */
+ 		fp=stdin;
+ 
+ 	if(!fp) {
+ 		msg_perror("can't open %s",file);
+ 		exit(2);
+ 	}
+ 	while(fgets(buf,1024,fp)) {
+ /*		int size_buf;*/
+ 		char *end_str;
+ 
+ 		end_str=rindex(buf,'\n');
+ 		if(end_str)
+ 			*end_str='\0';
+ 		add_sparse(buf);
+ 
+ 	}
+ 	fclose(fp);
+ }
+ 
+ /* Returns non-zero if the file 'name' should be treated as sparse */
+ int
+ check_sparse(name)
+ char *name;
+ {
+ 	int n;
+ 	char *str;
+ 	extern char *strstr();
+ 
+ 	for(n=0;n<size_re_sparse;n++) {
+ 		if(fnmatch(re_sparse[n], name, FNM_TARPATH) == 0)
+ 			return 1;
+ 	}
+ 	for(n=0;n<size_sparse;n++) {
+ 		/* Accept the output from strstr only if it is the last
+ 		   part of the string.  There is certainly a faster way to
+ 		   do this. . . */
+ 		if(   (str=strstr(name,sparse[n]))
+  		   && (str==name || str[-1]=='/')
+ 		   && str[strlen(sparse[n])]=='\0')
  			return 1;
  	}
  	return 0;
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads