]>
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.");
136 msg("Couldn't get current directory: %s",path
);
140 /* If this doesn't fit, we're in serious trouble */
142 strcat(path
,gnu_dumpfile
);
145 fp
=fopen(gnu_dumpfile
,"r");
146 if(fp
==0 && errno
!=ENOENT
) {
147 msg_perror("Can't open %s",gnu_dumpfile
);
152 fgets(buf
,sizeof(buf
),fp
);
157 while(fgets(buf
,sizeof(buf
),fp
)) {
158 strp
= &buf
[strlen(buf
)];
163 while(isdigit(*strp
))
166 while(isspace(*strp
))
168 while(isdigit(*strp
))
171 add_dir(un_quote_string(strp
),dev
,ino
,(char *)0);
182 extern char *quote_copy_string();
184 fp
=fopen(gnu_dumpfile
,"w");
186 msg_perror("Can't write to %s",gnu_dumpfile
);
189 fprintf(fp
,"%lu\n",this_time
);
190 for(dp
=dir_list
;dp
;dp
=dp
->next
) {
193 str
=quote_copy_string(dp
->name
);
195 fprintf(fp
,"%u %u %s\n",dp
->dev
,dp
->ino
,str
);
198 fprintf(fp
,"%u %u %s\n",dp
->dev
,dp
->ino
,dp
->name
);
209 for(dp
=dir_list
;dp
;dp
=dp
->next
) {
210 if(!strcmp(dp
->name
,name
))
217 /* Collect all the names from argv[] (or whatever), then expand them into
218 a directory tree, and put all the directories at the beginning. */
220 collect_and_sort_names()
222 struct name
*n
,*n_next
;
232 if(!namelist
) addname(".");
233 for(n
=namelist
;n
;n
=n_next
) {
235 if(n
->found
|| n
->dir_contents
)
237 if(n
->regexp
) /* FIXME just skip regexps for now */
240 if(chdir(n
->change_dir
)<0) {
241 msg_perror("can't chdir to %s",n
->change_dir
);
246 if (statx (n
->name
, &statbuf
, STATSIZE
, STX_HIDDEN
|STX_LINK
))
248 if(lstat(n
->name
,&statbuf
)<0)
251 msg_perror("can't stat %s",n
->name
);
254 if(S_ISDIR(statbuf
.st_mode
)) {
256 add_dir_name(n
->name
,statbuf
.st_dev
);
261 for(n
=namelist
;n
;n
=n
->next
)
263 namelist
=(struct name
*)merge_sort((PTR
)namelist
,num_names
,(char *)(&(namelist
->next
))-(char *)namelist
,name_cmp
);
265 for(n
=namelist
;n
;n
=n
->next
) {
278 return strcmp(n1
->name
,n2
->name
);
284 return strcmp(n1
->name
,n2
->name
);
294 frst
= (*(char **)p1
)+1;
295 scnd
= (*(char **)p2
)+1;
297 return strcmp(frst
,scnd
);
301 get_dir_contents(p
,device
)
306 register struct direct
*d
;
322 bufsiz
=strlen(p
)+NAMSIZ
;
323 namebuf
=ck_malloc(bufsiz
+2);
326 msg_perror("can't open directory %s",p
);
328 msg("error opening directory %s",p
);
335 all_children
= dp
? dp
->allnew
: 0;
336 (void) strcpy(namebuf
,p
);
337 if(p
[strlen(p
)-1]!='/')
338 (void) strcat(namebuf
,"/");
341 the_buffer
=init_buffer();
342 while(d
=readdir(dirp
)) {
346 if(is_dot_or_dotdot(d
->d_name
))
348 if(DP_NAMELEN(d
) + len
>=bufsiz
) {
350 namebuf
=ck_realloc(namebuf
,bufsiz
+2);
352 (void) strcpy(namebuf
+len
,d
->d_name
);
354 if (0 != f_follow_links
?
355 statx(namebuf
, &hs
, STATSIZE
, STX_HIDDEN
):
356 statx(namebuf
, &hs
, STATSIZE
, STX_HIDDEN
|STX_LINK
))
358 if (0 != f_follow_links
? stat(namebuf
, &hs
): lstat(namebuf
, &hs
))
361 msg_perror("can't stat %s",namebuf
);
364 if( (f_local_filesys
&& device
!=hs
.st_dev
)
365 || (f_exclude
&& check_exclude(namebuf
)))
366 add_buffer(the_buffer
,"N",1);
368 else if (S_ISHIDDEN (hs
.st_mode
)) {
369 add_buffer (the_buffer
, "D", 1);
370 strcat (d
->d_name
, "A");
374 else if(S_ISDIR(hs
.st_mode
)) {
375 if(dp
=get_dir(namebuf
)) {
376 if( dp
->dev
!=hs
.st_dev
377 || dp
->ino
!=hs
.st_ino
) {
379 msg("directory %s has been renamed.",namebuf
);
387 msg("Directory %s is new",namebuf
);
388 add_dir(namebuf
,hs
.st_dev
,hs
.st_ino
,"");
395 add_buffer(the_buffer
,"D",1);
396 } else if( !all_children
398 && new_time
>hs
.st_mtime
400 || new_time
>hs
.st_ctime
))
401 add_buffer(the_buffer
,"N",1);
403 add_buffer(the_buffer
,"Y",1);
404 add_buffer(the_buffer
,d
->d_name
,(int)(DP_NAMELEN(d
)+1));
406 add_buffer(the_buffer
,"\000\000",2);
409 /* Well, we've read in the contents of the dir, now sort them */
410 buf
=get_buffer(the_buffer
);
412 flush_buffer(the_buffer
);
416 for(p_buf
=buf
;*p_buf
;) {
423 vec
=(char **)malloc(sizeof(char *)*(n_strs
+1));
424 for(p_vec
=vec
,p_buf
=buf
;*p_buf
;p_buf
+=strlen(p_buf
)+1)
427 qsort((PTR
)vec
,n_strs
,sizeof(char *),dirent_cmp
);
428 new_buf
=(char *)malloc(p_buf
-buf
+2);
429 for(p_vec
=vec
,p_buf
=new_buf
;*p_vec
;p_vec
++) {
432 for(p_tmp
= *p_vec
;*p_buf
++= *p_tmp
++;)
437 flush_buffer(the_buffer
);
444 /* p is a directory. Add all the files in P to the namelist. If any of the
445 files is a directory, recurse on the subdirectory. . . */
447 add_dir_name(p
,device
)
462 /* char **vec,**p_vec;*/
463 /* int n_strs,n_size;*/
469 new_buf
=get_dir_contents(p
,device
);
471 for(n
=namelist
;n
;n
=n
->next
) {
472 if(!strcmp(n
->name
,p
)) {
473 n
->dir_contents
= new_buf
? new_buf
: "\0\0\0\0";
481 buflen
= NAMSIZ
<=len
? len
+ NAMSIZ
: NAMSIZ
;
482 namebuf
= ck_malloc(buflen
+1);
484 (void)strcpy(namebuf
,p
);
485 if(namebuf
[len
-1]!='/') {
489 for(p_buf
=new_buf
;*p_buf
;p_buf
+=sublen
+1) {
490 sublen
=strlen(p_buf
);
492 if(len
+sublen
>=buflen
) {
494 namebuf
= ck_realloc(namebuf
,buflen
+1);
496 (void)strcpy(namebuf
+len
,p_buf
+1);
498 add_dir_name(namebuf
,device
);
505 /* Returns non-zero if p is . or .. This could be a macro for speed. */
510 return (p
[0]=='.' && (p
[1]=='\0' || (p
[1]=='.' && p
[2]=='\0')));
519 gnu_restore(skipcrud
)
523 /* int current_dir_length; */
526 /* int archive_dir_length; */
532 extern struct stat hstat
; /* Stat struct corresponding */
535 extern union record
*head
;
537 dirp
=opendir(skipcrud
+current_file_name
);
540 /* The directory doesn't exist now. It'll be created.
541 In any case, we don't have to delete any files out
543 skip_file((long)hstat
.st_size
);
547 the_buffer
=init_buffer();
548 while(d
=readdir(dirp
)) {
549 if(is_dot_or_dotdot(d
->d_name
))
552 add_buffer(the_buffer
,d
->d_name
,(int)(DP_NAMELEN(d
)+1));
555 add_buffer(the_buffer
,"",1);
557 current_dir
=get_buffer(the_buffer
);
558 archive_dir
=(char *)malloc(hstat
.st_size
);
560 msg("Can't allocate %d bytes for restore",hstat
.st_size
);
561 skip_file((long)hstat
.st_size
);
565 for(size
=hstat
.st_size
;size
>0;size
-=copied
) {
566 from
=findrec()->charptr
;
568 msg("Unexpected EOF in archive\n");
571 copied
=endofrecs()->charptr
- from
;
574 bcopy((PTR
)from
,(PTR
)to
,(int)copied
);
576 userec((union record
*)(from
+copied
-1));
579 for(cur
=current_dir
;*cur
;cur
+=strlen(cur
)+1) {
580 for(arc
=archive_dir
;*arc
;arc
+=strlen(arc
)+1) {
586 p
=new_name(skipcrud
+current_file_name
,cur
);
587 if(f_confirm
&& !confirm("delete",p
)) {
592 fprintf(msg_file
,"%s: deleting %s\n",tar
,p
);
593 if(recursively_delete(p
)) {
594 msg("%s: Error while deleting %s\n",tar
,p
);
600 flush_buffer(the_buffer
);
605 recursively_delete(path
)
615 if(lstat(path
,&sbuf
)<0)
617 if(S_ISDIR(sbuf
.st_mode
)) {
619 /* path_len=strlen(path); */
623 while(dp
=readdir(dirp
)) {
624 if(is_dot_or_dotdot(dp
->d_name
))
626 path_buf
=new_name(path
,dp
->d_name
);
627 if(recursively_delete(path_buf
)) {
This page took 0.065937 seconds and 4 git commands to generate.