Re: Versioning configuration files on a server: fatal: Unable to create '//etc/.git/index.lock': No such file or directory

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi folks,

> > I think 490544b (get_cwd_relative(): do not misinterpret suffix as
> > subdirectory - 2010-05-22) causes it. Haven't fully understood what's
> > going on in that function though :P
> Seems you're right. I just reverted this commit and the problem seems to
> go away.
A bit more gdb'ing with -O0, I found the following. get_cwd_relative is
called with dir="/". The cwd is "/etc". The stack looks like:

#0  get_relative_cwd (buffer=0x7a44c0 "/etc", size=4096, dir=0x7b1041 "") at dir.c:961
#1  0x00000000004dfdf1 in setup_git_directory () at setup.c:612
#2  0x0000000000404f69 in run_builtin (p=0x75ea10, argc=2, argv=0x7fffffffc918) at git.c:257
#3  0x00000000004051e3 in handle_internal_command (argc=2, argv=0x7fffffffc918) at git.c:431
#4  0x000000000040538a in main (argc=2, argv=0x7fffffffc918) at git.c:516

After the following code runs:

    while (*dir && *dir == *cwd) {
	    dir++; 
	    cwd++;
    }

I have dir="" and cwd="etc". Then the following code runs:

    switch (*cwd) {
    case '\0':
	    return cwd;
    case '/':
	    return cwd + 1;
    default:
	    return NULL;
    }

Since *cwd='e', it returns NULL.

The old code (before 490544b) was:

   if (*cwd == '/')
	   return cwd + 1;
   return cwd;

So this would return "etc".


So, that's what is happens. I think this happens because
get_relative_cwd expects dir to not contain a trailing slash. Normally,
there is no trailing slash, but in the special case of dir="/" there is
(sort of) a trailing slash.

I'm not completely sure how to fix this. Looking at 72ec8ba (Support
working directory located at root - 2010-02-14), perhaps something like
this?

diff --git a/dir.c b/dir.c
index d1e5e5e..5408db9 100644
--- a/dir.c
+++ b/dir.c
@@ -943,6 +943,7 @@ int file_exists(const char *f)
 char *get_relative_cwd(char *buffer, int size, const char *dir)
 {
        char *cwd = buffer;
+       size_t len, root_len;
 
        if (!dir)
                return NULL;
@@ -952,6 +953,15 @@ char *get_relative_cwd(char *buffer, int size, const char *dir)
        if (!is_absolute_path(dir))
                dir = make_absolute_path(dir);
 
+       len = strlen(dir);
+       root_len = offset_1st_component(dir);
+
+       if (root_len >= len) {
+           /* dir is the filesystem root, so the cwd is always inside */
+           root_len = offset_1st_component(cwd);
+           return cwd + root_len;
+       }
+
        while (*dir && *dir == *cwd) {
                dir++;
                cwd++;

I'm not sure how this stuff really works, though. I think this works for *nix,
but I'm unsure about Windows.

Gr.

Matthijs

Attachment: signature.asc
Description: Digital signature


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]