/* * Copyright 2025, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. */ #include #include #include "Context.h" #include "MemoryReader.h" #include "strace.h" #include "Syscall.h" #include "TypeHandler.h" #include "util.h" static string format_mode(Context &context, mode_t mode) { if (context.GetContents(Context::ENUMERATIONS)) { #define MODE_TYPE(mode) \ case mode: \ return #mode switch (mode) { MODE_TYPE(S_IFSOCK); MODE_TYPE(S_IFLNK); MODE_TYPE(S_IFREG); MODE_TYPE(S_IFBLK); MODE_TYPE(S_IFDIR); MODE_TYPE(S_IFIFO); MODE_TYPE(S_IFCHR); } } return context.FormatSigned(mode); } static string read_stat(Context &context, Parameter *param, void *data) { int statMask = 0xffffffff; if (param->Out()) { if ((status_t)context.GetReturnValue() < 0) return ""; } else { Parameter* nextParam = context.GetNextSibling(param); if (nextParam != NULL) { nextParam = context.GetNextSibling(nextParam); if (nextParam != NULL && nextParam->Name() == "statMask") statMask = context.ReadValue(nextParam); } } struct stat s; int32 bytesRead; status_t err = context.Reader().Read(data, &s, sizeof(s), bytesRead); if (err != B_OK) return context.FormatPointer(data); string r; if ((statMask & 0xffffffff) == 0xffffffff) { char mode[12]; r += ", st_dev = " + format_unsigned(s.st_dev); r += ", st_ino = " + format_unsigned(s.st_ino); snprintf(mode, sizeof(mode), "%03" B_PRIo32, (uint32)(s.st_mode & ~(S_IFMT | S_ISUID | S_ISGID | S_ISVTX))); r += ", st_mode = " + format_mode(context, s.st_mode & S_IFMT) + "|"; r += mode; r += ", st_nlink = " + format_unsigned(s.st_nlink); } if ((statMask & B_STAT_UID) != 0) r += ", st_uid = " + format_unsigned(s.st_uid); if ((statMask & B_STAT_GID) != 0) r += ", st_gid = " + format_unsigned(s.st_gid); if ((statMask & B_STAT_SIZE) != 0) r += ", st_size = " + format_unsigned64(s.st_size); if ((statMask & 0xffffffff) == 0xffffffff) r += ", st_blksize = " + format_unsigned(s.st_blksize); if ((statMask & B_STAT_ACCESS_TIME) != 0) r += ", st_atim = " + format_timespec(context, s.st_atim); if ((statMask & B_STAT_MODIFICATION_TIME) != 0) r += ", st_mtim = " + format_timespec(context, s.st_mtim); if ((statMask & B_STAT_CHANGE_TIME) != 0) r += ", st_ctim = " + format_timespec(context, s.st_ctim); if ((statMask & B_STAT_CREATION_TIME) != 0) r += ", st_crtim = " + format_timespec(context, s.st_crtim); if ((statMask & 0xffffffff) == 0xffffffff) { r += ", st_type = " + format_unsigned(s.st_type); r += ", st_blocks = " + format_unsigned(s.st_blocks); } return "{" + r.substr(2) + "}"; } template<> string TypeHandlerImpl::GetParameterValue(Context &context, Parameter *param, const void *address) { void *data = *(void **)address; if (data != NULL && context.GetContents(Context::SIMPLE_STRUCTS)) return read_stat(context, param, data); return context.FormatPointer(data); } template<> string TypeHandlerImpl::GetReturnValue(Context &context, uint64 value) { return context.FormatPointer((void *)value); } DEFINE_TYPE(stat_ptr, struct stat*); void patch_file() { Syscall *readStat = get_syscall("_kern_read_stat"); readStat->GetParameter("stat")->SetOut(true); Syscall *readIndexStat = get_syscall("_kern_read_index_stat"); readIndexStat->GetParameter("stat")->SetOut(true); }