]> Dogcows Code - chaz/tar/blob - src/misc.c
Fix backup handling and restoring file modes of existing directories
[chaz/tar] / src / misc.c
1 /* Miscellaneous functions, not really specific to GNU tar.
2
3 Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
4 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14 Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19
20 #include <system.h>
21 #include <rmt.h>
22 #include "common.h"
23 #include <quotearg.h>
24 #include <save-cwd.h>
25 #include <xgetcwd.h>
26 #include <unlinkdir.h>
27 #include <utimens.h>
28
29 #if HAVE_STROPTS_H
30 # include <stropts.h>
31 #endif
32 #if HAVE_SYS_FILIO_H
33 # include <sys/filio.h>
34 #endif
35
36 \f
37 /* Handling strings. */
38
39 /* Assign STRING to a copy of VALUE if not zero, or to zero. If
40 STRING was nonzero, it is freed first. */
41 void
42 assign_string (char **string, const char *value)
43 {
44 if (*string)
45 free (*string);
46 *string = value ? xstrdup (value) : 0;
47 }
48
49 /* Allocate a copy of the string quoted as in C, and returns that. If
50 the string does not have to be quoted, it returns a null pointer.
51 The allocated copy should normally be freed with free() after the
52 caller is done with it.
53
54 This is used in one context only: generating the directory file in
55 incremental dumps. The quoted string is not intended for human
56 consumption; it is intended only for unquote_string. The quoting
57 is locale-independent, so that users needn't worry about locale
58 when reading directory files. This means that we can't use
59 quotearg, as quotearg is locale-dependent and is meant for human
60 consumption. */
61 char *
62 quote_copy_string (const char *string)
63 {
64 const char *source = string;
65 char *destination = 0;
66 char *buffer = 0;
67 int copying = 0;
68
69 while (*source)
70 {
71 int character = *source++;
72
73 switch (character)
74 {
75 case '\n': case '\\':
76 if (!copying)
77 {
78 size_t length = (source - string) - 1;
79
80 copying = 1;
81 buffer = xmalloc (length + 2 + 2 * strlen (source) + 1);
82 memcpy (buffer, string, length);
83 destination = buffer + length;
84 }
85 *destination++ = '\\';
86 *destination++ = character == '\\' ? '\\' : 'n';
87 break;
88
89 default:
90 if (copying)
91 *destination++ = character;
92 break;
93 }
94 }
95 if (copying)
96 {
97 *destination = '\0';
98 return buffer;
99 }
100 return 0;
101 }
102
103 /* Takes a quoted C string (like those produced by quote_copy_string)
104 and turns it back into the un-quoted original. This is done in
105 place. Returns 0 only if the string was not properly quoted, but
106 completes the unquoting anyway.
107
108 This is used for reading the saved directory file in incremental
109 dumps. It is used for decoding old `N' records (demangling names).
110 But also, it is used for decoding file arguments, would they come
111 from the shell or a -T file, and for decoding the --exclude
112 argument. */
113 int
114 unquote_string (char *string)
115 {
116 int result = 1;
117 char *source = string;
118 char *destination = string;
119
120 /* Escape sequences other than \\ and \n are no longer generated by
121 quote_copy_string, but accept them for backwards compatibility,
122 and also because unquote_string is used for purposes other than
123 parsing the output of quote_copy_string. */
124
125 while (*source)
126 if (*source == '\\')
127 switch (*++source)
128 {
129 case '\\':
130 *destination++ = '\\';
131 source++;
132 break;
133
134 case 'a':
135 *destination++ = '\a';
136 source++;
137 break;
138
139 case 'b':
140 *destination++ = '\b';
141 source++;
142 break;
143
144 case 'f':
145 *destination++ = '\f';
146 source++;
147 break;
148
149 case 'n':
150 *destination++ = '\n';
151 source++;
152 break;
153
154 case 'r':
155 *destination++ = '\r';
156 source++;
157 break;
158
159 case 't':
160 *destination++ = '\t';
161 source++;
162 break;
163
164 case 'v':
165 *destination++ = '\v';
166 source++;
167 break;
168
169 case '?':
170 *destination++ = 0177;
171 source++;
172 break;
173
174 case '0':
175 case '1':
176 case '2':
177 case '3':
178 case '4':
179 case '5':
180 case '6':
181 case '7':
182 {
183 int value = *source++ - '0';
184
185 if (*source < '0' || *source > '7')
186 {
187 *destination++ = value;
188 break;
189 }
190 value = value * 8 + *source++ - '0';
191 if (*source < '0' || *source > '7')
192 {
193 *destination++ = value;
194 break;
195 }
196 value = value * 8 + *source++ - '0';
197 *destination++ = value;
198 break;
199 }
200
201 default:
202 result = 0;
203 *destination++ = '\\';
204 if (*source)
205 *destination++ = *source++;
206 break;
207 }
208 else if (source != destination)
209 *destination++ = *source++;
210 else
211 source++, destination++;
212
213 if (source != destination)
214 *destination = '\0';
215 return result;
216 }
217 \f
218 /* Handling numbers. */
219
220 /* Output fraction and trailing digits appropriate for a nanoseconds
221 count equal to NS, but don't output unnecessary '.' or trailing
222 zeros. */
223
224 void
225 code_ns_fraction (int ns, char *p)
226 {
227 if (ns == 0)
228 *p = '\0';
229 else
230 {
231 int i = 9;
232 *p++ = '.';
233
234 while (ns % 10 == 0)
235 {
236 ns /= 10;
237 i--;
238 }
239
240 p[i] = '\0';
241
242 for (;;)
243 {
244 p[--i] = '0' + ns % 10;
245 if (i == 0)
246 break;
247 ns /= 10;
248 }
249 }
250 }
251
252 char const *
253 code_timespec (struct timespec t, char sbuf[TIMESPEC_STRSIZE_BOUND])
254 {
255 time_t s = t.tv_sec;
256 int ns = t.tv_nsec;
257 char *np;
258 bool negative = s < 0;
259
260 if (negative && ns != 0)
261 {
262 s++;
263 ns = BILLION - ns;
264 }
265
266 np = umaxtostr (negative ? - (uintmax_t) s : (uintmax_t) s, sbuf + 1);
267 if (negative)
268 *--np = '-';
269 code_ns_fraction (ns, sbuf + UINTMAX_STRSIZE_BOUND);
270 return np;
271 }
272 \f
273 /* File handling. */
274
275 /* Saved names in case backup needs to be undone. */
276 static char *before_backup_name;
277 static char *after_backup_name;
278
279 /* Return 1 if FILE_NAME is obviously "." or "/". */
280 static bool
281 must_be_dot_or_slash (char const *file_name)
282 {
283 file_name += FILE_SYSTEM_PREFIX_LEN (file_name);
284
285 if (ISSLASH (file_name[0]))
286 {
287 for (;;)
288 if (ISSLASH (file_name[1]))
289 file_name++;
290 else if (file_name[1] == '.'
291 && ISSLASH (file_name[2 + (file_name[2] == '.')]))
292 file_name += 2 + (file_name[2] == '.');
293 else
294 return ! file_name[1];
295 }
296 else
297 {
298 while (file_name[0] == '.' && ISSLASH (file_name[1]))
299 {
300 file_name += 2;
301 while (ISSLASH (*file_name))
302 file_name++;
303 }
304
305 return ! file_name[0] || (file_name[0] == '.' && ! file_name[1]);
306 }
307 }
308
309 /* Some implementations of rmdir let you remove '.' or '/'.
310 Report an error with errno set to zero for obvious cases of this;
311 otherwise call rmdir. */
312 static int
313 safer_rmdir (const char *file_name)
314 {
315 if (must_be_dot_or_slash (file_name))
316 {
317 errno = 0;
318 return -1;
319 }
320
321 return rmdir (file_name);
322 }
323
324 /* Remove FILE_NAME, returning 1 on success. If FILE_NAME is a directory,
325 then if OPTION is RECURSIVE_REMOVE_OPTION is set remove FILE_NAME
326 recursively; otherwise, remove it only if it is empty. If FILE_NAME is
327 a directory that cannot be removed (e.g., because it is nonempty)
328 and if OPTION is WANT_DIRECTORY_REMOVE_OPTION, then return -1.
329 Return 0 on error, with errno set; if FILE_NAME is obviously the working
330 directory return zero with errno set to zero. */
331 int
332 remove_any_file (const char *file_name, enum remove_option option)
333 {
334 /* Try unlink first if we cannot unlink directories, as this saves
335 us a system call in the common case where we're removing a
336 non-directory. */
337 bool try_unlink_first = cannot_unlink_dir ();
338
339 if (try_unlink_first)
340 {
341 if (unlink (file_name) == 0)
342 return 1;
343
344 /* POSIX 1003.1-2001 requires EPERM when attempting to unlink a
345 directory without appropriate privileges, but many Linux
346 kernels return the more-sensible EISDIR. */
347 if (errno != EPERM && errno != EISDIR)
348 return 0;
349 }
350
351 if (safer_rmdir (file_name) == 0)
352 return 1;
353
354 switch (errno)
355 {
356 case ENOTDIR:
357 return !try_unlink_first && unlink (file_name) == 0;
358
359 case 0:
360 case EEXIST:
361 #if defined ENOTEMPTY && ENOTEMPTY != EEXIST
362 case ENOTEMPTY:
363 #endif
364 switch (option)
365 {
366 case ORDINARY_REMOVE_OPTION:
367 break;
368
369 case WANT_DIRECTORY_REMOVE_OPTION:
370 return -1;
371
372 case RECURSIVE_REMOVE_OPTION:
373 {
374 char *directory = savedir (file_name);
375 char const *entry;
376 size_t entrylen;
377
378 if (! directory)
379 return 0;
380
381 for (entry = directory;
382 (entrylen = strlen (entry)) != 0;
383 entry += entrylen + 1)
384 {
385 char *file_name_buffer = new_name (file_name, entry);
386 int r = remove_any_file (file_name_buffer,
387 RECURSIVE_REMOVE_OPTION);
388 int e = errno;
389 free (file_name_buffer);
390
391 if (! r)
392 {
393 free (directory);
394 errno = e;
395 return 0;
396 }
397 }
398
399 free (directory);
400 return safer_rmdir (file_name) == 0;
401 }
402 }
403 break;
404 }
405
406 return 0;
407 }
408
409 /* Check if FILE_NAME already exists and make a backup of it right now.
410 Return success (nonzero) only if the backup is either unneeded, or
411 successful. For now, directories are considered to never need
412 backup. If THIS_IS_THE_ARCHIVE is nonzero, this is the archive and
413 so, we do not have to backup block or character devices, nor remote
414 entities. */
415 bool
416 maybe_backup_file (const char *file_name, bool this_is_the_archive)
417 {
418 struct stat file_stat;
419
420 assign_string (&before_backup_name, file_name);
421
422 /* A run situation may exist between Emacs or other GNU programs trying to
423 make a backup for the same file simultaneously. If theoretically
424 possible, real problems are unlikely. Doing any better would require a
425 convention, GNU-wide, for all programs doing backups. */
426
427 assign_string (&after_backup_name, 0);
428
429 /* Check if we really need to backup the file. */
430
431 if (this_is_the_archive && _remdev (file_name))
432 return true;
433
434 if (stat (file_name, &file_stat))
435 {
436 if (errno == ENOENT)
437 return true;
438
439 stat_error (file_name);
440 return false;
441 }
442
443 if (S_ISDIR (file_stat.st_mode))
444 return true;
445
446 if (this_is_the_archive
447 && (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
448 return true;
449
450 after_backup_name = find_backup_file_name (file_name, backup_type);
451 if (! after_backup_name)
452 xalloc_die ();
453
454 if (rename (before_backup_name, after_backup_name) == 0)
455 {
456 if (verbose_option)
457 fprintf (stdlis, _("Renaming %s to %s\n"),
458 quote_n (0, before_backup_name),
459 quote_n (1, after_backup_name));
460 return true;
461 }
462 else
463 {
464 /* The backup operation failed. */
465 int e = errno;
466 ERROR ((0, e, _("%s: Cannot rename to %s"),
467 quotearg_colon (before_backup_name),
468 quote_n (1, after_backup_name)));
469 assign_string (&after_backup_name, 0);
470 return false;
471 }
472 }
473
474 /* Try to restore the recently backed up file to its original name.
475 This is usually only needed after a failed extraction. */
476 void
477 undo_last_backup (void)
478 {
479 if (after_backup_name)
480 {
481 if (rename (after_backup_name, before_backup_name) != 0)
482 {
483 int e = errno;
484 ERROR ((0, e, _("%s: Cannot rename to %s"),
485 quotearg_colon (after_backup_name),
486 quote_n (1, before_backup_name)));
487 }
488 if (verbose_option)
489 fprintf (stdlis, _("Renaming %s back to %s\n"),
490 quote_n (0, after_backup_name),
491 quote_n (1, before_backup_name));
492 assign_string (&after_backup_name, 0);
493 }
494 }
495
496 /* Depending on DEREF, apply either stat or lstat to (NAME, BUF). */
497 int
498 deref_stat (bool deref, char const *name, struct stat *buf)
499 {
500 return deref ? stat (name, buf) : lstat (name, buf);
501 }
502
503 /* Set FD's (i.e., FILE's) access time to TIMESPEC[0]. If that's not
504 possible to do by itself, set its access and data modification
505 times to TIMESPEC[0] and TIMESPEC[1], respectively. */
506 int
507 set_file_atime (int fd, char const *file, struct timespec const timespec[2])
508 {
509 #ifdef _FIOSATIME
510 if (0 <= fd)
511 {
512 struct timeval timeval;
513 timeval.tv_sec = timespec[0].tv_sec;
514 timeval.tv_usec = timespec[0].tv_nsec / 1000;
515 if (ioctl (fd, _FIOSATIME, &timeval) == 0)
516 return 0;
517 }
518 #endif
519
520 return gl_futimens (fd, file, timespec);
521 }
522
523 /* A description of a working directory. */
524 struct wd
525 {
526 char const *name;
527 int saved;
528 struct saved_cwd saved_cwd;
529 };
530
531 /* A vector of chdir targets. wd[0] is the initial working directory. */
532 static struct wd *wd;
533
534 /* The number of working directories in the vector. */
535 static size_t wds;
536
537 /* The allocated size of the vector. */
538 static size_t wd_alloc;
539
540 /* DIR is the operand of a -C option; add it to vector of chdir targets,
541 and return the index of its location. */
542 int
543 chdir_arg (char const *dir)
544 {
545 if (wds == wd_alloc)
546 {
547 if (wd_alloc == 0)
548 {
549 wd_alloc = 2;
550 wd = xmalloc (sizeof *wd * wd_alloc);
551 }
552 else
553 wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
554
555 if (! wds)
556 {
557 wd[wds].name = ".";
558 wd[wds].saved = 0;
559 wds++;
560 }
561 }
562
563 /* Optimize the common special case of the working directory,
564 or the working directory as a prefix. */
565 if (dir[0])
566 {
567 while (dir[0] == '.' && ISSLASH (dir[1]))
568 for (dir += 2; ISSLASH (*dir); dir++)
569 continue;
570 if (! dir[dir[0] == '.'])
571 return wds - 1;
572 }
573
574 wd[wds].name = dir;
575 wd[wds].saved = 0;
576 return wds++;
577 }
578
579 /* Change to directory I. If I is 0, change to the initial working
580 directory; otherwise, I must be a value returned by chdir_arg. */
581 void
582 chdir_do (int i)
583 {
584 static int previous;
585
586 if (previous != i)
587 {
588 struct wd *prev = &wd[previous];
589 struct wd *curr = &wd[i];
590
591 if (! prev->saved)
592 {
593 int err = 0;
594 prev->saved = 1;
595 if (save_cwd (&prev->saved_cwd) != 0)
596 err = errno;
597 else if (0 <= prev->saved_cwd.desc)
598 {
599 /* Make sure we still have at least one descriptor available. */
600 int fd1 = prev->saved_cwd.desc;
601 int fd2 = dup (fd1);
602 if (0 <= fd2)
603 close (fd2);
604 else if (errno == EMFILE)
605 {
606 /* Force restore_cwd to use chdir_long. */
607 close (fd1);
608 prev->saved_cwd.desc = -1;
609 prev->saved_cwd.name = xgetcwd ();
610 }
611 else
612 err = errno;
613 }
614
615 if (err)
616 FATAL_ERROR ((0, err, _("Cannot save working directory")));
617 }
618
619 if (curr->saved)
620 {
621 if (restore_cwd (&curr->saved_cwd))
622 FATAL_ERROR ((0, 0, _("Cannot change working directory")));
623 }
624 else
625 {
626 if (i && ! ISSLASH (curr->name[0]))
627 chdir_do (i - 1);
628 if (chdir (curr->name) != 0)
629 chdir_fatal (curr->name);
630 }
631
632 previous = i;
633 }
634 }
635 \f
636 void
637 close_diag (char const *name)
638 {
639 if (ignore_failed_read_option)
640 close_warn (name);
641 else
642 close_error (name);
643 }
644
645 void
646 open_diag (char const *name)
647 {
648 if (ignore_failed_read_option)
649 open_warn (name);
650 else
651 open_error (name);
652 }
653
654 void
655 read_diag_details (char const *name, off_t offset, size_t size)
656 {
657 if (ignore_failed_read_option)
658 read_warn_details (name, offset, size);
659 else
660 read_error_details (name, offset, size);
661 }
662
663 void
664 readlink_diag (char const *name)
665 {
666 if (ignore_failed_read_option)
667 readlink_warn (name);
668 else
669 readlink_error (name);
670 }
671
672 void
673 savedir_diag (char const *name)
674 {
675 if (ignore_failed_read_option)
676 savedir_warn (name);
677 else
678 savedir_error (name);
679 }
680
681 void
682 seek_diag_details (char const *name, off_t offset)
683 {
684 if (ignore_failed_read_option)
685 seek_warn_details (name, offset);
686 else
687 seek_error_details (name, offset);
688 }
689
690 void
691 stat_diag (char const *name)
692 {
693 if (ignore_failed_read_option)
694 stat_warn (name);
695 else
696 stat_error (name);
697 }
698
699 void
700 write_fatal_details (char const *name, ssize_t status, size_t size)
701 {
702 write_error_details (name, status, size);
703 fatal_exit ();
704 }
705
706 /* Fork, aborting if unsuccessful. */
707 pid_t
708 xfork (void)
709 {
710 pid_t p = fork ();
711 if (p == (pid_t) -1)
712 call_arg_fatal ("fork", _("child process"));
713 return p;
714 }
715
716 /* Create a pipe, aborting if unsuccessful. */
717 void
718 xpipe (int fd[2])
719 {
720 if (pipe (fd) < 0)
721 call_arg_fatal ("pipe", _("interprocess channel"));
722 }
723
724 /* Return PTR, aligned upward to the next multiple of ALIGNMENT.
725 ALIGNMENT must be nonzero. The caller must arrange for ((char *)
726 PTR) through ((char *) PTR + ALIGNMENT - 1) to be addressable
727 locations. */
728
729 static inline void *
730 ptr_align (void *ptr, size_t alignment)
731 {
732 char *p0 = ptr;
733 char *p1 = p0 + alignment - 1;
734 return p1 - (size_t) p1 % alignment;
735 }
736
737 /* Return the address of a page-aligned buffer of at least SIZE bytes.
738 The caller should free *PTR when done with the buffer. */
739
740 void *
741 page_aligned_alloc (void **ptr, size_t size)
742 {
743 size_t alignment = getpagesize ();
744 size_t size1 = size + alignment;
745 if (size1 < size)
746 xalloc_die ();
747 *ptr = xmalloc (size1);
748 return ptr_align (*ptr, alignment);
749 }
This page took 0.061027 seconds and 5 git commands to generate.