source: vendor/tar/1.16.1/src/misc.c

Last change on this file was 3342, checked in by bird, 19 years ago

tar 1.16.1

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