]>
Dogcows Code - chaz/tar/blob - src/gnu.c
1 /* GNU dump extensions to tar.
2 Copyright (C) 1988, 1992 Free Software Foundation
4 This file is part of GNU Tar.
6 GNU Tar is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Tar is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Tar; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 #include <sys/types.h>
33 #if defined(_POSIX_VERSION) || defined(DIRENT)
39 #define DP_NAMELEN(x) strlen((x)->d_name)
40 #endif /* _POSIX_VERSION or DIRENT */
41 #if !defined(_POSIX_VERSION) && !defined(DIRENT) && defined(BSD42)
43 #define DP_NAMELEN(x) (x)->d_namlen
44 #endif /* not _POSIX_VERSION and BSD42 */
47 #define DP_NAMELEN(x) (x)->d_namlen
50 #if defined(USG) && !defined(_POSIX_VERSION) && !defined(DIRENT)
52 #define DP_NAMELEN(x) strlen((x)->d_name)
53 #endif /* USG and not _POSIX_VERSION and not DIRENT */
59 extern time_t new_time
;
60 extern FILE *msg_file
;
64 extern PTR
ck_malloc();
65 extern PTR
ck_realloc();
67 extern PTR
init_buffer();
68 extern char *get_buffer();
69 int is_dot_or_dotdot();
70 extern void add_buffer();
71 extern void flush_buffer();
73 int recursively_delete();
75 char *un_quote_string();
77 extern char *new_name();
79 static void add_dir_name();
89 static struct dirname
*dir_list
;
90 static time_t this_time
;
93 add_dir(name
,dev
,ino
,text
)
101 dp
=(struct dirname
*)malloc(sizeof(struct dirname
));
108 dp
->name
=malloc(strlen(name
)+1);
109 strcpy(dp
->name
,name
);
122 static char *path
= 0;
125 path
= ck_malloc(PATH_MAX
);
127 if(gnu_dumpfile
[0]!='/') {
128 #if defined(__MSDOS__) || defined(USG) || defined(_POSIX_VERSION)
129 if(!getcwd(path
,PATH_MAX
)) {
130 msg("Couldn't get current directory.");
137 msg("Couldn't get current directory: %s",path
);
141 /* If this doesn't fit, we're in serious trouble */
143 strcat(path
,gnu_dumpfile
);
146 fp
=fopen(gnu_dumpfile
,"r");
147 if(fp
==0 && errno
!=ENOENT
) {
148 msg_perror("Can't open %s",gnu_dumpfile
);
153 fgets(buf
,sizeof(buf
),fp
);
158 while(fgets(buf
,sizeof(buf
),fp
)) {
159 strp
= &buf
[strlen(buf
)];
164 while(isdigit(*strp
))
167 while(isspace(*strp
))
169 while(isdigit(*strp
))
172 add_dir(un_quote_string(strp
),dev
,ino
,(char *)0);
183 extern char *quote_copy_string();
185 fp
=fopen(gnu_dumpfile
,"w");
187 msg_perror("Can't write to %s",gnu_dumpfile
);
190 fprintf(fp
,"%lu\n",this_time
);
191 for(dp
=dir_list
;dp
;dp
=dp
->next
) {
194 str
=quote_copy_string(dp
->name
);
196 fprintf(fp
,"%u %u %s\n",dp
->dev
,dp
->ino
,str
);
199 fprintf(fp
,"%u %u %s\n",dp
->dev
,dp
->ino
,dp
->name
);
210 for(dp
=dir_list
;dp
;dp
=dp
->next
) {
211 if(!strcmp(dp
->name
,name
))
218 /* Collect all the names from argv[] (or whatever), then expand them into
219 a directory tree, and put all the directories at the beginning. */
221 collect_and_sort_names()
223 struct name
*n
,*n_next
;
233 if(!namelist
) addname(".");
234 for(n
=namelist
;n
;n
=n_next
) {
236 if(n
->found
|| n
->dir_contents
)
238 if(n
->regexp
) /* FIXME just skip regexps for now */
241 if(chdir(n
->change_dir
)<0) {
242 msg_perror("can't chdir to %s",n
->change_dir
);
247 if (statx (n
->name
, &statbuf
, STATSIZE
, STX_HIDDEN
|STX_LINK
))
249 if(lstat(n
->name
,&statbuf
)<0)
252 msg_perror("can't stat %s",n
->name
);
255 if(S_ISDIR(statbuf
.st_mode
)) {
257 add_dir_name(n
->name
,statbuf
.st_dev
);
262 for(n
=namelist
;n
;n
=n
->next
)
264 namelist
=(struct name
*)merge_sort((PTR
)namelist
,num_names
,(char *)(&(namelist
->next
))-(char *)namelist
,name_cmp
);
266 for(n
=namelist
;n
;n
=n
->next
) {
279 return strcmp(n1
->name
,n2
->name
);
285 return strcmp(n1
->name
,n2
->name
);
295 frst
= (*(char **)p1
)+1;
296 scnd
= (*(char **)p2
)+1;
298 return strcmp(frst
,scnd
);
302 get_dir_contents(p
,device
)
307 register struct direct
*d
;
323 bufsiz
=strlen(p
)+NAMSIZ
;
324 namebuf
=ck_malloc(bufsiz
+2);
327 msg_perror("can't open directory %s",p
);
329 msg("error opening directory %s",p
);
336 all_children
= dp
? dp
->allnew
: 0;
337 (void) strcpy(namebuf
,p
);
338 if(p
[strlen(p
)-1]!='/')
339 (void) strcat(namebuf
,"/");
342 the_buffer
=init_buffer();
343 while(d
=readdir(dirp
)) {
347 if(is_dot_or_dotdot(d
->d_name
))
349 if(DP_NAMELEN(d
) + len
>=bufsiz
) {
351 namebuf
=ck_realloc(namebuf
,bufsiz
+2);
353 (void) strcpy(namebuf
+len
,d
->d_name
);
355 if (0 != f_follow_links
?
356 statx(namebuf
, &hs
, STATSIZE
, STX_HIDDEN
):
357 statx(namebuf
, &hs
, STATSIZE
, STX_HIDDEN
|STX_LINK
))
359 if (0 != f_follow_links
? stat(namebuf
, &hs
): lstat(namebuf
, &hs
))
362 msg_perror("can't stat %s",namebuf
);
365 if( (f_local_filesys
&& device
!=hs
.st_dev
)
366 || (f_exclude
&& check_exclude(namebuf
)))
367 add_buffer(the_buffer
,"N",1);
369 else if (S_ISHIDDEN (hs
.st_mode
)) {
370 add_buffer (the_buffer
, "D", 1);
371 strcat (d
->d_name
, "A");
375 else if(S_ISDIR(hs
.st_mode
)) {
376 if(dp
=get_dir(namebuf
)) {
377 if( dp
->dev
!=hs
.st_dev
378 || dp
->ino
!=hs
.st_ino
) {
380 msg("directory %s has been renamed.",namebuf
);
388 msg("Directory %s is new",namebuf
);
389 add_dir(namebuf
,hs
.st_dev
,hs
.st_ino
,"");
396 add_buffer(the_buffer
,"D",1);
397 } else if( !all_children
399 && new_time
>hs
.st_mtime
401 || new_time
>hs
.st_ctime
))
402 add_buffer(the_buffer
,"N",1);
404 add_buffer(the_buffer
,"Y",1);
405 add_buffer(the_buffer
,d
->d_name
,(int)(DP_NAMELEN(d
)+1));
407 add_buffer(the_buffer
,"\000\000",2);
410 /* Well, we've read in the contents of the dir, now sort them */
411 buf
=get_buffer(the_buffer
);
413 flush_buffer(the_buffer
);
417 for(p_buf
=buf
;*p_buf
;) {
424 vec
=(char **)malloc(sizeof(char *)*(n_strs
+1));
425 for(p_vec
=vec
,p_buf
=buf
;*p_buf
;p_buf
+=strlen(p_buf
)+1)
428 qsort((PTR
)vec
,n_strs
,sizeof(char *),dirent_cmp
);
429 new_buf
=(char *)malloc(p_buf
-buf
+2);
430 for(p_vec
=vec
,p_buf
=new_buf
;*p_vec
;p_vec
++) {
433 for(p_tmp
= *p_vec
;*p_buf
++= *p_tmp
++;)
438 flush_buffer(the_buffer
);
445 /* p is a directory. Add all the files in P to the namelist. If any of the
446 files is a directory, recurse on the subdirectory. . . */
448 add_dir_name(p
,device
)
463 /* char **vec,**p_vec;*/
464 /* int n_strs,n_size;*/
470 new_buf
=get_dir_contents(p
,device
);
472 for(n
=namelist
;n
;n
=n
->next
) {
473 if(!strcmp(n
->name
,p
)) {
474 n
->dir_contents
= new_buf
? new_buf
: "\0\0\0\0";
482 buflen
= NAMSIZ
<=len
? len
+ NAMSIZ
: NAMSIZ
;
483 namebuf
= ck_malloc(buflen
+1);
485 (void)strcpy(namebuf
,p
);
486 if(namebuf
[len
-1]!='/') {
490 for(p_buf
=new_buf
;*p_buf
;p_buf
+=sublen
+1) {
491 sublen
=strlen(p_buf
);
493 if(len
+sublen
>=buflen
) {
495 namebuf
= ck_realloc(namebuf
,buflen
+1);
497 (void)strcpy(namebuf
+len
,p_buf
+1);
499 add_dir_name(namebuf
,device
);
506 /* Returns non-zero if p is . or .. This could be a macro for speed. */
511 return (p
[0]=='.' && (p
[1]=='\0' || (p
[1]=='.' && p
[2]=='\0')));
520 gnu_restore(skipcrud
)
524 /* int current_dir_length; */
527 /* int archive_dir_length; */
533 extern struct stat hstat
; /* Stat struct corresponding */
536 extern union record
*head
;
538 dirp
=opendir(skipcrud
+current_file_name
);
541 /* The directory doesn't exist now. It'll be created.
542 In any case, we don't have to delete any files out
544 skip_file((long)hstat
.st_size
);
548 the_buffer
=init_buffer();
549 while(d
=readdir(dirp
)) {
550 if(is_dot_or_dotdot(d
->d_name
))
553 add_buffer(the_buffer
,d
->d_name
,(int)(DP_NAMELEN(d
)+1));
556 add_buffer(the_buffer
,"",1);
558 current_dir
=get_buffer(the_buffer
);
559 archive_dir
=(char *)malloc(hstat
.st_size
);
561 msg("Can't allocate %d bytes for restore",hstat
.st_size
);
562 skip_file((long)hstat
.st_size
);
566 for(size
=hstat
.st_size
;size
>0;size
-=copied
) {
567 from
=findrec()->charptr
;
569 msg("Unexpected EOF in archive\n");
572 copied
=endofrecs()->charptr
- from
;
575 bcopy((PTR
)from
,(PTR
)to
,(int)copied
);
577 userec((union record
*)(from
+copied
-1));
580 for(cur
=current_dir
;*cur
;cur
+=strlen(cur
)+1) {
581 for(arc
=archive_dir
;*arc
;arc
+=strlen(arc
)+1) {
587 p
=new_name(skipcrud
+current_file_name
,cur
);
588 if(f_confirm
&& !confirm("delete",p
)) {
593 fprintf(msg_file
,"%s: deleting %s\n",tar
,p
);
594 if(recursively_delete(p
)) {
595 msg("%s: Error while deleting %s\n",tar
,p
);
601 flush_buffer(the_buffer
);
606 recursively_delete(path
)
616 if(lstat(path
,&sbuf
)<0)
618 if(S_ISDIR(sbuf
.st_mode
)) {
620 /* path_len=strlen(path); */
624 while(dp
=readdir(dirp
)) {
625 if(is_dot_or_dotdot(dp
->d_name
))
627 path_buf
=new_name(path
,dp
->d_name
);
628 if(recursively_delete(path_buf
)) {
This page took 0.06515 seconds and 4 git commands to generate.