[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
mingw and same-inode
From: |
Eric Blake |
Subject: |
mingw and same-inode |
Date: |
Wed, 23 Sep 2009 21:10:10 +0000 (UTC) |
User-agent: |
Loom/3.14 (http://gmane.org/) |
I'm currently testing these two patches, as mingw prerequisites before I can
get linkat() working. In particular, mingw is lousy at SAME_INODE, since all
three of [fl]stat produce st_ino == 0 for all files (then again, mingw never
claimed POSIX compliance!). Code was always taking the identical-file path,
even for distinct files.
I'm also preparing a followup patch for coreutils usage of SAME_INODE.
Thoughts before I apply this?
>From 0719361730021a335bb932bfe4ce2f0524f43649 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Wed, 23 Sep 2009 14:13:00 -0600
Subject: [PATCH 1/2] lstat: avoid mingw compilation error
The openat module required lstat, but then repeated the checks
for whether lstat worked. When cross-compiling to mingw, this
led to a wrong answer and tried compiling lstat.c, even though it
was not necessary, with a result of a compiler warning about
undeclared lstat.
* m4/lstat.m4 (gl_FUNC_LSTAT): Avoid duplicate calls to
AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK, and deal with missing
lstat ourselves.
* lib/lstat.c [!HAVE_LSTAT]: Do nothing if <sys/stat.h> override
was adequate.
* m4/sys_stat_h.m4 (gl_HEADER_SYS_STAT_H): Let lstat module handle
the checks for lstat.
Signed-off-by: Eric Blake <address@hidden>
---
ChangeLog | 9 +++++++++
lib/lstat.c | 23 ++++++++++++++++-------
m4/lstat.m4 | 10 ++++++----
m4/sys_stat_h.m4 | 12 +-----------
4 files changed, 32 insertions(+), 22 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 8a4aebf..7ed6953 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2009-09-23 Eric Blake <address@hidden>
+ lstat: avoid mingw compilation error
+ * m4/lstat.m4 (gl_FUNC_LSTAT): Avoid duplicate calls to
+ AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK, and deal with missing
+ lstat ourselves.
+ * lib/lstat.c [!HAVE_LSTAT]: Do nothing if <sys/stat.h> override
+ was adequate.
+ * m4/sys_stat_h.m4 (gl_HEADER_SYS_STAT_H): Let lstat module handle
+ the checks for lstat.
+
link: fix test failure on Solaris 9
* lib/link.c (rpl_link): Don't assume link will catch bogus
trailing slash on source.
diff --git a/lib/lstat.c b/lib/lstat.c
index a05f674..27a0cb5 100644
--- a/lib/lstat.c
+++ b/lib/lstat.c
@@ -20,11 +20,18 @@
#include <config.h>
+#if !HAVE_LSTAT
+/* On systems that lack symlinks, our replacement <sys/stat.h> already
+ defined lstat as stat, so there is nothing further to do other than
+ avoid an empty file. */
+typedef int dummy;
+#else /* HAVE_LSTAT */
+
/* Get the original definition of lstat. It might be defined as a macro. */
-#define __need_system_sys_stat_h
-#include <sys/types.h>
-#include <sys/stat.h>
-#undef __need_system_sys_stat_h
+# define __need_system_sys_stat_h
+# include <sys/types.h>
+# include <sys/stat.h>
+# undef __need_system_sys_stat_h
static inline int
orig_lstat (const char *filename, struct stat *buf)
@@ -33,10 +40,10 @@ orig_lstat (const char *filename, struct stat *buf)
}
/* Specification. */
-#include <sys/stat.h>
+# include <sys/stat.h>
-#include <string.h>
-#include <errno.h>
+# include <string.h>
+# include <errno.h>
/* lstat works differently on Linux and Solaris systems. POSIX (see
`pathname resolution' in the glossary) requires that programs like
@@ -81,3 +88,5 @@ rpl_lstat (const char *file, struct stat *sbuf)
}
return stat (file, sbuf);
}
+
+#endif /* HAVE_LSTAT */
diff --git a/m4/lstat.m4 b/m4/lstat.m4
index 74c78fe..089d0ff 100644
--- a/m4/lstat.m4
+++ b/m4/lstat.m4
@@ -1,4 +1,4 @@
-# serial 19
+# serial 20
# Copyright (C) 1997-2001, 2003-2009 Free Software Foundation, Inc.
#
@@ -12,15 +12,17 @@ AC_DEFUN([gl_FUNC_LSTAT],
[
AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
dnl If lstat does not exist, the replacement <sys/stat.h> does
- dnl "#define lstat stat", and lstat.c does not need to be compiled.
+ dnl "#define lstat stat", and lstat.c is a no-op.
AC_CHECK_FUNCS_ONCE([lstat])
if test $ac_cv_func_lstat = yes; then
- AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
- dnl Note: AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK does AC_LIBOBJ([lstat]).
+ AC_REQUIRE([AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK])
if test $ac_cv_func_lstat_dereferences_slashed_symlink = no; then
+ dnl Note: AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK does AC_LIBOBJ([lstat]).
REPLACE_LSTAT=1
fi
# Prerequisites of lib/lstat.c.
AC_REQUIRE([AC_C_INLINE])
+ else
+ HAVE_LSTAT=0
fi
])
diff --git a/m4/sys_stat_h.m4 b/m4/sys_stat_h.m4
index df7b238..147c517 100644
--- a/m4/sys_stat_h.m4
+++ b/m4/sys_stat_h.m4
@@ -1,4 +1,4 @@
-# sys_stat_h.m4 serial 16 -*- Autoconf -*-
+# sys_stat_h.m4 serial 17 -*- Autoconf -*-
dnl Copyright (C) 2006-2009 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -11,16 +11,6 @@ AC_DEFUN([gl_HEADER_SYS_STAT_H],
[
AC_REQUIRE([gl_SYS_STAT_H_DEFAULTS])
- dnl Check for lstat. Systems that lack it (mingw) also lack symlinks, so
- dnl stat is a good replacement.
- AC_CHECK_FUNCS_ONCE([lstat])
- if test $ac_cv_func_lstat = yes; then
- HAVE_LSTAT=1
- else
- HAVE_LSTAT=0
- fi
- AC_SUBST([HAVE_LSTAT])
-
dnl For the mkdir substitute.
AC_REQUIRE([AC_C_INLINE])
---
1.6.1.2
>From 5538c910e1acd307a3d3e69f6d80044b1f3d935a Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Wed, 23 Sep 2009 14:51:29 -0600
Subject: [PATCH 2/2] same-inode: make SAME_INODE tri-state, to port to mingw
Mingw has the annoying habit (already documented in
doc/posix-functions/*stat) that st_ino is always 0.
This means that naive uses of SAME_INODE(a,b) would
succeed, even on distinct files.
Here's an analysis of all gnulib modules that used
the macro before this commit:
chdir-safer is safe - SAME_INODE protected by HAVE_READLINK
cycle-check - mingw has no dir hard links and no symlinks,
so no directory cycles can occur, and we should ignore -1
fts - SAME_INODE protected by FTS_DEBUG
hash-triple - using -1 gives more hash collisions, but
the results are still correct
openat-proc - SAME_INODE protected by stat("/proc/self")
same - no dir cycles, so files are only same with identical name
link-follow.m4 - configure test already correct on mingw
test-canonicalize* - test already passes on mingw
test-[l]stat - test already passes on mingw
* NEWS: Mention this change.
* lib/same-inode.h (same-inode.h): Recognize mingw limitation of
st_ino always being 0.
* lib/cycle-check.h (CYCLE_CHECK_REFLECT_CHDIR_UP): Update caller.
* lib/cycle-check.c (cycle_check): Likewise.
* lib/same.c (same_name): Likewise.
Signed-off-by: Eric Blake <address@hidden>
---
ChangeLog | 8 ++++++++
NEWS | 3 +++
lib/cycle-check.c | 5 +++--
lib/cycle-check.h | 4 ++--
lib/same-inode.h | 16 +++++++++++++---
lib/same.c | 7 +++++--
6 files changed, 34 insertions(+), 9 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 7ed6953..a729fdf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2009-09-23 Eric Blake <address@hidden>
+ same-inode: make SAME_INODE tri-state, to port to mingw
+ * NEWS: Mention this change.
+ * lib/same-inode.h (same-inode.h): Recognize mingw limitation of
+ st_ino always being 0.
+ * lib/cycle-check.h (CYCLE_CHECK_REFLECT_CHDIR_UP): Update caller.
+ * lib/cycle-check.c (cycle_check): Likewise.
+ * lib/same.c (same_name): Likewise.
+
lstat: avoid mingw compilation error
* m4/lstat.m4 (gl_FUNC_LSTAT): Avoid duplicate calls to
AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK, and deal with missing
diff --git a/NEWS b/NEWS
index 62c631f..87fc884 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,9 @@ User visible incompatible changes
Date Modules Changes
+2009-09-23 same-inode The macro SAME_INODE is now tri-state, adding -1
+ for unknown.
+
2009-09-16 canonicalize-lgpl
The include file is changed from "canonicalize.h"
to <stdlib.h>.
diff --git a/lib/cycle-check.c b/lib/cycle-check.c
index e120460..a5b6df1 100644
--- a/lib/cycle-check.c
+++ b/lib/cycle-check.c
@@ -1,6 +1,7 @@
/* help detect directory cycles efficiently
- Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006, 2009 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
@@ -62,7 +63,7 @@ cycle_check (struct cycle_check_state *state, struct stat
const *sb)
/* If the current directory ever happens to be the same
as the one we last recorded for the cycle detection,
then it's obviously part of a cycle. */
- if (state->chdir_counter && SAME_INODE (*sb, state->dev_ino))
+ if (state->chdir_counter && SAME_INODE (*sb, state->dev_ino) == 1)
return true;
/* If the number of `descending' chdir calls is a power of two,
diff --git a/lib/cycle-check.h b/lib/cycle-check.h
index ee3bf21..ea9b9c4 100644
--- a/lib/cycle-check.h
+++ b/lib/cycle-check.h
@@ -1,6 +1,6 @@
/* help detect directory cycles efficiently
- Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2006, 2009 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
@@ -41,7 +41,7 @@ bool cycle_check (struct cycle_check_state *state, struct
stat const *sb);
/* You must call cycle_check at least once before using this macro. */ \
if ((State)->chdir_counter == 0) \
abort (); \
- if (SAME_INODE ((State)->dev_ino, SB_subdir)) \
+ if (SAME_INODE ((State)->dev_ino, SB_subdir) == 1) \
{ \
(State)->dev_ino.st_dev = (SB_dir).st_dev; \
(State)->dev_ino.st_ino = (SB_dir).st_ino; \
diff --git a/lib/same-inode.h b/lib/same-inode.h
index 0632711..4b89dd1 100644
--- a/lib/same-inode.h
+++ b/lib/same-inode.h
@@ -1,6 +1,6 @@
/* Determine whether two stat buffers refer to the same file.
- Copyright (C) 2006 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009 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
@@ -18,8 +18,18 @@
#ifndef SAME_INODE_H
# define SAME_INODE_H 1
+/* Perform a tri-state query on whether STAT_BUF_1 and STAT_BUF_2
+ represent the same file. Return 1 for equal, 0 for distinct, and
+ -1 for indeterminate (the latter is generally possible only on
+ mingw). Algorithms that use this macro must be prepared to handle
+ the indeterminate case without wrong results. For example, if an
+ optimization is possible if two files are the same but unsafe if
+ distinct, use SAME_INODE()==1; whereas for an optimization that is
+ possible only for distinct files, use !SAME_INODE(). */
+
# define SAME_INODE(Stat_buf_1, Stat_buf_2) \
- ((Stat_buf_1).st_ino == (Stat_buf_2).st_ino \
- && (Stat_buf_1).st_dev == (Stat_buf_2).st_dev)
+ (((Stat_buf_1).st_ino == (Stat_buf_2).st_ino \
+ && (Stat_buf_1).st_dev == (Stat_buf_2).st_dev) \
+ ? 1 - 2 * !(Stat_buf_1).st_ino : 0)
#endif
diff --git a/lib/same.c b/lib/same.c
index af3a95e..5251fb8 100644
--- a/lib/same.c
+++ b/lib/same.c
@@ -1,7 +1,7 @@
/* Determine whether two file names refer to the same file.
- Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006 Free
- Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
+ 2009 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
@@ -97,6 +97,9 @@ same_name (const char *source, const char *dest)
}
same = SAME_INODE (source_dir_stats, dest_dir_stats);
+ if (same < 0)
+ same = (identical_basenames
+ && strcmp (source_basename, dest_basename) == 0);
#if ! _POSIX_NO_TRUNC && HAVE_PATHCONF && defined _PC_NAME_MAX
if (same && ! identical_basenames)
--
1.6.1.2
- mingw and same-inode,
Eric Blake <=