blob: 3313414f24ef6eae9854fc344128bc89f15ad110 [file] [log] [blame] [raw]
/* A part of the Native C Library for Windows NT
Copyright 2007-2015 PC GO Ld.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*/
#include <sys/stat.h>
#include <windows.h>
#include <nt.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <wchar.h>
#include <stdio.h>
static int fstat_f(int fd, struct stat *st) {
FILE_BASIC_INFORMATION fbi;
FILE_STANDARD_INFORMATION fsi;
FILE_INTERNAL_INFORMATION fii;
IO_STATUS_BLOCK io_status;
long int status1 = NtQueryInformationFile((void *)fd, &io_status, &fbi, sizeof fbi, FileBasicInformation);
//printf("nativelibc debug: fstat: status1 = 0x%lx\n", status1);
//if(__set_errno_from_ntstatus(status)) return -1;
st->st_mode = S_IREAD | S_IEXEC;
if(status1 >= 0) {
unsigned long int t;
st->st_ctime = RtlTimeToSecondsSince1970(&fbi.ChangeTime, &t) ? t : 0;
st->st_mtime = RtlTimeToSecondsSince1970(&fbi.LastWriteTime, &t) ? t : 0;
st->st_atime = RtlTimeToSecondsSince1970(&fbi.LastAccessTime, &t) ? t : 0;
//st->st_mode = 0777;
//if(fbi.FileAttributes & FILE_ATTRIBUTE_READONLY) st->st_mode &= ~0222;
if(!(fbi.FileAttributes & FILE_ATTRIBUTE_READONLY)) st->st_mode |= S_IWRITE;
//printf("nativelibc debug: fstat: fbi.FileAttributes = 0x%lx\n", fbi.FileAttributes);
//if(st->st_ctime) printf("ctime = %lu\n", (unsigned long int)st->st_ctime);
}
long int status2 = NtQueryInformationFile((void *)fd, &io_status, &fsi, sizeof fsi, FileStandardInformation);
//printf("nativelibc debug: fstat: status2 = 0x%lx\n", status2);
if(__set_errno_from_ntstatus(status2)) {
if(status1 < 0) return -1;
st->st_blocks = 0;
st->st_size = 0;
st->st_rdev = 0;
st->st_gid = 0;
st->st_uid = 0;
st->st_nlink = 1;
} else {
if(status1 < 0) {
st->st_ctime = 0;
st->st_mtime = 0;
st->st_atime = 0;
}
st->st_blocks = fsi.AllocationSize.QuadPart / 512;
st->st_size = fsi.EndOfFile.QuadPart;
st->st_rdev = 0;
st->st_gid = 0;
st->st_uid = 0;
st->st_nlink = fsi.NumberOfLinks;
st->st_mode |= fsi.Directory ? S_IFDIR : S_IFREG;
}
st->st_dev = 0;
long int status3 = NtQueryInformationFile((void *)fd, &io_status, &fii, sizeof fii, FileInternalInformation);
//printf("nativelibc debug: fstat: status3 = 0x%lx\n", status3);
if(__set_errno_from_ntstatus(status3)) st->st_ino = 0;
else st->st_ino = fii.IndexNumber.QuadPart;
return 0;
}
static int fstat_do(int fd, struct stat *st) {
OBJECT_BASIC_INFORMATION obi;
long int status = NtQueryObject((void *)fd, ObjectBasicInformation, &obi, sizeof obi, NULL);
if(status < 0) {
__set_errno_from_ntstatus(status);
return -1;
}
unsigned long int t;
st->st_mode = 0777 | S_IFDIR;
st->st_ctime = RtlTimeToSecondsSince1970(&obi.CreateTime, &t) ? t : 0;
st->st_mtime = 0;
st->st_atime = 0;
st->st_blocks = 0;
st->st_size = 0;
st->st_rdev = 0;
st->st_gid = 0;
st->st_uid = 0;
st->st_nlink = 1;
st->st_ino = 0;
return 0;
}
static int fstat_sl(int fd, struct stat *st) {
OBJECT_BASIC_INFORMATION obi;
long int status = NtQueryObject((void *)fd, ObjectBasicInformation, &obi, sizeof obi, NULL);
if(status < 0) {
__set_errno_from_ntstatus(status);
return -1;
}
unsigned long int t;
st->st_mode = 0777 | S_IFLNK;
st->st_ctime = RtlTimeToSecondsSince1970(&obi.CreateTime, &t) ? t : 0;
st->st_mtime = 0;
st->st_atime = 0;
st->st_blocks = 0;
st->st_size = 0;
st->st_rdev = 0;
st->st_gid = 0;
st->st_uid = 0;
st->st_nlink = 1;
st->st_ino = 0;
return 0;
}
int fstat(int fd, struct stat *st) {
//printf("function: fstat(%d, %p)\n", fd, st);
if(!st) {
errno = EFAULT;
return -1;
}
//OBJECT_TYPE_INFORMATION oti;
size_t oti_size = sizeof(OBJECT_TYPE_INFORMATION) + 256;
OBJECT_TYPE_INFORMATION *oti = malloc(oti_size);
if(!oti) return -1;
long int status = NtQueryObject((void *)fd, ObjectTypeInformation, oti, oti_size, NULL);
//printf("nativelibc debug: fstat: status = 0x%lx\n", status);
if(status < 0) {
free(oti);
__set_errno_from_ntstatus(status);
return -1;
}
//printf("TypeName: ");
//NtDisplayString(&oti->TypeName);
//putchar('\n');
//printf("PoolType: %lu\n", oti->PoolType);
#if 0
// ==========TESTING==========
OBJECT_BASIC_INFORMATION obi;
status = NtQueryObject((void *)fd, ObjectBasicInformation, &obi, sizeof obi, NULL);
//printf("nativelibc debug: fstat: status = 0x%lx\n", status);
if(status >= 0) {
unsigned long int t;
printf("Attributes = 0x%lx\n"
"GrantedAccess = 0x%lx\n"
"NameInformationLength = %lu\n"
"TypeInformationLength = %lu\n",
obi.Attributes,
obi.GrantedAccess,
obi.NameInformationLength,
obi.TypeInformationLength);
if(RtlTimeToSecondsSince1970(&obi.CreateTime, &t)) printf("\nctime = %lu\n", t);
}
putchar('\n');
// ==========TESTING==========
#endif
int r = -1;
if(wcscmp(oti->TypeName.Buffer, L"File") == 0) r = fstat_f(fd, st);
else if(wcscmp(oti->TypeName.Buffer, L"Directory") == 0) r = fstat_do(fd, st);
else if(wcscmp(oti->TypeName.Buffer, L"SymbolicLink") == 0) r = fstat_sl(fd, st);
else errno = ENOSYS;
free(oti);
return r;
}
int stat(const char *path, struct stat *st) {
if(!path || !st) {
errno = EFAULT;
return -1;
}
if(!*path) {
errno = ENOENT;
return -1;
}
int fd = open(path, O_RDONLY);
if(fd == -1) return -1;
/*
if(fd == -1) {
if(errno != EISDIR) return -1;
fd = open(path, O_DIRECTORY);
//printf("nativelibc debug: stat: fd = %d\n", fd);
if(fd == -1) return -1;
}*/
int r = fstat(fd, st);
int e = errno;
close(fd);
errno = e;
return r;
}
int lstat(const char *path, struct stat *st) {
if(!path || !st) {
errno = EFAULT;
return -1;
}
if(!*path) {
errno = ENOENT;
return -1;
}
int fd = open(path, O_RDONLY | O_NOFOLLOW);
if(fd == -1) return -1;
/*
if(fd == -1) {
perror("nativelibc debug");
if(errno != EISDIR) return -1;
fd = open(path, O_DIRECTORY | O_NOFOLLOW);
//printf("nativelibc debug: stat: fd = %d\n", fd);
if(fd == -1) return -1;
}*/
int r = fstat(fd, st);
int e = errno;
close(fd);
errno = e;
return r;
}