source: trunk/essentials/app-arch/tar/src/misc.c

Last change on this file was 3357, checked in by bird, 18 years ago

Workaround for kLIBC buf #163.

File size: 17.4 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#if defined __KLIBC__ /* Workaround for kLIBC bug #163. */
362# if __KLIBC_VERSION__ <= 0x60002
363 case ENOENT:
364 {
365 struct stat s;
366 if ( lstat (file_name, &s) != 0
367 || S_ISDIR (s.st_mode) /* paranoia */)
368 {
369 errno = ENOENT;
370 break;
371 }
372 errno = ENOTDIR;
373 /* fall thru */
374 }
375# endif
376#endif
377 case ENOTDIR:
378 return !try_unlink_first && unlink (file_name) == 0;
379
380 case 0:
381 case EEXIST:
382#if defined ENOTEMPTY && ENOTEMPTY != EEXIST
383 case ENOTEMPTY:
384#endif
385 switch (option)
386 {
387 case ORDINARY_REMOVE_OPTION:
388 break;
389
390 case WANT_DIRECTORY_REMOVE_OPTION:
391 return -1;
392
393 case RECURSIVE_REMOVE_OPTION:
394 {
395 char *directory = savedir (file_name);
396 char const *entry;
397 size_t entrylen;
398
399 if (! directory)
400 return 0;
401
402 for (entry = directory;
403 (entrylen = strlen (entry)) != 0;
404 entry += entrylen + 1)
405 {
406 char *file_name_buffer = new_name (file_name, entry);
407 int r = remove_any_file (file_name_buffer,
408 RECURSIVE_REMOVE_OPTION);
409 int e = errno;
410 free (file_name_buffer);
411
412 if (! r)
413 {
414 free (directory);
415 errno = e;
416 return 0;
417 }
418 }
419
420 free (directory);
421 return safer_rmdir (file_name) == 0;
422 }
423 }
424 break;
425 }
426
427 return 0;
428}
429
430/* Check if FILE_NAME already exists and make a backup of it right now.
431 Return success (nonzero) only if the backup is either unneeded, or
432 successful. For now, directories are considered to never need
433 backup. If THIS_IS_THE_ARCHIVE is nonzero, this is the archive and
434 so, we do not have to backup block or character devices, nor remote
435 entities. */
436bool
437maybe_backup_file (const char *file_name, bool this_is_the_archive)
438{
439 struct stat file_stat;
440
441 /* Check if we really need to backup the file. */
442
443 if (this_is_the_archive && _remdev (file_name))
444 return true;
445
446 if (stat (file_name, &file_stat))
447 {
448 if (errno == ENOENT)
449 return true;
450
451 stat_error (file_name);
452 return false;
453 }
454
455 if (S_ISDIR (file_stat.st_mode))
456 return true;
457
458 if (this_is_the_archive
459 && (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
460 return true;
461
462 assign_string (&before_backup_name, file_name);
463
464 /* A run situation may exist between Emacs or other GNU programs trying to
465 make a backup for the same file simultaneously. If theoretically
466 possible, real problems are unlikely. Doing any better would require a
467 convention, GNU-wide, for all programs doing backups. */
468
469 assign_string (&after_backup_name, 0);
470 after_backup_name = find_backup_file_name (file_name, backup_type);
471 if (! after_backup_name)
472 xalloc_die ();
473
474 if (rename (before_backup_name, after_backup_name) == 0)
475 {
476 if (verbose_option)
477 fprintf (stdlis, _("Renaming %s to %s\n"),
478 quote_n (0, before_backup_name),
479 quote_n (1, after_backup_name));
480 return true;
481 }
482 else
483 {
484 /* The backup operation failed. */
485 int e = errno;
486 ERROR ((0, e, _("%s: Cannot rename to %s"),
487 quotearg_colon (before_backup_name),
488 quote_n (1, after_backup_name)));
489 assign_string (&after_backup_name, 0);
490 return false;
491 }
492}
493
494/* Try to restore the recently backed up file to its original name.
495 This is usually only needed after a failed extraction. */
496void
497undo_last_backup (void)
498{
499 if (after_backup_name)
500 {
501 if (rename (after_backup_name, before_backup_name) != 0)
502 {
503 int e = errno;
504 ERROR ((0, e, _("%s: Cannot rename to %s"),
505 quotearg_colon (after_backup_name),
506 quote_n (1, before_backup_name)));
507 }
508 if (verbose_option)
509 fprintf (stdlis, _("Renaming %s back to %s\n"),
510 quote_n (0, after_backup_name),
511 quote_n (1, before_backup_name));
512 assign_string (&after_backup_name, 0);
513 }
514}
515
516/* Depending on DEREF, apply either stat or lstat to (NAME, BUF). */
517int
518deref_stat (bool deref, char const *name, struct stat *buf)
519{
520 return deref ? stat (name, buf) : lstat (name, buf);
521}
522
523/* Set FD's (i.e., FILE's) access time to TIMESPEC[0]. If that's not
524 possible to do by itself, set its access and data modification
525 times to TIMESPEC[0] and TIMESPEC[1], respectively. */
526int
527set_file_atime (int fd, char const *file, struct timespec const timespec[2])
528{
529#ifdef _FIOSATIME
530 if (0 <= fd)
531 {
532 struct timeval timeval;
533 timeval.tv_sec = timespec[0].tv_sec;
534 timeval.tv_usec = timespec[0].tv_nsec / 1000;
535 if (ioctl (fd, _FIOSATIME, &timeval) == 0)
536 return 0;
537 }
538#endif
539
540 return futimens (fd, file, timespec);
541}
542
543/* A description of a working directory. */
544struct wd
545{
546 char const *name;
547 int saved;
548 struct saved_cwd saved_cwd;
549};
550
551/* A vector of chdir targets. wd[0] is the initial working directory. */
552static struct wd *wd;
553
554/* The number of working directories in the vector. */
555static size_t wds;
556
557/* The allocated size of the vector. */
558static size_t wd_alloc;
559
560/* DIR is the operand of a -C option; add it to vector of chdir targets,
561 and return the index of its location. */
562int
563chdir_arg (char const *dir)
564{
565 if (wds == wd_alloc)
566 {
567 if (wd_alloc == 0)
568 {
569 wd_alloc = 2;
570 wd = xmalloc (sizeof *wd * wd_alloc);
571 }
572 else
573 wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
574
575 if (! wds)
576 {
577 wd[wds].name = ".";
578 wd[wds].saved = 0;
579 wds++;
580 }
581 }
582
583 /* Optimize the common special case of the working directory,
584 or the working directory as a prefix. */
585 if (dir[0])
586 {
587 while (dir[0] == '.' && ISSLASH (dir[1]))
588 for (dir += 2; ISSLASH (*dir); dir++)
589 continue;
590 if (! dir[dir[0] == '.'])
591 return wds - 1;
592 }
593
594 wd[wds].name = dir;
595 wd[wds].saved = 0;
596 return wds++;
597}
598
599/* Return maximum number of open files */
600int
601get_max_open_files ()
602{
603#if defined _SC_OPEN_MAX
604 return sysconf (_SC_OPEN_MAX);
605#elif defined RLIMIT_NOFILE
606 struct rlimit rlim;
607
608 if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
609 return rlim.rlim_max;
610#elif defined HAVE_GETDTABLESIZE
611 return getdtablesize ();
612#endif
613 return -1;
614}
615
616/* Close all descriptors, except the first three */
617void
618closeopen ()
619{
620 int i;
621
622 for (i = get_max_open_files () - 1; i > 2; i--)
623 close (i);
624}
625
626/* Change to directory I. If I is 0, change to the initial working
627 directory; otherwise, I must be a value returned by chdir_arg. */
628void
629chdir_do (int i)
630{
631 static int previous;
632 static int saved_count;
633
634 if (previous != i)
635 {
636 struct wd *prev = &wd[previous];
637 struct wd *curr = &wd[i];
638
639 if (! prev->saved)
640 {
641 prev->saved = 1;
642 saved_count++;
643 /* Make sure we still have at least one descriptor available */
644 if (saved_count >= get_max_open_files () - 4)
645 {
646 /* Force restore_cwd to use chdir_long */
647 prev->saved_cwd.desc = -1;
648 prev->saved_cwd.name = xgetcwd ();
649 }
650 else if (save_cwd (&prev->saved_cwd) != 0)
651 FATAL_ERROR ((0, 0, _("Cannot save working directory")));
652 }
653
654 if (curr->saved)
655 {
656 if (restore_cwd (&curr->saved_cwd))
657 FATAL_ERROR ((0, 0, _("Cannot change working directory")));
658 }
659 else
660 {
661 if (i && ! ISSLASH (curr->name[0]))
662 chdir_do (i - 1);
663 if (chdir (curr->name) != 0)
664 chdir_fatal (curr->name);
665 }
666
667 previous = i;
668 }
669}
670
671
672void
673close_diag (char const *name)
674{
675 if (ignore_failed_read_option)
676 close_warn (name);
677 else
678 close_error (name);
679}
680
681void
682open_diag (char const *name)
683{
684 if (ignore_failed_read_option)
685 open_warn (name);
686 else
687 open_error (name);
688}
689
690void
691read_diag_details (char const *name, off_t offset, size_t size)
692{
693 if (ignore_failed_read_option)
694 read_warn_details (name, offset, size);
695 else
696 read_error_details (name, offset, size);
697}
698
699void
700readlink_diag (char const *name)
701{
702 if (ignore_failed_read_option)
703 readlink_warn (name);
704 else
705 readlink_error (name);
706}
707
708void
709savedir_diag (char const *name)
710{
711 if (ignore_failed_read_option)
712 savedir_warn (name);
713 else
714 savedir_error (name);
715}
716
717void
718seek_diag_details (char const *name, off_t offset)
719{
720 if (ignore_failed_read_option)
721 seek_warn_details (name, offset);
722 else
723 seek_error_details (name, offset);
724}
725
726void
727stat_diag (char const *name)
728{
729 if (ignore_failed_read_option)
730 stat_warn (name);
731 else
732 stat_error (name);
733}
734
735void
736write_fatal_details (char const *name, ssize_t status, size_t size)
737{
738 write_error_details (name, status, size);
739 fatal_exit ();
740}
741
742/* Fork, aborting if unsuccessful. */
743pid_t
744xfork (void)
745{
746 pid_t p = fork ();
747 if (p == (pid_t) -1)
748 call_arg_fatal ("fork", _("child process"));
749 return p;
750}
751
752/* Create a pipe, aborting if unsuccessful. */
753void
754xpipe (int fd[2])
755{
756 if (pipe (fd) < 0)
757 call_arg_fatal ("pipe", _("interprocess channel"));
758}
759
760/* Return PTR, aligned upward to the next multiple of ALIGNMENT.
761 ALIGNMENT must be nonzero. The caller must arrange for ((char *)
762 PTR) through ((char *) PTR + ALIGNMENT - 1) to be addressable
763 locations. */
764
765static inline void *
766ptr_align (void *ptr, size_t alignment)
767{
768 char *p0 = ptr;
769 char *p1 = p0 + alignment - 1;
770 return p1 - (size_t) p1 % alignment;
771}
772
773/* Return the address of a page-aligned buffer of at least SIZE bytes.
774 The caller should free *PTR when done with the buffer. */
775
776void *
777page_aligned_alloc (void **ptr, size_t size)
778{
779 size_t alignment = getpagesize ();
780 size_t size1 = size + alignment;
781 if (size1 < size)
782 xalloc_die ();
783 *ptr = xmalloc (size1);
784 return ptr_align (*ptr, alignment);
785}
Note: See TracBrowser for help on using the repository browser.