aboutsummaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/ChangeLog6
-rw-r--r--util/fileutil.c112
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;
}