diff options
Diffstat (limited to 'util')
-rw-r--r-- | util/ChangeLog | 6 | ||||
-rw-r--r-- | util/fileutil.c | 112 |
2 files changed, 95 insertions, 23 deletions
diff --git a/util/ChangeLog b/util/ChangeLog index f6a916f53..189ab6de3 100644 --- a/util/ChangeLog +++ b/util/ChangeLog @@ -1,3 +1,9 @@ +2007-08-24 Werner Koch <[email protected]> + + * fileutil.c (same_file_p): New. Taken from SVN trunk. + (compare_filenames) [HAVE_DRIVE_LETTERS]: Take drive letters and + backslashes in account. + 2007-04-16 David Shaw <[email protected]> * strgutil.c (ascii_toupper, ascii_tolower, ascii_strcasecmp, diff --git a/util/fileutil.c b/util/fileutil.c index 5834e3d89..dc2722105 100644 --- a/util/fileutil.c +++ b/util/fileutil.c @@ -1,5 +1,5 @@ /* fileutil.c - file utilities - * Copyright (C) 1998, 2003, 2005 Free Software Foundation, Inc. + * Copyright (C) 1998, 2003, 2005, 2007 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -30,6 +30,17 @@ #ifdef HAVE_PWD_H #include <pwd.h> #endif +#include <ctype.h> +#ifdef HAVE_W32_SYSTEM +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +#else /*!HAVE_W32_SYSTEM*/ +# include <sys/types.h> +# include <sys/stat.h> +# include <unistd.h> +#endif /*!HAVE_W32_SYSTEM*/ + + #include "util.h" #include "memory.h" #include "ttyio.h" @@ -194,32 +205,87 @@ make_filename( const char *first_part, ... ) } +/* Compare whether the filenames are identical. This is a + special version of strcmp() taking the semantics of filenames in + account. Note that this function works only on the supplied names + without considereing any context like the current directory. See + also same_file_p(). */ int -compare_filenames( const char *a, const char *b ) +compare_filenames (const char *a, const char *b) { - /* ? check whether this is an absolute filename and - * resolve symlinks? - */ -#ifndef __riscos__ -#ifdef HAVE_DRIVE_LETTERS - return ascii_strcasecmp(a,b); -#else - return strcmp(a,b); +#ifdef __riscos__ + int c = 0; + char *abuf, *bbuf; + + abuf = riscos_gstrans(a); + bbuf = riscos_gstrans(b); + c = ascii_strcasecmp (abuf, bbuf); + xfree(abuf); + xfree(bbuf); + + return c; +#elif defined (HAVE_DRIVE_LETTERS) + for ( ; *a && *b; a++, b++ ) + { + if (*a != *b + && (toupper (*(const unsigned char*)a) + != toupper (*(const unsigned char*)b) ) + && !((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/'))) + break; + } + if ((*a == '/' && *b == '\\') || (*a == '\\' && *b == '/')) + return 0; + else + return (toupper (*(const unsigned char*)a) + - toupper (*(const unsigned char*)b)); +#else /*!HAVE_DRIVE_LETTERS*/ + return strcmp (a,b); #endif -#else /* __riscos__ */ - int c = 0; - char *abuf, *bbuf; - - abuf = riscos_gstrans(a); - bbuf = riscos_gstrans(b); - - c = ascii_strcasecmp (abuf, bbuf); - - xfree(abuf); - xfree(bbuf); +} - return c; -#endif /* __riscos__ */ +/* Check whether the files NAME1 and NAME2 are identical. This is for + example achieved by comparing the inode numbers of the files. */ +int +same_file_p (const char *name1, const char *name2) +{ + int yes; + + /* First try a shortcut. */ + if (!compare_filenames (name1, name2)) + yes = 1; + else + { +#ifdef HAVE_W32_SYSTEM + HANDLE file1, file2; + BY_HANDLE_FILE_INFORMATION info1, info2; + + file1 = CreateFile (name1, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + if (file1 == INVALID_HANDLE_VALUE) + yes = 0; /* If we can't open the file, it is not the same. */ + else + { + file2 = CreateFile (name2, 0, 0, NULL, OPEN_EXISTING, 0, NULL); + if (file1 == INVALID_HANDLE_VALUE) + yes = 0; /* If we can't open the file, it is not the same. */ + else + { + yes = (GetFileInformationByHandle (file1, &info1) + && GetFileInformationByHandle (file2, &info2) + && info1.dwVolumeSerialNumber==info2.dwVolumeSerialNumber + && info1.nFileIndexHigh == info2.nFileIndexHigh + && info1.nFileIndexLow == info2.nFileIndexLow); + CloseHandle (file2); + } + CloseHandle (file1); + } +#else /*!HAVE_W32_SYSTEM*/ + struct stat info1, info2; + + yes = (!stat (name1, &info1) && !stat (name2, &info2) + && info1.st_dev == info2.st_dev && info1.st_ino == info2.st_ino); +#endif /*!HAVE_W32_SYSTEM*/ + } + return yes; } |