X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fmisc.c;h=6f67887fab6d0f83829974d3eaa4b75353b399f7;hb=45a574151ae64ae4f9b0d99302f7da6d9d8451a9;hp=12b40ac341e50c62aed399d480821bfa372002e0;hpb=cc40c57a37b1e443a5088fdda0fbb3687b1f4773;p=chaz%2Ftar diff --git a/src/misc.c b/src/misc.c index 12b40ac..6f67887 100644 --- a/src/misc.c +++ b/src/misc.c @@ -50,6 +50,9 @@ assign_string (char **string, const char *value) *string = value ? xstrdup (value) : 0; } +#if 0 +/* This function is currently unused; perhaps it should be removed? */ + /* Allocate a copy of the string quoted as in C, and returns that. If the string does not have to be quoted, it returns a null pointer. The allocated copy should normally be freed with free() after the @@ -62,7 +65,7 @@ assign_string (char **string, const char *value) when reading directory files. This means that we can't use quotearg, as quotearg is locale-dependent and is meant for human consumption. */ -char * +static char * quote_copy_string (const char *string) { const char *source = string; @@ -103,6 +106,7 @@ quote_copy_string (const char *string) } return 0; } +#endif /* Takes a quoted C string (like those produced by quote_copy_string) and turns it back into the un-quoted original. This is done in @@ -278,7 +282,32 @@ normalize_filename_x (char *file_name) char * normalize_filename (const char *name) { - char *copy = xstrdup (name); + char *copy = NULL; + + if (IS_RELATIVE_FILE_NAME (name)) + { + /* Set COPY to the absolute file name if possible. + + FIXME: There should be no need to get the absolute file name. + getcwd is slow, it might fail, and it does not necessarily + return a canonical name even when it succeeds. Perhaps we + can use dev+ino pairs instead of names? */ + copy = xgetcwd (); + if (copy) + { + size_t copylen = strlen (copy); + bool need_separator = ! (DOUBLE_SLASH_IS_DISTINCT_ROOT + && copylen == 2 && ISSLASH (copy[1])); + copy = xrealloc (copy, copylen + need_separator + strlen (name) + 1); + copy[copylen] = DIRECTORY_SEPARATOR; + strcpy (copy + copylen + need_separator, name); + } + else + WARN ((0, errno, _("Cannot get working directory"))); + } + + if (! copy) + copy = xstrdup (name); normalize_filename_x (copy); return copy; } @@ -615,8 +644,15 @@ set_file_atime (int fd, char const *file, struct timespec const timespec[2]) /* A description of a working directory. */ struct wd { + /* The directory's name. */ char const *name; - int saved; + + /* A negative value if no attempt has been made to save the + directory, 0 if it was saved successfully, and a positive errno + value if it was not saved successfully. */ + int err; + + /* The saved version of the directory, if ERR == 0. */ struct saved_cwd saved_cwd; }; @@ -655,7 +691,7 @@ chdir_arg (char const *dir) if (! wd_count) { wd[wd_count].name = "."; - wd[wd_count].saved = 0; + wd[wd_count].err = -1; wd_count++; } } @@ -672,28 +708,28 @@ chdir_arg (char const *dir) } wd[wd_count].name = dir; - wd[wd_count].saved = 0; + wd[wd_count].err = -1; return wd_count++; } +/* Index of current directory. */ +int chdir_current; + /* Change to directory I. If I is 0, change to the initial working directory; otherwise, I must be a value returned by chdir_arg. */ void chdir_do (int i) { - static int previous; - - if (previous != i) + if (chdir_current != i) { - struct wd *prev = &wd[previous]; + struct wd *prev = &wd[chdir_current]; struct wd *curr = &wd[i]; - if (! prev->saved) + if (prev->err < 0) { - int err = 0; - prev->saved = 1; + prev->err = 0; if (save_cwd (&prev->saved_cwd) != 0) - err = errno; + prev->err = errno; else if (0 <= prev->saved_cwd.desc) { /* Make sure we still have at least one descriptor available. */ @@ -708,20 +744,20 @@ chdir_do (int i) prev->saved_cwd.desc = -1; prev->saved_cwd.name = xgetcwd (); if (! prev->saved_cwd.name) - err = errno; + prev->err = errno; } else - err = errno; + prev->err = errno; } - - if (err) - FATAL_ERROR ((0, err, _("Cannot save working directory"))); } - if (curr->saved) + if (0 <= curr->err) { - if (restore_cwd (&curr->saved_cwd)) - FATAL_ERROR ((0, 0, _("Cannot change working directory"))); + int err = curr->err; + if (err == 0 && restore_cwd (&curr->saved_cwd) != 0) + err = errno; + if (err) + FATAL_ERROR ((0, err, _("Cannot restore working directory"))); } else { @@ -731,7 +767,7 @@ chdir_do (int i) chdir_fatal (curr->name); } - previous = i; + chdir_current = i; } }