{"thread":{"id":"29532","subject":"Problem pushing to a Novell share","startedAt":"2012-02-02T22:54:44Z","lastAt":"2012-02-03T19:33:27Z","messageCount":4,"participants":["Rüdiger Kessel","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"183677","messageId":"CAJ4nRM0-3GWN=OYOXDdGtktU0mc8mhcoKqbo=U4Jm5AmSbPAyQ@mail.gmail.com","threadId":"29532","inReplyTo":null,"subject":"Problem pushing to a Novell share","fromName":"Rüdiger Kessel","fromEmail":"ruediger.kessel@gmail.com","sentAt":"2012-02-02T22:54:44Z","receivedAt":"2012-02-02T22:54:44Z","isPatch":false,"sender":{"key":"ruediger.kessel@gmail.com","avatar":null},"body":"Hi\n\na push to an .git-repository on a Novell network-share using msysgit\nfails with the following error message:\n\nerror: unable to create temporary sha1 filename : File exists\n\nThe problem has been found in git version 1.7.9\n\nThe problem is caused by a non-existing sub-directory in the file path\nwhich is not automatically created on Novell shares.\n\nA quick fix is to improve the create_tmpfile() function in sha1_file.c:\n\nstatic int create_tmpfile(char *buffer, size_t bufsiz, const char *filename)\n{\n    static struct stat sb;\n    int fd, dirlen = directory_size(filename);\n\n    if (dirlen + 20 > bufsiz) {\n        errno = ENAMETOOLONG;\n        return -1;\n    }\n\n    memcpy(buffer, filename, dirlen);\n    buffer[dirlen-1] = 0;\n    if (stat(buffer, &sb) != 0 && errno == ENOENT) {\n        if (mkdir(buffer, 0777) || adjust_shared_perm(buffer))\n            return -1;\n    }\n\n    memcpy(buffer, filename, dirlen);\n    strcpy(buffer + dirlen, \"tmp_obj_XXXXXX\");\n    fd = git_mkstemp_mode(buffer, 0444);\n    return fd;\n}\n\nThe function will create one missing directory level if it does not\nexist prior to creating the tmp-file.\n\nThis method seems to work, but it works only if one directory level is\nmissing which might not be the case in general. A better solution\nwould be to create the whole directory tree if needed.\n\nThe best solution would be if MINGW would handle this issue.\n\nI recommend including this patch into GIT since it does no harm on\nposix systems but it improves compatibility on others.\n\nRüdiger\n"},{"id":"183679","messageId":"7vmx90vlyr.fsf@alter.siamese.dyndns.org","threadId":"29532","inReplyTo":"CAJ4nRM0-3GWN=OYOXDdGtktU0mc8mhcoKqbo=U4Jm5AmSbPAyQ@mail.gmail.com","subject":"Re: Problem pushing to a Novell share","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-02T23:45:16Z","receivedAt":"2012-02-02T23:45:16Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Rüdiger Kessel <ruediger.kessel@gmail.com> writes:\n\n> A quick fix is to improve the create_tmpfile() function in sha1_file.c:\n>\n> static int create_tmpfile(char *buffer, size_t bufsiz, const char *filename)\n> {\n>     static struct stat sb;\n>     int fd, dirlen = directory_size(filename);\n>\n>     if (dirlen + 20 > bufsiz) {\n>         errno = ENAMETOOLONG;\n>         return -1;\n>     }\n>\n>     memcpy(buffer, filename, dirlen);\n>     buffer[dirlen-1] = 0;\n>     if (stat(buffer, &sb) != 0 && errno == ENOENT) {\n>         if (mkdir(buffer, 0777) || adjust_shared_perm(buffer))\n>             return -1;\n>     }\n>\n>     memcpy(buffer, filename, dirlen);\n>     strcpy(buffer + dirlen, \"tmp_obj_XXXXXX\");\n>     fd = git_mkstemp_mode(buffer, 0444);\n>     return fd;\n> }\n>\n> The function will create one missing directory level if it does not\n> exist prior to creating the tmp-file.\n\nPlease remove your modification above, and follow the code we have.  We\ntry git_mkstemp_mode() first, because it is more common than not having\nthe leading directory and we do not want to waste an extra stat() every\ntie we come here.  Only when the first attempt fails by returning error\n(i.e. fd < 0 and errno == ENOENT), we try mkdir() and then try again.\n\nIf you see \"missing directory\", it would be because on your system the\ncode somehow does not notice the failure from the first attempt.  Why?\n\nThe breakage you are seeing could come from either:\n\n - git_mkstemp_mode(), more specifically, the underlying mkstemp(), not\n   returning negative when it fails for some reason; or\n\n - when the above fails, it fails to set errno to ENOENT.\n\nand *that* is what needs to be fixed.\n\nI think pessimizing create_tmpfile() like you did is not a fix; it is\nsweeping the real problem under the rug.\n"},{"id":"183689","messageId":"7vfwesu2ma.fsf@alter.siamese.dyndns.org","threadId":"29532","inReplyTo":"CAJ4nRM1K=sCy8_0PG-NADVn4T0XG1ELC7AvtQyW-Dc1cUMzEXQ@mail.gmail.com","subject":"Re: Problem pushing to a Novell share","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-03T01:28:29Z","receivedAt":"2012-02-03T01:28:29Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Rüdiger Kessel <ruediger.kessel@gmail.com> writes:\n\n> Trying git_mkstemp_mode() first means trying more 16000 times to create a\n> random file before realizing that something might be wrong.\n\nWell, git_mkstemps_mode() does have such a 16k loop, and it tries to\ncreate a unique, unused file this way:\n\n\t\tfd = open(pattern, O_CREAT | O_EXCL | O_RDWR, mode);\n\t\tif (fd > 0)\n\t\t\treturn fd;\n\t\t/*\n\t\t * Fatal error (EPERM, ENOSPC etc).\n\t\t * It doesn't make sense to loop.\n\t\t */\n\t\tif (errno != EEXIST)\n\t\t\tbreak;\n\nIf you do not have a directory D and try to create D/tmp_random here,\nshouldn't you get an error that is _NOT_ EEXIST and trigger this break?\n"},{"id":"183750","messageId":"7vipjnpv94.fsf@alter.siamese.dyndns.org","threadId":"29532","inReplyTo":"CAJ4nRM2+u9OcLgJBN7+_rv1OiXETGNhozAfvYtj=hVNTfCMxhQ@mail.gmail.com","subject":"Re: Problem pushing to a Novell share","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-02-03T19:33:27Z","receivedAt":"2012-02-03T19:33:27Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"[jc: just forwarding to the list --- the msysgit list might have been a\nbetter place to forward to, but I know msysgit folks read this list too,\nso...]\n\nRüdiger Kessel <ruediger.kessel@gmail.com> writes:\n\nI have confimed that it is not a mingw problem. Direct calls to\nCreateFile() in kernel32.dll show the same behaviour.\n\nOn a Novel share I get Error 80 \"File exists\" if a directory does not\nexist, while I get Error 3 \"Path not found\" on a local drive\n\n2012/2/3 Rüdiger Kessel <ruediger.kessel@gmail.com>:\n Well, it is a Novell bug, but what can we do?\n\n I studied it in detail and open() sets errno=EEXIST if the directory\n is missing on a Novell share causing git_mkstemp_mode looping 16k\n times and never creates the dir.\n\n The correct errno would be ENOENT, but that not what the systems is sending.\n\n So it is either using stat on the directory before trying to create\n the tmp-file or GIT cannot be used with Novell shares. What is it\n going to be?\n\n Protocolling the mkdir error handling I saw that git creates quite a\n number of new directories this way. Therefore my pessimistic approach\n might be too costly at the end.\n"}]}