]>
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 ();
90 static struct dirname
*dir_list
;
91 static time_t this_time
;
94 add_dir (name
, dev
, ino
, text
)
102 dp
= (struct dirname
*) malloc (sizeof (struct dirname
));
109 dp
->name
= malloc (strlen (name
) + 1);
110 strcpy (dp
->name
, name
);
123 static char *path
= 0;
126 path
= ck_malloc (PATH_MAX
);
128 if (gnu_dumpfile
[0] != '/')
130 #if defined(__MSDOS__) || defined(USG) || defined(_POSIX_VERSION)
131 if (!getcwd (path
, PATH_MAX
))
133 msg ("Couldn't get current directory.");
141 msg ("Couldn't get current directory: %s", path
);
145 /* If this doesn't fit, we're in serious trouble */
147 strcat (path
, gnu_dumpfile
);
150 fp
= fopen (gnu_dumpfile
, "r");
151 if (fp
== 0 && errno
!= ENOENT
)
153 msg_perror ("Can't open %s", gnu_dumpfile
);
158 fgets (buf
, sizeof (buf
), fp
);
162 new_time
= atol (buf
);
164 while (fgets (buf
, sizeof (buf
), fp
))
166 strp
= &buf
[strlen (buf
)];
167 if (strp
[-1] == '\n')
171 while (isdigit (*strp
))
174 while (isspace (*strp
))
176 while (isdigit (*strp
))
179 add_dir (un_quote_string (strp
), dev
, ino
, (char *) 0);
190 extern char *quote_copy_string ();
192 fp
= fopen (gnu_dumpfile
, "w");
195 msg_perror ("Can't write to %s", gnu_dumpfile
);
198 fprintf (fp
, "%lu\n", this_time
);
199 for (dp
= dir_list
; dp
; dp
= dp
->next
)
203 str
= quote_copy_string (dp
->name
);
206 fprintf (fp
, "%u %u %s\n", dp
->dev
, dp
->ino
, str
);
210 fprintf (fp
, "%u %u %s\n", dp
->dev
, dp
->ino
, dp
->name
);
221 for (dp
= dir_list
; dp
; dp
= dp
->next
)
223 if (!strcmp (dp
->name
, name
))
230 /* Collect all the names from argv[] (or whatever), then expand them into
231 a directory tree, and put all the directories at the beginning. */
233 collect_and_sort_names ()
235 struct name
*n
, *n_next
;
247 for (n
= namelist
; n
; n
= n_next
)
250 if (n
->found
|| n
->dir_contents
)
252 if (n
->regexp
) /* FIXME just skip regexps for now */
255 if (chdir (n
->change_dir
) < 0)
257 msg_perror ("can't chdir to %s", n
->change_dir
);
262 if (statx (n
->name
, &statbuf
, STATSIZE
, STX_HIDDEN
| STX_LINK
))
264 if (lstat (n
->name
, &statbuf
) < 0)
267 msg_perror ("can't stat %s", n
->name
);
270 if (S_ISDIR (statbuf
.st_mode
))
273 add_dir_name (n
->name
, statbuf
.st_dev
);
278 for (n
= namelist
; n
; n
= n
->next
)
280 namelist
= (struct name
*) merge_sort ((PTR
) namelist
, num_names
, (char *) (&(namelist
->next
)) - (char *) namelist
, name_cmp
);
282 for (n
= namelist
; n
; n
= n
->next
)
292 struct name
*n1
, *n2
;
297 return strcmp (n1
->name
, n2
->name
);
304 return strcmp (n1
->name
, n2
->name
);
314 frst
= (*(char **) p1
) + 1;
315 scnd
= (*(char **) p2
) + 1;
317 return strcmp (frst
, scnd
);
321 get_dir_contents (p
, device
)
326 register struct direct
*d
;
342 bufsiz
= strlen (p
) + NAMSIZ
;
343 namebuf
= ck_malloc (bufsiz
+ 2);
347 msg_perror ("can't open directory %s", p
);
349 msg ("error opening directory %s", p
);
358 all_children
= dp
? dp
->allnew
: 0;
359 (void) strcpy (namebuf
, p
);
360 if (p
[strlen (p
) - 1] != '/')
361 (void) strcat (namebuf
, "/");
362 len
= strlen (namebuf
);
364 the_buffer
= init_buffer ();
365 while (d
= readdir (dirp
))
370 if (is_dot_or_dotdot (d
->d_name
))
372 if (DP_NAMELEN (d
) + len
>= bufsiz
)
375 namebuf
= ck_realloc (namebuf
, bufsiz
+ 2);
377 (void) strcpy (namebuf
+ len
, d
->d_name
);
379 if (0 != f_follow_links
?
380 statx (namebuf
, &hs
, STATSIZE
, STX_HIDDEN
) :
381 statx (namebuf
, &hs
, STATSIZE
, STX_HIDDEN
| STX_LINK
))
383 if (0 != f_follow_links
? stat (namebuf
, &hs
) : lstat (namebuf
, &hs
))
386 msg_perror ("can't stat %s", namebuf
);
389 if ((f_local_filesys
&& device
!= hs
.st_dev
)
390 || (f_exclude
&& check_exclude (namebuf
)))
391 add_buffer (the_buffer
, "N", 1);
393 else if (S_ISHIDDEN (hs
.st_mode
))
395 add_buffer (the_buffer
, "D", 1);
396 strcat (d
->d_name
, "A");
400 else if (S_ISDIR (hs
.st_mode
))
402 if (dp
= get_dir (namebuf
))
404 if (dp
->dev
!= hs
.st_dev
405 || dp
->ino
!= hs
.st_ino
)
408 msg ("directory %s has been renamed.", namebuf
);
418 msg ("Directory %s is new", namebuf
);
419 add_dir (namebuf
, hs
.st_dev
, hs
.st_ino
, "");
420 dp
= get_dir (namebuf
);
426 add_buffer (the_buffer
, "D", 1);
428 else if (!all_children
430 && new_time
> hs
.st_mtime
432 || new_time
> hs
.st_ctime
))
433 add_buffer (the_buffer
, "N", 1);
435 add_buffer (the_buffer
, "Y", 1);
436 add_buffer (the_buffer
, d
->d_name
, (int) (DP_NAMELEN (d
) + 1));
438 add_buffer (the_buffer
, "\000\000", 2);
441 /* Well, we've read in the contents of the dir, now sort them */
442 buf
= get_buffer (the_buffer
);
445 flush_buffer (the_buffer
);
451 for (p_buf
= buf
; *p_buf
;)
455 tmp
= strlen (p_buf
) + 1;
459 vec
= (char **) malloc (sizeof (char *) * (n_strs
+ 1));
460 for (p_vec
= vec
, p_buf
= buf
; *p_buf
; p_buf
+= strlen (p_buf
) + 1)
463 qsort ((PTR
) vec
, n_strs
, sizeof (char *), dirent_cmp
);
464 new_buf
= (char *) malloc (p_buf
- buf
+ 2);
465 for (p_vec
= vec
, p_buf
= new_buf
; *p_vec
; p_vec
++)
469 for (p_tmp
= *p_vec
; *p_buf
++ = *p_tmp
++;)
474 flush_buffer (the_buffer
);
481 /* p is a directory. Add all the files in P to the namelist. If any of the
482 files is a directory, recurse on the subdirectory. . . */
484 add_dir_name (p
, device
)
499 /* char **vec,**p_vec;*/
500 /* int n_strs,n_size;*/
506 new_buf
= get_dir_contents (p
, device
);
508 for (n
= namelist
; n
; n
= n
->next
)
510 if (!strcmp (n
->name
, p
))
512 n
->dir_contents
= new_buf
? new_buf
: "\0\0\0\0";
520 buflen
= NAMSIZ
<= len
? len
+ NAMSIZ
: NAMSIZ
;
521 namebuf
= ck_malloc (buflen
+ 1);
523 (void) strcpy (namebuf
, p
);
524 if (namebuf
[len
- 1] != '/')
526 namebuf
[len
++] = '/';
529 for (p_buf
= new_buf
; *p_buf
; p_buf
+= sublen
+ 1)
531 sublen
= strlen (p_buf
);
534 if (len
+ sublen
>= buflen
)
537 namebuf
= ck_realloc (namebuf
, buflen
+ 1);
539 (void) strcpy (namebuf
+ len
, p_buf
+ 1);
541 add_dir_name (namebuf
, device
);
548 /* Returns non-zero if p is . or .. This could be a macro for speed. */
553 return (p
[0] == '.' && (p
[1] == '\0' || (p
[1] == '.' && p
[2] == '\0')));
562 gnu_restore (skipcrud
)
566 /* int current_dir_length; */
569 /* int archive_dir_length; */
575 extern struct stat hstat
; /* Stat struct corresponding */
578 extern union record
*head
;
580 dirp
= opendir (skipcrud
+ current_file_name
);
584 /* The directory doesn't exist now. It'll be created.
585 In any case, we don't have to delete any files out
587 skip_file ((long) hstat
.st_size
);
591 the_buffer
= init_buffer ();
592 while (d
= readdir (dirp
))
594 if (is_dot_or_dotdot (d
->d_name
))
597 add_buffer (the_buffer
, d
->d_name
, (int) (DP_NAMELEN (d
) + 1));
600 add_buffer (the_buffer
, "", 1);
602 current_dir
= get_buffer (the_buffer
);
603 archive_dir
= (char *) malloc (hstat
.st_size
);
604 if (archive_dir
== 0)
606 msg ("Can't allocate %d bytes for restore", hstat
.st_size
);
607 skip_file ((long) hstat
.st_size
);
611 for (size
= hstat
.st_size
; size
> 0; size
-= copied
)
613 from
= findrec ()->charptr
;
616 msg ("Unexpected EOF in archive\n");
619 copied
= endofrecs ()->charptr
- from
;
622 bcopy ((PTR
) from
, (PTR
) to
, (int) copied
);
624 userec ((union record
*) (from
+ copied
- 1));
627 for (cur
= current_dir
; *cur
; cur
+= strlen (cur
) + 1)
629 for (arc
= archive_dir
; *arc
; arc
+= strlen (arc
) + 1)
632 if (!strcmp (arc
, cur
))
637 p
= new_name (skipcrud
+ current_file_name
, cur
);
638 if (f_confirm
&& !confirm ("delete", p
))
644 fprintf (msg_file
, "%s: deleting %s\n", tar
, p
);
645 if (recursively_delete (p
))
647 msg ("%s: Error while deleting %s\n", tar
, p
);
653 flush_buffer (the_buffer
);
658 recursively_delete (path
)
668 if (lstat (path
, &sbuf
) < 0)
670 if (S_ISDIR (sbuf
.st_mode
))
673 /* path_len=strlen(path); */
674 dirp
= opendir (path
);
677 while (dp
= readdir (dirp
))
679 if (is_dot_or_dotdot (dp
->d_name
))
681 path_buf
= new_name (path
, dp
->d_name
);
682 if (recursively_delete (path_buf
))
692 if (rmdir (path
) < 0)
696 if (unlink (path
) < 0)
This page took 0.061762 seconds and 5 git commands to generate.