static int winfs_stat(struct file *f, struct newstat *buf) { struct winfs_file *winfile = (struct winfs_file *) f; BY_HANDLE_FILE_INFORMATION info; if (!GetFileInformationByHandle(winfile->handle, &info)) { log_warning("GetFileInformationByHandle() failed.\n"); return -1; /* TODO */ } /* Programs (ld.so) may use st_dev and st_ino to identity files so these must be unique for each file. */ INIT_STRUCT_NEWSTAT_PADDING(buf); buf->st_dev = mkdev(8, 0); // (8, 0): /dev/sda //buf->st_ino = ((uint64_t)info.nFileIndexHigh << 32ULL) + info.nFileIndexLow; /* Hash 64 bit inode to 32 bit to fix legacy applications * We may later add an option for changing this behaviour */ buf->st_ino = info.nFileIndexHigh ^ info.nFileIndexLow; if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) buf->st_mode = 0555; else buf->st_mode = 0755; if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { buf->st_mode |= S_IFDIR; buf->st_size = 0; } else { int r; if ((info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) && (r = winfs_read_symlink(winfile->handle, NULL, 0)) > 0) { buf->st_mode |= S_IFLNK; buf->st_size = r; } else { buf->st_mode |= S_IFREG; buf->st_size = ((uint64_t)info.nFileSizeHigh << 32ULL) + info.nFileSizeLow; } } buf->st_nlink = info.nNumberOfLinks; buf->st_uid = 0; buf->st_gid = 0; buf->st_rdev = 0; buf->st_blksize = PAGE_SIZE; buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / buf->st_blksize; buf->st_atime = filetime_to_unix_sec(&info.ftLastAccessTime); buf->st_atime_nsec = filetime_to_unix_nsec(&info.ftLastAccessTime); buf->st_mtime = filetime_to_unix_sec(&info.ftLastWriteTime); buf->st_mtime_nsec = filetime_to_unix_nsec(&info.ftLastWriteTime); buf->st_ctime = filetime_to_unix_sec(&info.ftCreationTime); buf->st_ctime_nsec = filetime_to_unix_nsec(&info.ftCreationTime); return 0; }
static int winfs_stat(struct file *f, struct newstat *buf) { AcquireSRWLockShared(&f->rw_lock); struct winfs_file *winfile = (struct winfs_file *) f; BY_HANDLE_FILE_INFORMATION info; GetFileInformationByHandle(winfile->handle, &info); /* Programs (ld.so) may use st_dev and st_ino to identity files so these must be unique for each file. */ INIT_STRUCT_NEWSTAT_PADDING(buf); buf->st_dev = mkdev(8, 0); // (8, 0): /dev/sda //buf->st_ino = ((uint64_t)info.nFileIndexHigh << 32ULL) + info.nFileIndexLow; /* Hash 64 bit inode to 32 bit to fix legacy applications * We may later add an option for changing this behaviour */ buf->st_ino = info.nFileIndexHigh ^ info.nFileIndexLow; if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) buf->st_mode = 0555; else buf->st_mode = 0755; if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { buf->st_mode |= S_IFDIR; buf->st_size = 0; } else { buf->st_mode |= S_IFREG; buf->st_size = ((uint64_t)info.nFileSizeHigh << 32ULL) + info.nFileSizeLow; if (info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) { WaitForSingleObject(winfile->fp_mutex, INFINITE); /* Save current file pointer */ LARGE_INTEGER distanceToMove, currentFilePointer; distanceToMove.QuadPart = 0; SetFilePointerEx(winfile->handle, distanceToMove, ¤tFilePointer, FILE_CURRENT); int type = winfs_get_special_file_type(winfile->handle); if (type > 0) { if (type == SPECIAL_FILE_SYMLINK) { buf->st_mode |= S_IFLNK; buf->st_size -= WINFS_SYMLINK_HEADER_LEN; } else if (type == SPECIAL_FILE_SOCKET) { buf->st_mode |= S_IFSOCK; buf->st_size = 0; } } /* Restore current file pointer */ SetFilePointerEx(winfile->handle, currentFilePointer, ¤tFilePointer, FILE_BEGIN); ReleaseMutex(winfile->fp_mutex); } } buf->st_nlink = info.nNumberOfLinks; buf->st_uid = 0; buf->st_gid = 0; buf->st_rdev = 0; buf->st_blksize = PAGE_SIZE; buf->st_blocks = (buf->st_size + buf->st_blksize - 1) / buf->st_blksize; buf->st_atime = filetime_to_unix_sec(&info.ftLastAccessTime); buf->st_atime_nsec = filetime_to_unix_nsec(&info.ftLastAccessTime); buf->st_mtime = filetime_to_unix_sec(&info.ftLastWriteTime); buf->st_mtime_nsec = filetime_to_unix_nsec(&info.ftLastWriteTime); buf->st_ctime = filetime_to_unix_sec(&info.ftCreationTime); buf->st_ctime_nsec = filetime_to_unix_nsec(&info.ftCreationTime); ReleaseSRWLockShared(&f->rw_lock); return 0; }