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