X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fmisc.c;h=b8ef6eabf1ae16e43b1fece6d948b7bf0bc65b76;hb=e3d28d84bda24a45c239b398e7b42ccd9be2d0c2;hp=5fe80f4bb56e3616010cbb9075ca06e009572b6e;hpb=df7b55a8f6354e30e8da62eec7f706df033d0c81;p=chaz%2Ftar diff --git a/src/misc.c b/src/misc.c index 5fe80f4..b8ef6ea 100644 --- a/src/misc.c +++ b/src/misc.c @@ -1,7 +1,7 @@ /* Miscellaneous functions, not really specific to GNU tar. - Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001, - 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2012 Free Software Foundation, Inc. + Copyright 1988, 1992, 1994-1997, 1999-2001, 2003-2007, 2009-2010, + 2012-2013 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -14,8 +14,7 @@ Public License for more details. You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + with this program. If not, see . */ #define COMMON_INLINE _GL_EXTERN_INLINE #include @@ -284,7 +283,7 @@ normalize_filename (const char *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 (); + copy = tar_getcwd (); if (copy) { size_t copylen = strlen (copy); @@ -333,7 +332,7 @@ replace_prefix (char **pname, const char *samp, size_t slen, the range MINVAL .. -1, represent it with a string representation of the negative integer, using leading '-'. */ #if ! (INTMAX_MAX <= UINTMAX_MAX / 2) -# error "strtosysint accepts uintmax_t to represent intmax_t" +# error "sysinttostr: uintmax_t cannot represent all intmax_t values" #endif char * sysinttostr (uintmax_t value, intmax_t minval, uintmax_t maxval, @@ -362,7 +361,7 @@ sysinttostr (uintmax_t value, intmax_t minval, uintmax_t maxval, On conversion error, return 0 and set errno = EINVAL. On overflow, return an extreme value and set errno = ERANGE. */ #if ! (INTMAX_MAX <= UINTMAX_MAX) -# error "strtosysint accepts uintmax_t to represent nonnegative intmax_t" +# error "strtosysint: nonnegative intmax_t does not fit in uintmax_t" #endif intmax_t strtosysint (char const *arg, char **arglim, intmax_t minval, uintmax_t maxval) @@ -632,7 +631,7 @@ remove_any_file (const char *file_name, enum remove_option option) case RECURSIVE_REMOVE_OPTION: { - char *directory = savedir (file_name); + char *directory = tar_savedir (file_name, 0); char const *entry; size_t entrylen; @@ -977,6 +976,21 @@ chdir_do (int i) } } +char * +tar_getcwd (void) +{ + static char *cwd; + namebuf_t nbuf; + int i; + + if (!cwd) + cwd = xgetcwd (); + nbuf = namebuf_create (cwd); + for (i = 1; i <= chdir_current; i++) + namebuf_add_dir (nbuf, wd[i].name); + return namebuf_finish (nbuf); +} + void close_diag (char const *name) { @@ -1145,3 +1159,55 @@ namebuf_name (namebuf_t buf, const char *name) strcpy (buf->buffer + buf->dir_length, name); return buf->buffer; } + +void +namebuf_add_dir (namebuf_t buf, const char *name) +{ + static char dirsep[] = { DIRECTORY_SEPARATOR, 0 }; + if (!ISSLASH (buf->buffer[buf->dir_length - 1])) + { + namebuf_name (buf, dirsep); + buf->dir_length++; + } + namebuf_name (buf, name); + buf->dir_length += strlen (name); +} + +char * +namebuf_finish (namebuf_t buf) +{ + char *res = buf->buffer; + + if (ISSLASH (buf->buffer[buf->dir_length - 1])) + buf->buffer[buf->dir_length] = 0; + free (buf); + return res; +} + +/* Return the filenames in directory NAME, relative to the chdir_fd. + If the directory does not exist, report error if MUST_EXIST is + true. + + Return NULL on errors. +*/ +char * +tar_savedir (const char *name, int must_exist) +{ + char *ret = NULL; + DIR *dir = NULL; + int fd = openat (chdir_fd, name, open_read_flags | O_DIRECTORY); + if (fd < 0) + { + if (!must_exist && errno == ENOENT) + return NULL; + open_error (name); + } + else if (! ((dir = fdopendir (fd)) + && (ret = streamsavedir (dir)))) + savedir_error (name); + + if (dir ? closedir (dir) != 0 : 0 <= fd && close (fd) != 0) + savedir_error (name); + + return ret; +}