Package: git-core
Severity: important
Tags: patch

Hi!

When trying to build your package on hurd-i386, the following error is
raised:
> gcc -o checkout-index.o -c -g -Wall -O2 -DNO_OPENSSL
> -DSHA1_HEADER='"mozilla-sha1/sha1.h"'  checkout-index.c
> In file included from checkout-index.c:39:
> cache.h:172: error: 'PATH_MAX' undeclared here (not in a function)
> make[1]: *** [checkout-index.o] Error 1
> make[1]: Leaving directory `/home/kibi/build/git-core-1.4.1'
> make: *** [build-arch-stamp] Error 2

As briefly explained on the hurd-devel-debian page[1], unconditional use
of PATH_MAX is a POSIX incompatibility. Due to the number of occurrences
of it in the source code (`grep PATH_MAX * | wc -l` reports 80), I guess
that a workaround will be sufficient, at least at the moment. Another
justification for using this workaround is that the same one is already
used for MAXPATHLEN (see the context in PATH_MAX.diff).

 1. http://www.debian.org/ports/hurd/hurd-devel-debian


A second problem is that GNU(/Hurd) is not detected by the Makefile;
that's solved with the second patch I join, Makefile-GNU.diff.


The last but not least problem resides in read-cache.c. In IS_ERR, an
assumption is made: ENOENT, EINVAL and all error codes (errno) of
the function 'lstat' are lower (in absolute value) than 1000, which is
the case on many arch (e.g. on Linux) but that's not the case on Hurd.
You may have a look at the file 'errno-hurd.log' that I also join, which
provides a sample program and its result on both Hurd & Linux platform.

In the last patch I hereby submit, I try to solve the strange error
handling by using a switch on the error codes that can be encountered
(either direct affectations, or errno set by lstat), but that doesn't
guarantee that _correct_ affected items won't have an address matching
an error code... That patch (error_handling.diff) has been tested on
both hurd and linux arch, and allows git-core to pass the testsuite on
both (whereas without it, the testsuite fails on hurd).

I agree that this patch doesn't solve all the problems that can be
encountered, but at least a great part. I guess that a correct error
handling using a variable (e.g. acting as a flag or as another
generalized errno) should be developed to ensure portability and
robustness.


As a quick reminder, summary of attached files:
 - PATH_MAX.diff: solves POSIX incompatibily
 - Makefile-GNU.diff: enables GNU detection, turns on NO_STRLCPY
 - errno-hurd.log: displays why IS_ERR doesn't play its role on hurd
 - error_handling.diff: fixes error handling as it can

The three .diff files can be dropped directly in debian/diff (once
reviewed), the package construction has been checked on both linux-i386
and hurd-i386.


Cheers,

-- 
Cyril Brulebois
--- a/git-compat-util.h.orig    2006-07-22 14:44:14.000000000 +0000
+++ b/git-compat-util.h 2006-07-22 14:54:21.000000000 +0000
@@ -165,4 +165,8 @@
 #ifndef MAXPATHLEN
 #define MAXPATHLEN 256
 #endif
+
+#ifndef PATH_MAX
+#define PATH_MAX 4096
+#endif
 #endif
--- a/Makefile  2006-07-25 14:00:48.000000000 +0000
+++ b/Makefile  2006-07-25 14:02:07.000000000 +0000
@@ -327,6 +327,10 @@
        # for now, build 32-bit version
        ALL_LDFLAGS += -L/usr/lib32
 endif
+ifeq ($(uname_S),GNU)
+       # GNU stands for GNU/Hurd
+       NO_STRLCPY=YesPlease
+endif
 ifneq (,$(findstring arm,$(uname_M)))
        ARM_SHA1 = YesPlease
 endif
/*  Sample program  */


[EMAIL PROTECTED]:~/build/debug$ cat einval.c
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {

        /* Taken from read-cache.c directly */
        printf("EINVAL : %d\n", EINVAL);
        printf("ENOENT : %d\n", ENOENT);
        printf("EBUSY  : %d\n", EBUSY );

        /* Taken from lstat(2) */
        printf("EACCES : %d\n",  EACCES );
        printf("EBADF  : %d\n", EBADF  );
        printf("EFAULT : %d\n", EFAULT );
        printf("ELOOP  : %d\n", ELOOP  );
        printf("ENOENT : %d\n", ENOENT );
        printf("ENOMEM : %d\n", ENOMEM );
        printf("ENOTDIR: %d\n", ENOTDIR);

        return 0;
}



/*  HURD-box  */


[EMAIL PROTECTED]:~/build/debug$ make test
gcc -o einval einval.c
./einval
EINVAL : 1073741846
ENOENT : 1073741826
EBUSY  : 1073741840
EACCES : 1073741837
EBADF  : 1073741833
EFAULT : 1073741838
ELOOP  : 1073741886
ENOENT : 1073741826
ENOMEM : 1073741836
ENOTDIR: 1073741844



/*  LINUX-box  */

[EMAIL PROTECTED]:~$ make test
gcc -o einval einval.c
./einval
EINVAL : 22
ENOENT : 2
EBUSY  : 16
EACCES : 13
EBADF  : 9
EFAULT : 14
ELOOP  : 40
ENOENT : 2
ENOMEM : 12
ENOTDIR: 20

--- a/read-cache.c	2006-07-25 03:09:56.000000000 +0000
+++ b/read-cache.c	2006-07-25 03:05:05.000000000 +0000
@@ -590,7 +593,28 @@
 
 static inline long IS_ERR(const void *ptr)
 {
-	return (unsigned long)ptr > (unsigned long)-1000L;
+	switch ((unsigned long)ptr) {
+
+	/* Called directly */
+	case    (unsigned long)-EINVAL :
+	case    (unsigned long)-ENOENT :
+
+	/* One never knows... */
+	case    (unsigned long)-EBUSY  :
+
+	/* lstat() [ENOENT not repeated] */
+	/* We should also support other less common errors, see man 2 lstat */
+	case    (unsigned long)-EACCES :
+	case    (unsigned long)-EBADF  :
+	case    (unsigned long)-EFAULT :
+	case    (unsigned long)-ELOOP  :
+	case    (unsigned long)-ENOMEM :
+	case    (unsigned long)-ENOTDIR:
+		return 1; /* This is an error */
+
+	default:
+		return 0; /* This is not an error */
+	}
 }
 
 /*
@@ -610,6 +634,7 @@
 	struct cache_entry *updated;
 	int changed, size;
 
+	/* BE CAREFUL with this errno! */
 	if (lstat(ce->name, &st) < 0)
 		return ERR_PTR(-errno);
 

Reply via email to