| /* 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; |
| } |