Thread View: gnu.utils.bug
1 messages
1 total messages
Started by Jeff Moskow
Thu, 29 Oct 1992 13:55
tar enhancement.
Author: Jeff Moskow
Date: Thu, 29 Oct 1992 13:55
Date: Thu, 29 Oct 1992 13:55
249 lines
7181 bytes
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