1 /* Miscellaneous functions, not really specific to GNU tar.
2 Copyright (C) 1988, 92, 94, 95, 96, 97 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2, or (at your option) any later
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
12 Public License for more details.
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 59 Place - Suite 330, Boston, MA 02111-1307, USA. */
20 #include "backupfile.h"
23 /* The following inclusion for crosschecking prototypes, only. */
26 /* Handling strings. */
28 #define ISPRINT(Char) (ISASCII (Char) && isprint (Char))
30 /*-------------------------------------------------------------------------.
31 | Assign STRING to a copy of VALUE if not NULL, or to NULL. If STRING was |
32 | not NULL, it is freed first. |
33 `-------------------------------------------------------------------------*/
36 assign_string (char **string, const char *value)
40 *string = value ? xstrdup (value) : NULL;
43 /*------------------------------------------------------------------------.
44 | Allocate a copy of the string quoted as in C, and returns that. If the |
45 | string does not have to be quoted, it returns the NULL string. The |
46 | allocated copy should normally be freed with free() after the caller is |
49 | This is used in two contexts only: either listing a tar file for the |
50 | --list (-t) option, or generating the directory file in incremental |
52 `------------------------------------------------------------------------*/
55 quote_copy_string (const char *string)
57 const char *source = string;
58 char *destination = NULL;
64 int character = (unsigned char) *source++;
66 if (character == '\\')
70 int length = (source - string) - 1;
73 buffer = (char *) xmalloc (length + 5 + strlen (source) * 4);
74 memcpy (buffer, string, (size_t) length);
75 destination = buffer + length;
77 *destination++ = '\\';
78 *destination++ = '\\';
80 else if (ISPRINT (character))
83 *destination++ = character;
89 int length = (source - string) - 1;
92 buffer = (char *) xmalloc (length + 5 + strlen (source) * 4);
93 memcpy (buffer, string, (size_t) length);
94 destination = buffer + length;
96 *destination++ = '\\';
100 *destination++ = 'n';
104 *destination++ = 't';
108 *destination++ = 'f';
112 *destination++ = 'b';
116 *destination++ = 'r';
120 *destination++ = '?';
124 *destination++ = (character >> 6) + '0';
125 *destination++ = ((character >> 3) & 07) + '0';
126 *destination++ = (character & 07) + '0';
139 /*-------------------------------------------------------------------------.
140 | Takes a quoted C string (like those produced by quote_copy_string) and |
141 | turns it back into the un-quoted original. This is done in place. |
142 | Returns 0 only if the string was not properly quoted, but completes the |
143 | unquoting anyway. |
145 | This is used for reading the saved directory file in incremental dumps. |
146 | It is used for decoding old `N' records (demangling names). But also, |
147 | it is used for decoding file arguments, would they come from the shell |
148 | or a -T file, and for decoding the --exclude argument. |
149 `-------------------------------------------------------------------------*/
152 unquote_string (char *string)
155 char *source = string;
156 char *destination = string;
163 *destination++ = '\\';
168 *destination++ = '\n';
173 *destination++ = '\t';
178 *destination++ = '\f';
183 *destination++ = '\b';
188 *destination++ = '\r';
193 *destination++ = 0177;
206 int value = *source++ - '0';
208 if (*source < '0' || *source > '7')
210 *destination++ = value;
213 value = value * 8 + *source++ - '0';
214 if (*source < '0' || *source > '7')
216 *destination++ = value;
219 value = value * 8 + *source++ - '0';
220 *destination++ = value;
226 *destination++ = '\\';
228 *destination++ = *source++;
231 else if (source != destination)
232 *destination++ = *source++;
234 source++, destination++;
236 if (source != destination)
248 merge_sort (char *list, int length, int offset, int (*compare) (char *, char *))
259 #define SUCCESSOR(Pointer) \
260 (*((char **) (((char *) (Pointer)) + offset)))
267 if ((*compare) (list, SUCCESSOR (list)) > 0)
269 result = SUCCESSOR (list);
270 SUCCESSOR (result) = list;
271 SUCCESSOR (list) = NULL;
278 first_length = (length + 1) / 2;
279 second_length = length / 2;
280 for (cursor = list, counter = first_length - 1;
282 cursor = SUCCESSOR (cursor), counter--)
284 second_list = SUCCESSOR (cursor);
285 SUCCESSOR (cursor) = NULL;
287 first_list = merge_sort (first_list, first_length, offset, compare);
288 second_list = merge_sort (second_list, second_length, offset, compare);
290 merge_point = &result;
291 while (first_list && second_list)
292 if ((*compare) (first_list, second_list) < 0)
294 cursor = SUCCESSOR (first_list);
295 *merge_point = first_list;
296 merge_point = &SUCCESSOR (first_list);
301 cursor = SUCCESSOR (second_list);
302 *merge_point = second_list;
303 merge_point = &SUCCESSOR (second_list);
304 second_list = cursor;
307 *merge_point = first_list;
309 *merge_point = second_list;
318 /* Saved names in case backup needs to be undone. */
319 static char *before_backup_name = NULL;
320 static char *after_backup_name = NULL;
322 /*------------------------------------------------------------------------.
323 | Returns nonzero if p is `.' or `..'. This could be a macro for speed. |
324 `------------------------------------------------------------------------*/
326 /* Early Solaris 2.4 readdir may return d->d_name as `' in NFS-mounted
327 directories. The workaround here skips `' just like `.'. Without it,
328 GNU tar would then treat `' much like `.' and loop endlessly. */
331 is_dot_or_dotdot (const char *p)
334 || (p[0] == '.' && (p[1] == '\0'
335 || (p[1] == '.' && p[2] == '\0'))));
338 /*-------------------------------------------------------------------------.
339 | Delete PATH, whatever it might be. If RECURSE, first recursively delete |
340 | the contents of PATH when it is a directory. Return zero on any error, |
341 | with errno set. As a special case, if we fail to delete a directory |
342 | when not RECURSE, do not set errno (just be tolerant to this error). |
343 `-------------------------------------------------------------------------*/
346 remove_any_file (const char *path, int recurse)
348 struct stat stat_buffer;
350 if (lstat (path, &stat_buffer) < 0)
353 if (S_ISDIR (stat_buffer.st_mode))
356 DIR *dirp = opendir (path);
362 while (dp = readdir (dirp), dp && !is_dot_or_dotdot (dp->d_name))
364 char *path_buffer = new_name (path, dp->d_name);
366 if (!remove_any_file (path_buffer, 1))
368 int saved_errno = errno;
372 errno = saved_errno; /* FIXME: errno should be read-only */
378 return rmdir (path) >= 0;
382 /* FIXME: Saving errno might not be needed anymore, now that
383 extract_archive tests for the special case before recovery. */
384 int saved_errno = errno;
386 if (rmdir (path) >= 0)
388 errno = saved_errno; /* FIXME: errno should be read-only */
392 return unlink (path) >= 0;
395 /*-------------------------------------------------------------------------.
396 | Check if PATH already exists and make a backup of it right now. Return |
397 | success (nonzero) only if the backup in either unneeded, or successful. |
399 | For now, directories are considered to never need backup. If ARCHIVE is |
400 | nonzero, this is the archive and so, we do not have to backup block or |
401 | character devices, nor remote entities. |
402 `-------------------------------------------------------------------------*/
405 maybe_backup_file (const char *path, int archive)
407 struct stat file_stat;
409 /* Check if we really need to backup the file. */
411 if (archive && _remdev (path))
414 if (stat (path, &file_stat))
419 ERROR ((0, errno, "%s", path));
423 if (S_ISDIR (file_stat.st_mode))
427 if (archive && S_ISBLK (file_stat.st_mode))
432 if (archive && S_ISCHR (file_stat.st_mode))
436 assign_string (&before_backup_name, path);
438 /* A run situation may exist between Emacs or other GNU programs trying to
439 make a backup for the same file simultaneously. If theoretically
440 possible, real problems are unlikely. Doing any better would require a
441 convention, GNU-wide, for all programs doing backups. */
443 assign_string (&after_backup_name, NULL);
444 after_backup_name = find_backup_file_name (path);
445 if (after_backup_name == NULL)
446 FATAL_ERROR ((0, 0, "Virtual memory exhausted"));
448 if (rename (before_backup_name, after_backup_name) == 0)
451 fprintf (stdlis, _("Renaming previous `%s' to `%s'\n"),
452 before_backup_name, after_backup_name);
456 /* The backup operation failed. */
458 ERROR ((0, errno, _("%s: Cannot rename for backup"), before_backup_name));
459 assign_string (&after_backup_name, NULL);
463 /*-----------------------------------------------------------------------.
464 | Try to restore the recently backed up file to its original name. This |
465 | is usually only needed after a failed extraction. |
466 `-----------------------------------------------------------------------*/
469 undo_last_backup (void)
471 if (after_backup_name)
473 if (rename (after_backup_name, before_backup_name) != 0)
474 ERROR ((0, errno, _("%s: Cannot rename from backup"),
475 before_backup_name));
477 fprintf (stdlis, _("Renaming `%s' back to `%s'\n"),
478 after_backup_name, before_backup_name);
479 assign_string (&after_backup_name, NULL);