]>
Dogcows Code - chaz/tar/blob - src/gnu.c
1 /* GNU dump extensions to tar.
2 Copyright (C) 1988, 1992, 1993 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>
37 extern time_t new_time
;
38 extern FILE *msg_file
;
42 extern PTR
ck_malloc ();
43 extern PTR
ck_realloc ();
45 extern PTR
init_buffer ();
46 extern char *get_buffer ();
47 int is_dot_or_dotdot ();
48 extern void add_buffer ();
49 extern void flush_buffer ();
51 int recursively_delete ();
53 char *un_quote_string ();
55 extern char *new_name ();
57 static void add_dir_name ();
68 static struct dirname
*dir_list
;
69 static time_t this_time
;
72 add_dir (name
, dev
, ino
, text
)
80 dp
= (struct dirname
*) ck_malloc (sizeof (struct dirname
));
87 dp
->name
= ck_malloc (strlen (name
) + 1);
88 strcpy (dp
->name
, name
);
101 static char *path
= 0;
104 path
= ck_malloc (PATH_MAX
);
106 if (gnu_dumpfile
[0] != '/')
108 #if defined(__MSDOS__) || defined(HAVE_GETCWD) || defined(_POSIX_VERSION)
109 if (!getcwd (path
, PATH_MAX
))
111 msg ("Couldn't get current directory.");
119 msg ("Couldn't get current directory: %s", path
);
123 /* If this doesn't fit, we're in serious trouble */
125 strcat (path
, gnu_dumpfile
);
128 fp
= fopen (gnu_dumpfile
, "r");
129 if (fp
== 0 && errno
!= ENOENT
)
131 msg_perror ("Can't open %s", gnu_dumpfile
);
136 fgets (buf
, sizeof (buf
), fp
);
140 new_time
= atol (buf
);
142 while (fgets (buf
, sizeof (buf
), fp
))
144 strp
= &buf
[strlen (buf
)];
145 if (strp
[-1] == '\n')
149 while (isdigit (*strp
))
152 while (isspace (*strp
))
154 while (isdigit (*strp
))
157 add_dir (un_quote_string (strp
), dev
, ino
, (char *) 0);
168 extern char *quote_copy_string ();
170 fp
= fopen (gnu_dumpfile
, "w");
173 msg_perror ("Can't write to %s", gnu_dumpfile
);
176 fprintf (fp
, "%lu\n", this_time
);
177 for (dp
= dir_list
; dp
; dp
= dp
->next
)
181 str
= quote_copy_string (dp
->name
);
184 fprintf (fp
, "%u %u %s\n", dp
->dev
, dp
->ino
, str
);
188 fprintf (fp
, "%u %u %s\n", dp
->dev
, dp
->ino
, dp
->name
);
199 for (dp
= dir_list
; dp
; dp
= dp
->next
)
201 if (!strcmp (dp
->name
, name
))
208 /* Collect all the names from argv[] (or whatever), then expand them into
209 a directory tree, and put all the directories at the beginning. */
211 collect_and_sort_names ()
213 struct name
*n
, *n_next
;
225 for (n
= namelist
; n
; n
= n_next
)
228 if (n
->found
|| n
->dir_contents
)
230 if (n
->regexp
) /* FIXME just skip regexps for now */
233 if (chdir (n
->change_dir
) < 0)
235 msg_perror ("can't chdir to %s", n
->change_dir
);
240 if (statx (n
->name
, &statbuf
, STATSIZE
, STX_HIDDEN
| STX_LINK
))
242 if (lstat (n
->name
, &statbuf
) < 0)
245 msg_perror ("can't stat %s", n
->name
);
248 if (S_ISDIR (statbuf
.st_mode
))
251 add_dir_name (n
->name
, statbuf
.st_dev
);
256 for (n
= namelist
; n
; n
= n
->next
)
258 namelist
= (struct name
*) merge_sort ((PTR
) namelist
, num_names
, (char *) (&(namelist
->next
)) - (char *) namelist
, name_cmp
);
260 for (n
= namelist
; n
; n
= n
->next
)
270 struct name
*n1
, *n2
;
275 return strcmp (n1
->name
, n2
->name
);
282 return strcmp (n1
->name
, n2
->name
);
292 frst
= (*(char **) p1
) + 1;
293 scnd
= (*(char **) p2
) + 1;
295 return strcmp (frst
, scnd
);
299 get_dir_contents (p
, device
)
304 register struct dirent
*d
;
320 bufsiz
= strlen (p
) + NAMSIZ
;
321 namebuf
= ck_malloc (bufsiz
+ 2);
325 msg_perror ("can't open directory %s", p
);
327 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
, "/");
340 len
= strlen (namebuf
);
342 the_buffer
= init_buffer ();
343 while (d
= readdir (dirp
))
348 if (is_dot_or_dotdot (d
->d_name
))
350 if (NLENGTH (d
) + len
>= bufsiz
)
353 namebuf
= ck_realloc (namebuf
, bufsiz
+ 2);
355 (void) strcpy (namebuf
+ len
, d
->d_name
);
357 if (0 != f_follow_links
?
358 statx (namebuf
, &hs
, STATSIZE
, STX_HIDDEN
) :
359 statx (namebuf
, &hs
, STATSIZE
, STX_HIDDEN
| STX_LINK
))
361 if (0 != f_follow_links
? stat (namebuf
, &hs
) : lstat (namebuf
, &hs
))
364 msg_perror ("can't stat %s", namebuf
);
367 if ((f_local_filesys
&& device
!= hs
.st_dev
)
368 || (f_exclude
&& check_exclude (namebuf
)))
369 add_buffer (the_buffer
, "N", 1);
371 else if (S_ISHIDDEN (hs
.st_mode
))
373 add_buffer (the_buffer
, "D", 1);
374 strcat (d
->d_name
, "A");
378 else if (S_ISDIR (hs
.st_mode
))
380 if (dp
= get_dir (namebuf
))
382 if (dp
->dev
!= hs
.st_dev
383 || dp
->ino
!= hs
.st_ino
)
386 msg ("directory %s has been renamed.", namebuf
);
396 msg ("Directory %s is new", namebuf
);
397 add_dir (namebuf
, hs
.st_dev
, hs
.st_ino
, "");
398 dp
= get_dir (namebuf
);
404 add_buffer (the_buffer
, "D", 1);
406 else if (!all_children
408 && new_time
> hs
.st_mtime
410 || new_time
> hs
.st_ctime
))
411 add_buffer (the_buffer
, "N", 1);
413 add_buffer (the_buffer
, "Y", 1);
414 add_buffer (the_buffer
, d
->d_name
, (int) (NLENGTH (d
) + 1));
416 add_buffer (the_buffer
, "\000\000", 2);
419 /* Well, we've read in the contents of the dir, now sort them */
420 buf
= get_buffer (the_buffer
);
423 flush_buffer (the_buffer
);
429 for (p_buf
= buf
; *p_buf
;)
433 tmp
= strlen (p_buf
) + 1;
437 vec
= (char **) ck_malloc (sizeof (char *) * (n_strs
+ 1));
438 for (p_vec
= vec
, p_buf
= buf
; *p_buf
; p_buf
+= strlen (p_buf
) + 1)
441 qsort ((PTR
) vec
, n_strs
, sizeof (char *), dirent_cmp
);
442 new_buf
= (char *) ck_malloc (p_buf
- buf
+ 2);
443 for (p_vec
= vec
, p_buf
= new_buf
; *p_vec
; p_vec
++)
447 for (p_tmp
= *p_vec
; *p_buf
++ = *p_tmp
++;)
452 flush_buffer (the_buffer
);
459 /* p is a directory. Add all the files in P to the namelist. If any of the
460 files is a directory, recurse on the subdirectory. . . */
462 add_dir_name (p
, device
)
477 /* char **vec,**p_vec;*/
478 /* int n_strs,n_size;*/
484 new_buf
= get_dir_contents (p
, device
);
486 for (n
= namelist
; n
; n
= n
->next
)
488 if (!strcmp (n
->name
, p
))
490 n
->dir_contents
= new_buf
? new_buf
: "\0\0\0\0";
498 buflen
= NAMSIZ
<= len
? len
+ NAMSIZ
: NAMSIZ
;
499 namebuf
= ck_malloc (buflen
+ 1);
501 (void) strcpy (namebuf
, p
);
502 if (namebuf
[len
- 1] != '/')
504 namebuf
[len
++] = '/';
507 for (p_buf
= new_buf
; *p_buf
; p_buf
+= sublen
+ 1)
509 sublen
= strlen (p_buf
);
512 if (len
+ sublen
>= buflen
)
515 namebuf
= ck_realloc (namebuf
, buflen
+ 1);
517 (void) strcpy (namebuf
+ len
, p_buf
+ 1);
519 add_dir_name (namebuf
, device
);
526 /* Returns non-zero if p is . or .. This could be a macro for speed. */
531 return (p
[0] == '.' && (p
[1] == '\0' || (p
[1] == '.' && p
[2] == '\0')));
540 gnu_restore (skipcrud
)
544 /* int current_dir_length; */
547 /* int archive_dir_length; */
553 extern struct stat hstat
; /* Stat struct corresponding */
556 extern union record
*head
;
558 dirp
= opendir (skipcrud
+ current_file_name
);
562 /* The directory doesn't exist now. It'll be created.
563 In any case, we don't have to delete any files out
565 skip_file ((long) hstat
.st_size
);
569 the_buffer
= init_buffer ();
570 while (d
= readdir (dirp
))
572 if (is_dot_or_dotdot (d
->d_name
))
575 add_buffer (the_buffer
, d
->d_name
, (int) (NLENGTH (d
) + 1));
578 add_buffer (the_buffer
, "", 1);
580 current_dir
= get_buffer (the_buffer
);
581 archive_dir
= (char *) ck_malloc (hstat
.st_size
);
582 if (archive_dir
== 0)
584 msg ("Can't allocate %d bytes for restore", hstat
.st_size
);
585 skip_file ((long) hstat
.st_size
);
589 for (size
= hstat
.st_size
; size
> 0; size
-= copied
)
591 from
= findrec ()->charptr
;
594 msg ("Unexpected EOF in archive\n");
597 copied
= endofrecs ()->charptr
- from
;
600 bcopy ((PTR
) from
, (PTR
) to
, (int) copied
);
602 userec ((union record
*) (from
+ copied
- 1));
605 for (cur
= current_dir
; *cur
; cur
+= strlen (cur
) + 1)
607 for (arc
= archive_dir
; *arc
; arc
+= strlen (arc
) + 1)
610 if (!strcmp (arc
, cur
))
615 p
= new_name (skipcrud
+ current_file_name
, cur
);
616 if (f_confirm
&& !confirm ("delete", p
))
622 fprintf (msg_file
, "%s: deleting %s\n", tar
, p
);
623 if (recursively_delete (p
))
625 msg ("%s: Error while deleting %s\n", tar
, p
);
631 flush_buffer (the_buffer
);
636 recursively_delete (path
)
646 if (lstat (path
, &sbuf
) < 0)
648 if (S_ISDIR (sbuf
.st_mode
))
651 /* path_len=strlen(path); */
652 dirp
= opendir (path
);
655 while (dp
= readdir (dirp
))
657 if (is_dot_or_dotdot (dp
->d_name
))
659 path_buf
= new_name (path
, dp
->d_name
);
660 if (recursively_delete (path_buf
))
670 if (rmdir (path
) < 0)
674 if (unlink (path
) < 0)
This page took 0.065793 seconds and 4 git commands to generate.