Skip to content

Commit

Permalink
mingw: fail with errno == ENOTDIR when appropriate
Browse files Browse the repository at this point in the history
POSIX semantics requires lstat() to fail with ENOTDIR when "[a]
component of the path prefix names an existing file that is neither a
directory nor a symbolic link to a directory".

See http://pubs.opengroup.org/onlinepubs/9699919799/functions/lstat.html

This behavior is expected by t1404-update-ref-df-conflicts now.

Signed-off-by: Johannes Schindelin <[email protected]>
  • Loading branch information
dscho committed Jun 11, 2015
1 parent 04db96a commit 731fe28
Showing 1 changed file with 39 additions and 0 deletions.
39 changes: 39 additions & 0 deletions compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,39 @@ int mingw_chmod(const char *filename, int mode)
return _wchmod(wfilename, mode);
}

/**
* Verifies that safe_create_leading_directories() would succeed.
*/
static int has_valid_directory_prefix(wchar_t *wfilename)
{
int n = wcslen(wfilename);

while (n > 0) {
wchar_t c = wfilename[--n];
DWORD attributes;

if (!is_dir_sep(c))
continue;

wfilename[n] = L'\0';
attributes = GetFileAttributesW(wfilename);
wfilename[n] = c;
if (attributes == FILE_ATTRIBUTE_DIRECTORY ||
attributes == FILE_ATTRIBUTE_DEVICE)
return 1;
if (attributes == INVALID_FILE_ATTRIBUTES)
switch (GetLastError()) {
case ERROR_PATH_NOT_FOUND:
continue;
case ERROR_FILE_NOT_FOUND:
/* This implies parent directory exists. */
return 1;
}
return 0;
}
return 1;
}

int mingw_lstat(const char *file_name, struct stat *buf)
{
WIN32_FILE_ATTRIBUTE_DATA fdata;
Expand Down Expand Up @@ -687,6 +720,12 @@ int mingw_lstat(const char *file_name, struct stat *buf)
case ERROR_NOT_ENOUGH_MEMORY:
errno = ENOMEM;
break;
case ERROR_PATH_NOT_FOUND:
if (!has_valid_directory_prefix(wfilename)) {
errno = ENOTDIR;
break;
}
/* fallthru */
default:
errno = ENOENT;
break;
Expand Down

0 comments on commit 731fe28

Please sign in to comment.