]> git.cworth.org Git - tar/blob - src/misc.c
Imported Upstream version 1.24
[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, 2009, 2010 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 <xgetcwd.h>
25 #include <unlinkdir.h>
26 #include <utimens.h>
27
28 #ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT
29 # define DOUBLE_SLASH_IS_DISTINCT_ROOT 0
30 #endif
31
32 \f
33 /* Handling strings.  */
34
35 /* Assign STRING to a copy of VALUE if not zero, or to zero.  If
36    STRING was nonzero, it is freed first.  */
37 void
38 assign_string (char **string, const char *value)
39 {
40   if (*string)
41     free (*string);
42   *string = value ? xstrdup (value) : 0;
43 }
44
45 #if 0
46 /* This function is currently unused; perhaps it should be removed?  */
47
48 /* Allocate a copy of the string quoted as in C, and returns that.  If
49    the string does not have to be quoted, it returns a null pointer.
50    The allocated copy should normally be freed with free() after the
51    caller is done with it.
52
53    This is used in one context only: generating the directory file in
54    incremental dumps.  The quoted string is not intended for human
55    consumption; it is intended only for unquote_string.  The quoting
56    is locale-independent, so that users needn't worry about locale
57    when reading directory files.  This means that we can't use
58    quotearg, as quotearg is locale-dependent and is meant for human
59    consumption.  */
60 static char *
61 quote_copy_string (const char *string)
62 {
63   const char *source = string;
64   char *destination = 0;
65   char *buffer = 0;
66   int copying = 0;
67
68   while (*source)
69     {
70       int character = *source++;
71
72       switch (character)
73         {
74         case '\n': case '\\':
75           if (!copying)
76             {
77               size_t length = (source - string) - 1;
78
79               copying = 1;
80               buffer = xmalloc (length + 2 + 2 * strlen (source) + 1);
81               memcpy (buffer, string, length);
82               destination = buffer + length;
83             }
84           *destination++ = '\\';
85           *destination++ = character == '\\' ? '\\' : 'n';
86           break;
87
88         default:
89           if (copying)
90             *destination++ = character;
91           break;
92         }
93     }
94   if (copying)
95     {
96       *destination = '\0';
97       return buffer;
98     }
99   return 0;
100 }
101 #endif
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
218 /* Zap trailing slashes.  */
219 char *
220 zap_slashes (char *name)
221 {
222   char *q;
223
224   if (!name || *name == 0)
225     return name;
226   q = name + strlen (name) - 1;
227   while (q > name && ISSLASH (*q))
228     *q-- = '\0';
229   return name;
230 }
231
232 /* Normalize FILE_NAME by removing redundant slashes and "."
233    components, including redundant trailing slashes.  Leave ".."
234    alone, as it may be significant in the presence of symlinks and on
235    platforms where "/.." != "/".  Destructive version: modifies its
236    argument. */
237 static void
238 normalize_filename_x (char *file_name)
239 {
240   char *name = file_name + FILE_SYSTEM_PREFIX_LEN (file_name);
241   char *p;
242   char const *q;
243   char c;
244
245   /* Don't squeeze leading "//" to "/", on hosts where they're distinct.  */
246   name += (DOUBLE_SLASH_IS_DISTINCT_ROOT
247            && ISSLASH (*name) && ISSLASH (name[1]) && ! ISSLASH (name[2]));
248
249   /* Omit redundant leading "." components.  */
250   for (q = p = name; (*p = *q) == '.' && ISSLASH (q[1]); p += !*q)
251     for (q += 2; ISSLASH (*q); q++)
252       continue;
253
254   /* Copy components from Q to P, omitting redundant slashes and
255      internal "."  components.  */
256   while ((*p++ = c = *q++) != '\0')
257     if (ISSLASH (c))
258       while (ISSLASH (q[*q == '.']))
259         q += (*q == '.') + 1;
260
261   /* Omit redundant trailing "." component and slash.  */
262   if (2 < p - name)
263     {
264       p -= p[-2] == '.' && ISSLASH (p[-3]);
265       p -= 2 < p - name && ISSLASH (p[-2]);
266       p[-1] = '\0';
267     }
268 }
269
270 /* Normalize NAME by removing redundant slashes and "." components,
271    including redundant trailing slashes.  Return a normalized
272    newly-allocated copy.  */
273
274 char *
275 normalize_filename (const char *name)
276 {
277   char *copy = NULL;
278
279   if (IS_RELATIVE_FILE_NAME (name))
280     {
281       /* Set COPY to the absolute file name if possible.
282
283          FIXME: There should be no need to get the absolute file name.
284          getcwd is slow, it might fail, and it does not necessarily
285          return a canonical name even when it succeeds.  Perhaps we
286          can use dev+ino pairs instead of names?  */
287       copy = xgetcwd ();
288       if (copy)
289         {
290           size_t copylen = strlen (copy);
291           bool need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT
292                                    && copylen == 2 && ISSLASH (copy[1]));
293           copy = xrealloc (copy, copylen + need_separator + strlen (name) + 1);
294           copy[copylen] = DIRECTORY_SEPARATOR;
295           strcpy (copy + copylen + need_separator, name);
296         }
297       else
298         WARN ((0, errno, _("Cannot get working directory")));
299     }
300
301   if (! copy)
302     copy = xstrdup (name);
303   normalize_filename_x (copy);
304   return copy;
305 }
306
307 \f
308 void
309 replace_prefix (char **pname, const char *samp, size_t slen,
310                 const char *repl, size_t rlen)
311 {
312   char *name = *pname;
313   size_t nlen = strlen (name);
314   if (nlen > slen && memcmp (name, samp, slen) == 0 && ISSLASH (name[slen]))
315     {
316       if (rlen > slen)
317         {
318           name = xrealloc (name, nlen - slen + rlen + 1);
319           *pname = name;
320         }
321       memmove (name + rlen, name + slen, nlen - slen + 1);
322       memcpy (name, repl, rlen);
323     }
324 }
325
326 \f
327 /* Handling numbers.  */
328
329 /* Output fraction and trailing digits appropriate for a nanoseconds
330    count equal to NS, but don't output unnecessary '.' or trailing
331    zeros.  */
332
333 void
334 code_ns_fraction (int ns, char *p)
335 {
336   if (ns == 0)
337     *p = '\0';
338   else
339     {
340       int i = 9;
341       *p++ = '.';
342
343       while (ns % 10 == 0)
344         {
345           ns /= 10;
346           i--;
347         }
348
349       p[i] = '\0';
350
351       for (;;)
352         {
353           p[--i] = '0' + ns % 10;
354           if (i == 0)
355             break;
356           ns /= 10;
357         }
358     }
359 }
360
361 char const *
362 code_timespec (struct timespec t, char sbuf[TIMESPEC_STRSIZE_BOUND])
363 {
364   time_t s = t.tv_sec;
365   int ns = t.tv_nsec;
366   char *np;
367   bool negative = s < 0;
368
369   /* ignore invalid values of ns */
370   if (BILLION <= ns || ns < 0)
371     ns = 0;
372
373   if (negative && ns != 0)
374     {
375       s++;
376       ns = BILLION - ns;
377     }
378
379   np = umaxtostr (negative ? - (uintmax_t) s : (uintmax_t) s, sbuf + 1);
380   if (negative)
381     *--np = '-';
382   code_ns_fraction (ns, sbuf + UINTMAX_STRSIZE_BOUND);
383   return np;
384 }
385 \f
386 /* File handling.  */
387
388 /* Saved names in case backup needs to be undone.  */
389 static char *before_backup_name;
390 static char *after_backup_name;
391
392 /* Return 1 if FILE_NAME is obviously "." or "/".  */
393 bool
394 must_be_dot_or_slash (char const *file_name)
395 {
396   file_name += FILE_SYSTEM_PREFIX_LEN (file_name);
397
398   if (ISSLASH (file_name[0]))
399     {
400       for (;;)
401         if (ISSLASH (file_name[1]))
402           file_name++;
403         else if (file_name[1] == '.'
404                  && ISSLASH (file_name[2 + (file_name[2] == '.')]))
405           file_name += 2 + (file_name[2] == '.');
406         else
407           return ! file_name[1];
408     }
409   else
410     {
411       while (file_name[0] == '.' && ISSLASH (file_name[1]))
412         {
413           file_name += 2;
414           while (ISSLASH (*file_name))
415             file_name++;
416         }
417
418       return ! file_name[0] || (file_name[0] == '.' && ! file_name[1]);
419     }
420 }
421
422 /* Some implementations of rmdir let you remove '.' or '/'.
423    Report an error with errno set to zero for obvious cases of this;
424    otherwise call rmdir.  */
425 static int
426 safer_rmdir (const char *file_name)
427 {
428   if (must_be_dot_or_slash (file_name))
429     {
430       errno = 0;
431       return -1;
432     }
433
434   return unlinkat (chdir_fd, file_name, AT_REMOVEDIR);
435 }
436
437 /* Remove FILE_NAME, returning 1 on success.  If FILE_NAME is a directory,
438    then if OPTION is RECURSIVE_REMOVE_OPTION is set remove FILE_NAME
439    recursively; otherwise, remove it only if it is empty.  If FILE_NAME is
440    a directory that cannot be removed (e.g., because it is nonempty)
441    and if OPTION is WANT_DIRECTORY_REMOVE_OPTION, then return -1.
442    Return 0 on error, with errno set; if FILE_NAME is obviously the working
443    directory return zero with errno set to zero.  */
444 int
445 remove_any_file (const char *file_name, enum remove_option option)
446 {
447   /* Try unlink first if we cannot unlink directories, as this saves
448      us a system call in the common case where we're removing a
449      non-directory.  */
450   bool try_unlink_first = cannot_unlink_dir ();
451
452   if (try_unlink_first)
453     {
454       if (unlinkat (chdir_fd, file_name, 0) == 0)
455         return 1;
456
457       /* POSIX 1003.1-2001 requires EPERM when attempting to unlink a
458          directory without appropriate privileges, but many Linux
459          kernels return the more-sensible EISDIR.  */
460       if (errno != EPERM && errno != EISDIR)
461         return 0;
462     }
463
464   if (safer_rmdir (file_name) == 0)
465     return 1;
466
467   switch (errno)
468     {
469     case ENOTDIR:
470       return !try_unlink_first && unlinkat (chdir_fd, file_name, 0) == 0;
471
472     case 0:
473     case EEXIST:
474 #if defined ENOTEMPTY && ENOTEMPTY != EEXIST
475     case ENOTEMPTY:
476 #endif
477       switch (option)
478         {
479         case ORDINARY_REMOVE_OPTION:
480           break;
481
482         case WANT_DIRECTORY_REMOVE_OPTION:
483           return -1;
484
485         case RECURSIVE_REMOVE_OPTION:
486           {
487             char *directory = savedir (file_name);
488             char const *entry;
489             size_t entrylen;
490
491             if (! directory)
492               return 0;
493
494             for (entry = directory;
495                  (entrylen = strlen (entry)) != 0;
496                  entry += entrylen + 1)
497               {
498                 char *file_name_buffer = new_name (file_name, entry);
499                 int r = remove_any_file (file_name_buffer,
500                                          RECURSIVE_REMOVE_OPTION);
501                 int e = errno;
502                 free (file_name_buffer);
503
504                 if (! r)
505                   {
506                     free (directory);
507                     errno = e;
508                     return 0;
509                   }
510               }
511
512             free (directory);
513             return safer_rmdir (file_name) == 0;
514           }
515         }
516       break;
517     }
518
519   return 0;
520 }
521
522 /* Check if FILE_NAME already exists and make a backup of it right now.
523    Return success (nonzero) only if the backup is either unneeded, or
524    successful.  For now, directories are considered to never need
525    backup.  If THIS_IS_THE_ARCHIVE is nonzero, this is the archive and
526    so, we do not have to backup block or character devices, nor remote
527    entities.  */
528 bool
529 maybe_backup_file (const char *file_name, bool this_is_the_archive)
530 {
531   struct stat file_stat;
532
533   assign_string (&before_backup_name, file_name);
534
535   /* A run situation may exist between Emacs or other GNU programs trying to
536      make a backup for the same file simultaneously.  If theoretically
537      possible, real problems are unlikely.  Doing any better would require a
538      convention, GNU-wide, for all programs doing backups.  */
539
540   assign_string (&after_backup_name, 0);
541
542   /* Check if we really need to backup the file.  */
543
544   if (this_is_the_archive && _remdev (file_name))
545     return true;
546
547   if (deref_stat (file_name, &file_stat) != 0)
548     {
549       if (errno == ENOENT)
550         return true;
551
552       stat_error (file_name);
553       return false;
554     }
555
556   if (S_ISDIR (file_stat.st_mode))
557     return true;
558
559   if (this_is_the_archive
560       && (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode)))
561     return true;
562
563   after_backup_name = find_backup_file_name (file_name, backup_type);
564   if (! after_backup_name)
565     xalloc_die ();
566
567   if (renameat (chdir_fd, before_backup_name, chdir_fd, after_backup_name)
568       == 0)
569     {
570       if (verbose_option)
571         fprintf (stdlis, _("Renaming %s to %s\n"),
572                  quote_n (0, before_backup_name),
573                  quote_n (1, after_backup_name));
574       return true;
575     }
576   else
577     {
578       /* The backup operation failed.  */
579       int e = errno;
580       ERROR ((0, e, _("%s: Cannot rename to %s"),
581               quotearg_colon (before_backup_name),
582               quote_n (1, after_backup_name)));
583       assign_string (&after_backup_name, 0);
584       return false;
585     }
586 }
587
588 /* Try to restore the recently backed up file to its original name.
589    This is usually only needed after a failed extraction.  */
590 void
591 undo_last_backup (void)
592 {
593   if (after_backup_name)
594     {
595       if (renameat (chdir_fd, after_backup_name, chdir_fd, before_backup_name)
596           != 0)
597         {
598           int e = errno;
599           ERROR ((0, e, _("%s: Cannot rename to %s"),
600                   quotearg_colon (after_backup_name),
601                   quote_n (1, before_backup_name)));
602         }
603       if (verbose_option)
604         fprintf (stdlis, _("Renaming %s back to %s\n"),
605                  quote_n (0, after_backup_name),
606                  quote_n (1, before_backup_name));
607       assign_string (&after_backup_name, 0);
608     }
609 }
610
611 /* Apply either stat or lstat to (NAME, BUF), depending on the
612    presence of the --dereference option.  NAME is relative to the
613    most-recent argument to chdir_do.  */
614 int
615 deref_stat (char const *name, struct stat *buf)
616 {
617   return fstatat (chdir_fd, name, buf, fstatat_flags);
618 }
619
620 /* Set FD's (i.e., assuming the working directory is PARENTFD, FILE's)
621    access time to ATIME.  */
622 int
623 set_file_atime (int fd, int parentfd, char const *file, struct timespec atime)
624 {
625   struct timespec ts[2];
626   ts[0] = atime;
627   ts[1].tv_nsec = UTIME_OMIT;
628   return fdutimensat (fd, parentfd, file, ts, fstatat_flags);
629 }
630
631 /* A description of a working directory.  */
632 struct wd
633 {
634   /* The directory's name.  */
635   char const *name;
636
637   /* If nonzero, the file descriptor of the directory, or AT_FDCWD if
638      the working directory.  If zero, the directory needs to be opened
639      to be used.  */
640   int fd;
641 };
642
643 /* A vector of chdir targets.  wd[0] is the initial working directory.  */
644 static struct wd *wd;
645
646 /* The number of working directories in the vector.  */
647 static size_t wd_count;
648
649 /* The allocated size of the vector.  */
650 static size_t wd_alloc;
651
652 /* The maximum number of chdir targets with open directories.
653    Don't make it too large, as many operating systems have a small
654    limit on the number of open file descriptors.  Also, the current
655    implementation does not scale well.  */
656 enum { CHDIR_CACHE_SIZE = 16 };
657
658 /* Indexes into WD of chdir targets with open file descriptors, sorted
659    most-recently used first.  Zero indexes are unused.  */
660 static int wdcache[CHDIR_CACHE_SIZE];
661
662 /* Number of nonzero entries in WDCACHE.  */
663 static size_t wdcache_count;
664
665 int
666 chdir_count ()
667 {
668   if (wd_count == 0)
669     return wd_count;
670   return wd_count - 1;
671 }
672
673 /* DIR is the operand of a -C option; add it to vector of chdir targets,
674    and return the index of its location.  */
675 int
676 chdir_arg (char const *dir)
677 {
678   if (wd_count == wd_alloc)
679     {
680       if (wd_alloc == 0)
681         {
682           wd_alloc = 2;
683           wd = xmalloc (sizeof *wd * wd_alloc);
684         }
685       else
686         wd = x2nrealloc (wd, &wd_alloc, sizeof *wd);
687
688       if (! wd_count)
689         {
690           wd[wd_count].name = ".";
691           wd[wd_count].fd = AT_FDCWD;
692           wd_count++;
693         }
694     }
695
696   /* Optimize the common special case of the working directory,
697      or the working directory as a prefix.  */
698   if (dir[0])
699     {
700       while (dir[0] == '.' && ISSLASH (dir[1]))
701         for (dir += 2;  ISSLASH (*dir);  dir++)
702           continue;
703       if (! dir[dir[0] == '.'])
704         return wd_count - 1;
705     }
706
707   wd[wd_count].name = dir;
708   wd[wd_count].fd = 0;
709   return wd_count++;
710 }
711
712 /* Index of current directory.  */
713 int chdir_current;
714
715 /* Value suitable for use as the first argument to openat, and in
716    similar locations for fstatat, etc.  This is an open file
717    descriptor, or AT_FDCWD if the working directory is current.  It is
718    valid until the next invocation of chdir_do.  */
719 int chdir_fd = AT_FDCWD;
720
721 /* Change to directory I, in a virtual way.  This does not actually
722    invoke chdir; it merely sets chdir_fd to an int suitable as the
723    first argument for openat, etc.  If I is 0, change to the initial
724    working directory; otherwise, I must be a value returned by
725    chdir_arg.  */
726 void
727 chdir_do (int i)
728 {
729   if (chdir_current != i)
730     {
731       struct wd *curr = &wd[i];
732       int fd = curr->fd;
733
734       if (! fd)
735         {
736           if (! IS_ABSOLUTE_FILE_NAME (curr->name))
737             chdir_do (i - 1);
738           fd = openat (chdir_fd, curr->name,
739                        open_searchdir_flags & ~ O_NOFOLLOW);
740           if (fd < 0)
741             open_fatal (curr->name);
742
743           curr->fd = fd;
744
745           /* Add I to the cache, tossing out the lowest-ranking entry if the
746              cache is full.  */
747           if (wdcache_count < CHDIR_CACHE_SIZE)
748             wdcache[wdcache_count++] = i;
749           else
750             {
751               struct wd *stale = &wd[wdcache[CHDIR_CACHE_SIZE - 1]];
752               if (close (stale->fd) != 0)
753                 close_diag (stale->name);
754               stale->fd = 0;
755               wdcache[CHDIR_CACHE_SIZE - 1] = i;
756             }
757         }
758
759       if (0 < fd)
760         {
761           /* Move the i value to the front of the cache.  This is
762              O(CHDIR_CACHE_SIZE), but the cache is small.  */
763           size_t ci;
764           int prev = wdcache[0];
765           for (ci = 1; prev != i; ci++)
766             {
767               int curr = wdcache[ci];
768               wdcache[ci] = prev;
769               if (curr == i)
770                 break;
771               prev = curr;
772             }
773           wdcache[0] = i;
774         }
775
776       chdir_current = i;
777       chdir_fd = fd;
778     }
779 }
780 \f
781 void
782 close_diag (char const *name)
783 {
784   if (ignore_failed_read_option)
785     close_warn (name);
786   else
787     close_error (name);
788 }
789
790 void
791 open_diag (char const *name)
792 {
793   if (ignore_failed_read_option)
794     open_warn (name);
795   else
796     open_error (name);
797 }
798
799 void
800 read_diag_details (char const *name, off_t offset, size_t size)
801 {
802   if (ignore_failed_read_option)
803     read_warn_details (name, offset, size);
804   else
805     read_error_details (name, offset, size);
806 }
807
808 void
809 readlink_diag (char const *name)
810 {
811   if (ignore_failed_read_option)
812     readlink_warn (name);
813   else
814     readlink_error (name);
815 }
816
817 void
818 savedir_diag (char const *name)
819 {
820   if (ignore_failed_read_option)
821     savedir_warn (name);
822   else
823     savedir_error (name);
824 }
825
826 void
827 seek_diag_details (char const *name, off_t offset)
828 {
829   if (ignore_failed_read_option)
830     seek_warn_details (name, offset);
831   else
832     seek_error_details (name, offset);
833 }
834
835 void
836 stat_diag (char const *name)
837 {
838   if (ignore_failed_read_option)
839     stat_warn (name);
840   else
841     stat_error (name);
842 }
843
844 void
845 file_removed_diag (const char *name, bool top_level,
846                    void (*diagfn) (char const *name))
847 {
848   if (!top_level && errno == ENOENT)
849     {
850       WARNOPT (WARN_FILE_REMOVED,
851                (0, 0, _("%s: File removed before we read it"),
852                 quotearg_colon (name)));
853       set_exit_status (TAREXIT_DIFFERS);
854     }
855   else
856     diagfn (name);
857 }
858
859 void
860 dir_removed_diag (const char *name, bool top_level,
861                    void (*diagfn) (char const *name))
862 {
863   if (!top_level && errno == ENOENT)
864     {
865       WARNOPT (WARN_FILE_REMOVED,
866                (0, 0, _("%s: Directory removed before we read it"),
867                 quotearg_colon (name)));
868       set_exit_status (TAREXIT_DIFFERS);
869     }
870   else
871     diagfn (name);
872 }
873
874 void
875 write_fatal_details (char const *name, ssize_t status, size_t size)
876 {
877   write_error_details (name, status, size);
878   fatal_exit ();
879 }
880
881 /* Fork, aborting if unsuccessful.  */
882 pid_t
883 xfork (void)
884 {
885   pid_t p = fork ();
886   if (p == (pid_t) -1)
887     call_arg_fatal ("fork", _("child process"));
888   return p;
889 }
890
891 /* Create a pipe, aborting if unsuccessful.  */
892 void
893 xpipe (int fd[2])
894 {
895   if (pipe (fd) < 0)
896     call_arg_fatal ("pipe", _("interprocess channel"));
897 }
898
899 /* Return PTR, aligned upward to the next multiple of ALIGNMENT.
900    ALIGNMENT must be nonzero.  The caller must arrange for ((char *)
901    PTR) through ((char *) PTR + ALIGNMENT - 1) to be addressable
902    locations.  */
903
904 static inline void *
905 ptr_align (void *ptr, size_t alignment)
906 {
907   char *p0 = ptr;
908   char *p1 = p0 + alignment - 1;
909   return p1 - (size_t) p1 % alignment;
910 }
911
912 /* Return the address of a page-aligned buffer of at least SIZE bytes.
913    The caller should free *PTR when done with the buffer.  */
914
915 void *
916 page_aligned_alloc (void **ptr, size_t size)
917 {
918   size_t alignment = getpagesize ();
919   size_t size1 = size + alignment;
920   if (size1 < size)
921     xalloc_die ();
922   *ptr = xmalloc (size1);
923   return ptr_align (*ptr, alignment);
924 }
925
926 \f
927
928 struct namebuf
929 {
930   char *buffer;         /* directory, `/', and directory member */
931   size_t buffer_size;   /* allocated size of name_buffer */
932   size_t dir_length;    /* length of directory part in buffer */
933 };
934
935 namebuf_t
936 namebuf_create (const char *dir)
937 {
938   namebuf_t buf = xmalloc (sizeof (*buf));
939   buf->buffer_size = strlen (dir) + 2;
940   buf->buffer = xmalloc (buf->buffer_size);
941   strcpy (buf->buffer, dir);
942   buf->dir_length = strlen (buf->buffer);
943   if (!ISSLASH (buf->buffer[buf->dir_length - 1]))
944     buf->buffer[buf->dir_length++] = DIRECTORY_SEPARATOR;
945   return buf;
946 }
947
948 void
949 namebuf_free (namebuf_t buf)
950 {
951   free (buf->buffer);
952   free (buf);
953 }
954
955 char *
956 namebuf_name (namebuf_t buf, const char *name)
957 {
958   size_t len = strlen (name);
959   while (buf->dir_length + len + 1 >= buf->buffer_size)
960     buf->buffer = x2realloc (buf->buffer, &buf->buffer_size);
961   strcpy (buf->buffer + buf->dir_length, name);
962   return buf->buffer;
963 }