On Mon, Aug 8, 2022 at 8:23 PM <r.zhar...@postgrespro.ru> wrote: > initdb on my windows 10 system stopped working after the commit > c5cb8f3b: "Provide lstat() for Windows." > The error message is: creating directory C:/HOME/data ... initdb: > error: could not create directory "C:/HOME": File exists > > "C:/HOME" is the junction point to the second volume on my hard drive - > "\??\Volume{GUID}\" which name pgreadlink() erroneously strips here: > https://github.com/postgres/postgres/blob/7e29a79a46d30dc236d097825ab849158929d977/src/port/dirmod.c#L357. > So initdb could not stat the file with name "Volume{GUID}", tried to > create it and failed. > With the attached patch initdb works fine again.
- if (r > 4 && strncmp(buf, "\\??\\", 4) == 0) + if (r > 4 && strncmp(buf, "\\??\\", 4) == 0 && + strncmp(buf, "\\??\\Volume", 10) != 0) { memmove(buf, buf + 4, strlen(buf + 4) + 1); r -= 4; Hmm. I suppose the problem must be in pg_mkdir_p(). Our symlink() emulation usually adds this "\??\" prefix (making it an "NT object path"?), because junction points only work if they are in that format. Then our readlink() emulation removes it again, but in the case of your \??\Volume{GUID} path, created by you, not our symlink() emulation, removing "\??\" apparently makes it unopenable with CreateFile() (I guess that's what fails? What's the error?). So your patch just says: don't strip "\??\" if it's followed by "Volume". I don't understand all the kinds of DOS, Windows and NT paths (let me take a moment to say how much I love Unix), but here's a guess: could it be that NT "\??\C:\foo" = DOS "C:\foo", but NT "\??\Volume..." = DOS "\Volume..."? In other words, if it hasn't got a drive letter, maybe it still needs an initial "\" (or if not that, then *something* special, because otherwise it looks like a relative path). Would it be better to say: if it doesn't begin with "\??\X:", where X could be any letter, then don't modify it? Maybe [1] has some clues. It seems to give the info in a higher density form than the Windows docs (at least to the uninitiated like me wanting a quick overview with examples). Hmm, I wonder if we could get away from doing our own path mangling and use some of the proper library calls mentioned on that page... [1] https://googleprojectzero.blogspot.com/2016/02/the-definitive-guide-on-win32-to-nt.html