| /* 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 <stdio.h> |
| |
| 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_len = sizeof(OBJECT_TYPE_INFORMATION) + 256; |
| OBJECT_TYPE_INFORMATION *oti = malloc(oti_len); |
| long int status = NtQueryObject((void *)fd, ObjectTypeInformation, oti, oti_len, NULL); |
| printf("nativelibc debug: fstat: status = 0x%lx\n", status); |
| if(status >= 0) { |
| printf("TypeName: "); |
| NtDisplayString(&oti->TypeName); |
| putchar('\n'); |
| printf("PoolType: %lu\n", oti->PoolType); |
| } |
| free(oti); |
| |
| size_t oni_len = sizeof(OBJECT_NAME_INFORMATION) + 256; |
| OBJECT_NAME_INFORMATION *oni = malloc(oni_len); |
| status = NtQueryObject((void *)fd, ObjectNameInformation, oni, oni_len, NULL); |
| printf("nativelibc debug: fstat: status = 0x%lx\n", status); |
| if(status >= 0) { |
| printf("Name: "); |
| NtDisplayString(&oni->Name); |
| putchar('\n'); |
| } |
| free(oni); |
| |
| 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'); |
| } |
| |
| 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(ntstatus_to_errno(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); |
| if(ntstatus_to_errno(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; |
| //printf("nativelibc debug: fsi.Directory = %hhu\n", fsi.Directory); |
| //if(fsi.Directory) st->st_mode |= S_IFDIR; |
| st->st_mode |= fsi.Directory ? S_IFDIR : S_IFREG; |
| } |
| //if(!(fbi.FileAttributes & FILE_ATTRIBUTE_READONLY)) st->st_mode |= S_IWRITE; |
| st->st_dev = 0; |
| long int status3 = NtQueryInformationFile((void *)fd, &io_status, &fii, sizeof fii, FileInternalInformation); |
| if(ntstatus_to_errno(status3)) st->st_ino = 0; |
| else st->st_ino = fii.IndexNumber.QuadPart; |
| return 0; |
| } |
| |
| 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) { |
| 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) { |
| 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; |
| } |