ntdll: Add a common function to compute file information from the stat data.

This commit is contained in:
Alexandre Julliard 2009-11-18 17:01:15 +01:00
parent 7f5b24ed91
commit c3b602aa23
1 changed files with 120 additions and 125 deletions

View File

@ -1486,6 +1486,79 @@ NTSTATUS WINAPI NtSetVolumeInformationFile(
return 0; return 0;
} }
/* fill in the file information that depends on the stat info */
static NTSTATUS fill_stat_info( const struct stat *st, void *ptr, FILE_INFORMATION_CLASS class )
{
switch (class)
{
case FileBasicInformation:
{
FILE_BASIC_INFORMATION *info = ptr;
if (S_ISDIR(st->st_mode)) info->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
else info->FileAttributes = FILE_ATTRIBUTE_ARCHIVE;
if (!(st->st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
info->FileAttributes |= FILE_ATTRIBUTE_READONLY;
RtlSecondsSince1970ToTime( st->st_mtime, &info->LastWriteTime );
RtlSecondsSince1970ToTime( st->st_ctime, &info->ChangeTime );
RtlSecondsSince1970ToTime( st->st_atime, &info->LastAccessTime );
#ifdef HAVE_STRUCT_STAT_ST_MTIM
info->LastWriteTime.QuadPart += st->st_mtim.tv_nsec / 100;
#endif
#ifdef HAVE_STRUCT_STAT_ST_CTIM
info->ChangeTime.QuadPart += st->st_ctim.tv_nsec / 100;
#endif
#ifdef HAVE_STRUCT_STAT_ST_ATIM
info->LastAccessTime.QuadPart += st->st_atim.tv_nsec / 100;
#endif
info->CreationTime = info->LastWriteTime;
}
break;
case FileStandardInformation:
{
FILE_STANDARD_INFORMATION *info = ptr;
if ((info->Directory = S_ISDIR(st->st_mode)))
{
info->AllocationSize.QuadPart = 0;
info->EndOfFile.QuadPart = 0;
info->NumberOfLinks = 1;
}
else
{
info->AllocationSize.QuadPart = (ULONGLONG)st->st_blocks * 512;
info->EndOfFile.QuadPart = st->st_size;
info->NumberOfLinks = st->st_nlink;
}
}
break;
case FileInternalInformation:
{
FILE_INTERNAL_INFORMATION *info = ptr;
info->IndexNumber.QuadPart = st->st_ino;
}
break;
case FileEndOfFileInformation:
{
FILE_END_OF_FILE_INFORMATION *info = ptr;
info->EndOfFile.QuadPart = S_ISDIR(st->st_mode) ? 0 : st->st_size;
}
break;
case FileAllInformation:
{
FILE_ALL_INFORMATION *info = ptr;
fill_stat_info( st, &info->BasicInformation, FileBasicInformation );
fill_stat_info( st, &info->StandardInformation, FileStandardInformation );
fill_stat_info( st, &info->InternalInformation, FileInternalInformation );
}
break;
default:
return STATUS_INVALID_INFO_CLASS;
}
return STATUS_SUCCESS;
}
static NTSTATUS server_get_unix_name( HANDLE handle, ANSI_STRING *unix_name ) static NTSTATUS server_get_unix_name( HANDLE handle, ANSI_STRING *unix_name )
{ {
data_size_t size = 1024; data_size_t size = 1024;
@ -1625,35 +1698,12 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
switch (class) switch (class)
{ {
case FileBasicInformation: case FileBasicInformation:
{ if (fstat( fd, &st ) == -1)
FILE_BASIC_INFORMATION *info = ptr; io->u.Status = FILE_GetNtStatus();
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
if (fstat( fd, &st ) == -1) io->u.Status = STATUS_INVALID_INFO_CLASS;
io->u.Status = FILE_GetNtStatus(); else
else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) fill_stat_info( &st, ptr, class );
io->u.Status = STATUS_INVALID_INFO_CLASS;
else
{
if (S_ISDIR(st.st_mode)) info->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
else info->FileAttributes = FILE_ATTRIBUTE_ARCHIVE;
if (!(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
info->FileAttributes |= FILE_ATTRIBUTE_READONLY;
RtlSecondsSince1970ToTime( st.st_mtime, &info->CreationTime);
RtlSecondsSince1970ToTime( st.st_mtime, &info->LastWriteTime);
RtlSecondsSince1970ToTime( st.st_ctime, &info->ChangeTime);
RtlSecondsSince1970ToTime( st.st_atime, &info->LastAccessTime);
#ifdef HAVE_STRUCT_STAT_ST_MTIM
info->CreationTime.QuadPart += st.st_mtim.tv_nsec / 100;
info->LastWriteTime.QuadPart += st.st_mtim.tv_nsec / 100;
#endif
#ifdef HAVE_STRUCT_STAT_ST_CTIM
info->ChangeTime.QuadPart += st.st_ctim.tv_nsec / 100;
#endif
#ifdef HAVE_STRUCT_STAT_ST_ATIM
info->LastAccessTime.QuadPart += st.st_atim.tv_nsec / 100;
#endif
}
}
break; break;
case FileStandardInformation: case FileStandardInformation:
{ {
@ -1662,20 +1712,8 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus(); if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
else else
{ {
if ((info->Directory = S_ISDIR(st.st_mode))) fill_stat_info( &st, info, class );
{ info->DeletePending = FALSE; /* FIXME */
info->AllocationSize.QuadPart = 0;
info->EndOfFile.QuadPart = 0;
info->NumberOfLinks = 1;
info->DeletePending = FALSE;
}
else
{
info->AllocationSize.QuadPart = (ULONGLONG)st.st_blocks * 512;
info->EndOfFile.QuadPart = st.st_size;
info->NumberOfLinks = st.st_nlink;
info->DeletePending = FALSE; /* FIXME */
}
} }
} }
break; break;
@ -1688,12 +1726,8 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
} }
break; break;
case FileInternalInformation: case FileInternalInformation:
{ if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
FILE_INTERNAL_INFORMATION *info = ptr; else fill_stat_info( &st, ptr, class );
if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
else info->IndexNumber.QuadPart = st.st_ino;
}
break; break;
case FileEaInformation: case FileEaInformation:
{ {
@ -1702,12 +1736,8 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
} }
break; break;
case FileEndOfFileInformation: case FileEndOfFileInformation:
{ if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
FILE_END_OF_FILE_INFORMATION *info = ptr; else fill_stat_info( &st, ptr, class );
if (fstat( fd, &st ) == -1) io->u.Status = FILE_GetNtStatus();
else info->EndOfFile.QuadPart = S_ISDIR(st.st_mode) ? 0 : st.st_size;
}
break; break;
case FileAllInformation: case FileAllInformation:
{ {
@ -1718,39 +1748,8 @@ NTSTATUS WINAPI NtQueryInformationFile( HANDLE hFile, PIO_STATUS_BLOCK io,
io->u.Status = STATUS_INVALID_INFO_CLASS; io->u.Status = STATUS_INVALID_INFO_CLASS;
else else
{ {
if ((info->StandardInformation.Directory = S_ISDIR(st.st_mode))) fill_stat_info( &st, info, FileAllInformation );
{ info->StandardInformation.DeletePending = FALSE; /* FIXME */
info->BasicInformation.FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
info->StandardInformation.AllocationSize.QuadPart = 0;
info->StandardInformation.EndOfFile.QuadPart = 0;
info->StandardInformation.NumberOfLinks = 1;
info->StandardInformation.DeletePending = FALSE;
}
else
{
info->BasicInformation.FileAttributes = FILE_ATTRIBUTE_ARCHIVE;
info->StandardInformation.AllocationSize.QuadPart = (ULONGLONG)st.st_blocks * 512;
info->StandardInformation.EndOfFile.QuadPart = st.st_size;
info->StandardInformation.NumberOfLinks = st.st_nlink;
info->StandardInformation.DeletePending = FALSE; /* FIXME */
}
if (!(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
info->BasicInformation.FileAttributes |= FILE_ATTRIBUTE_READONLY;
RtlSecondsSince1970ToTime( st.st_mtime, &info->BasicInformation.CreationTime);
RtlSecondsSince1970ToTime( st.st_mtime, &info->BasicInformation.LastWriteTime);
RtlSecondsSince1970ToTime( st.st_ctime, &info->BasicInformation.ChangeTime);
RtlSecondsSince1970ToTime( st.st_atime, &info->BasicInformation.LastAccessTime);
#ifdef HAVE_STRUCT_STAT_ST_MTIM
info->BasicInformation.CreationTime.QuadPart += st.st_mtim.tv_nsec / 100;
info->BasicInformation.LastWriteTime.QuadPart += st.st_mtim.tv_nsec / 100;
#endif
#ifdef HAVE_STRUCT_STAT_ST_CTIM
info->BasicInformation.ChangeTime.QuadPart += st.st_ctim.tv_nsec / 100;
#endif
#ifdef HAVE_STRUCT_STAT_ST_ATIM
info->BasicInformation.LastAccessTime.QuadPart += st.st_atim.tv_nsec / 100;
#endif
info->InternalInformation.IndexNumber.QuadPart = st.st_ino;
info->EaInformation.EaSize = 0; info->EaInformation.EaSize = 0;
info->AccessInformation.AccessFlags = 0; /* FIXME */ info->AccessInformation.AccessFlags = 0; /* FIXME */
info->PositionInformation.CurrentByteOffset.QuadPart = lseek( fd, 0, SEEK_CUR ); info->PositionInformation.CurrentByteOffset.QuadPart = lseek( fd, 0, SEEK_CUR );
@ -2054,10 +2053,10 @@ NTSTATUS WINAPI NtSetInformationFile(HANDLE handle, PIO_STATUS_BLOCK io,
/****************************************************************************** /******************************************************************************
* FILE_QueryFullAttributesFile (internal) * NtQueryFullAttributesFile (NTDLL.@)
*/ */
static NTSTATUS FILE_QueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr, NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
FILE_NETWORK_OPEN_INFORMATION *info ) FILE_NETWORK_OPEN_INFORMATION *info )
{ {
ANSI_STRING unix_name; ANSI_STRING unix_name;
NTSTATUS status; NTSTATUS status;
@ -2073,24 +2072,19 @@ static NTSTATUS FILE_QueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
status = STATUS_INVALID_INFO_CLASS; status = STATUS_INVALID_INFO_CLASS;
else else
{ {
if (S_ISDIR(st.st_mode)) FILE_BASIC_INFORMATION basic;
{ FILE_STANDARD_INFORMATION std;
info->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
info->AllocationSize.QuadPart = 0; fill_stat_info( &st, &basic, FileBasicInformation );
info->EndOfFile.QuadPart = 0; fill_stat_info( &st, &std, FileStandardInformation );
}
else info->CreationTime = basic.CreationTime;
{ info->LastAccessTime = basic.LastAccessTime;
info->FileAttributes = FILE_ATTRIBUTE_ARCHIVE; info->LastWriteTime = basic.LastWriteTime;
info->AllocationSize.QuadPart = (ULONGLONG)st.st_blocks * 512; info->ChangeTime = basic.ChangeTime;
info->EndOfFile.QuadPart = st.st_size; info->AllocationSize = std.AllocationSize;
} info->EndOfFile = std.EndOfFile;
if (!(st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH))) info->FileAttributes = basic.FileAttributes;
info->FileAttributes |= FILE_ATTRIBUTE_READONLY;
RtlSecondsSince1970ToTime( st.st_mtime, &info->CreationTime );
RtlSecondsSince1970ToTime( st.st_mtime, &info->LastWriteTime );
RtlSecondsSince1970ToTime( st.st_ctime, &info->ChangeTime );
RtlSecondsSince1970ToTime( st.st_atime, &info->LastAccessTime );
if (DIR_is_hidden_file( attr->ObjectName )) if (DIR_is_hidden_file( attr->ObjectName ))
info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN; info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
} }
@ -2100,15 +2094,6 @@ static NTSTATUS FILE_QueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
return status; return status;
} }
/******************************************************************************
* NtQueryFullAttributesFile (NTDLL.@)
*/
NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
FILE_NETWORK_OPEN_INFORMATION *info )
{
return FILE_QueryFullAttributesFile( attr, info );
}
/****************************************************************************** /******************************************************************************
* NtQueryAttributesFile (NTDLL.@) * NtQueryAttributesFile (NTDLL.@)
@ -2116,17 +2101,27 @@ NTSTATUS WINAPI NtQueryFullAttributesFile( const OBJECT_ATTRIBUTES *attr,
*/ */
NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC_INFORMATION *info ) NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC_INFORMATION *info )
{ {
FILE_NETWORK_OPEN_INFORMATION full_info; ANSI_STRING unix_name;
NTSTATUS status; NTSTATUS status;
if (!(status = FILE_QueryFullAttributesFile( attr, &full_info ))) if (!(status = wine_nt_to_unix_file_name( attr->ObjectName, &unix_name, FILE_OPEN,
!(attr->Attributes & OBJ_CASE_INSENSITIVE) )))
{ {
info->CreationTime.QuadPart = full_info.CreationTime.QuadPart; struct stat st;
info->LastAccessTime.QuadPart = full_info.LastAccessTime.QuadPart;
info->LastWriteTime.QuadPart = full_info.LastWriteTime.QuadPart; if (stat( unix_name.Buffer, &st ) == -1)
info->ChangeTime.QuadPart = full_info.ChangeTime.QuadPart; status = FILE_GetNtStatus();
info->FileAttributes = full_info.FileAttributes; else if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
status = STATUS_INVALID_INFO_CLASS;
else
{
status = fill_stat_info( &st, info, FileBasicInformation );
if (DIR_is_hidden_file( attr->ObjectName ))
info->FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
}
RtlFreeAnsiString( &unix_name );
} }
else WARN("%s not found (%x)\n", debugstr_us(attr->ObjectName), status );
return status; return status;
} }