From 2fc806542a2c68707ac57b5a8f8de291ab3c52e4 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 1 Jan 2007 19:50:16 +0000 Subject: [PATCH] added usage of the Handle System to begin experimenting --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40257 --- core/interfaces/IHandleSys.h | 6 +- core/interfaces/ILibrarySys.h | 6 ++ core/msvc8/sourcemod_mm.vcproj | 4 ++ core/sm_globals.h | 1 + core/smn_filesystem.cpp | 114 +++++++++++++++++++++++++++++++++ core/smn_handles.cpp | 1 + core/sourcemod.cpp | 6 +- core/systems/HandleSys.cpp | 4 +- core/systems/HandleSys.h | 2 +- core/systems/LibrarySys.cpp | 5 ++ core/systems/LibrarySys.h | 1 + plugins/include/files.inc | 42 ++++++++++++ plugins/include/sourcemod.inc | 4 ++ 13 files changed, 190 insertions(+), 6 deletions(-) create mode 100644 core/smn_filesystem.cpp create mode 100644 plugins/include/files.inc diff --git a/core/interfaces/IHandleSys.h b/core/interfaces/IHandleSys.h index ab77a428..67bdf206 100644 --- a/core/interfaces/IHandleSys.h +++ b/core/interfaces/IHandleSys.h @@ -17,6 +17,8 @@ namespace SourceMod typedef unsigned int HandleType_t; typedef unsigned int Handle_t; + class SourcePawn::IPluginContext; + /** * About type checking: * Types can be inherited - a Parent type ("Supertype") can have child types. @@ -179,13 +181,13 @@ namespace SourceMod * * @param type Type to use on the handle. * @param object Object to bind to the handle. - * @param ctx Plugin context that will own this handle. NULL for none. + * @param pOwner Plugin context that will own this handle. NULL for none. * @param ident Identity token if any security rights are needed. * @return A new Handle_t. */ virtual Handle_t CreateScriptHandle(HandleType_t type, void *object, - sp_context_t *ctx, + SourcePawn::IPluginContext *pOwner, IdentityToken_t *ident) =0; /** diff --git a/core/interfaces/ILibrarySys.h b/core/interfaces/ILibrarySys.h index c59bc50e..94a00bb6 100644 --- a/core/interfaces/ILibrarySys.h +++ b/core/interfaces/ILibrarySys.h @@ -64,6 +64,12 @@ namespace SourceMod * @brief Returns whether the current entry is a file. */ virtual bool IsEntryFile() =0; + + /** + * @brief Returns true if the current entry is valid + * (Used similarly to MoreFiles). + */ + virtual bool IsEntryValid() =0; }; /** diff --git a/core/msvc8/sourcemod_mm.vcproj b/core/msvc8/sourcemod_mm.vcproj index 3ea688f5..a88b4467 100644 --- a/core/msvc8/sourcemod_mm.vcproj +++ b/core/msvc8/sourcemod_mm.vcproj @@ -211,6 +211,10 @@ RelativePath="..\sm_trie.cpp" > + + diff --git a/core/sm_globals.h b/core/sm_globals.h index 87c45daf..226ef801 100644 --- a/core/sm_globals.h +++ b/core/sm_globals.h @@ -49,6 +49,7 @@ private: extern ISourcePawnEngine *g_pSourcePawn; extern IVirtualMachine *g_pVM; +extern IdentityToken_t *g_pCoreIdent; #include "sm_autonatives.h" diff --git a/core/smn_filesystem.cpp b/core/smn_filesystem.cpp new file mode 100644 index 00000000..d43c2c15 --- /dev/null +++ b/core/smn_filesystem.cpp @@ -0,0 +1,114 @@ +#include "sm_globals.h" +#include "HandleSys.h" +#include "LibrarySys.h" + +HandleType_t g_FileType; +HandleType_t g_DirType; + +class FileNatives : + public SMGlobalClass, + public IHandleTypeDispatch +{ +public: + virtual void OnSourceModAllInitialized() + { + HandleSecurity sec; + sec.owner = g_pCoreIdent; + sec.access[HandleAccess_Inherit] = false; + sec.access[HandleAccess_Create] = false; + + g_FileType = g_HandleSys.CreateTypeEx("File", this, 0, &sec, NULL); + g_DirType = g_HandleSys.CreateTypeEx("Directory", this, 0, &sec, NULL); + } + virtual void OnSourceModShutdown() + { + g_HandleSys.RemoveType(g_DirType, g_pCoreIdent); + g_HandleSys.RemoveType(g_FileType, g_pCoreIdent); + g_DirType = 0; + g_FileType = 0; + } + virtual void OnHandleDestroy(HandleType_t type, void *object) + { + if (type == g_FileType) + { + FILE *fp = (FILE *)object; + fclose(fp); + } else if (type == g_DirType) { + IDirectory *pDir = (IDirectory *)object; + g_LibSys.CloseDirectory(pDir); + } + } +}; + + +cell_t sm_OpenDirectory(IPluginContext *pContext, const cell_t *params) +{ + char *path; + int err; + if ((err=pContext->LocalToString(params[1], &path)) != SP_ERROR_NONE) + { + pContext->ThrowNativeErrorEx(err, NULL); + return 0; + } + + IDirectory *pDir = g_LibSys.OpenDirectory(path); + if (!pDir) + { + return 0; + } + + return g_HandleSys.CreateScriptHandle(g_DirType, pDir, pContext, g_pCoreIdent); +} + +cell_t sm_ReadDirEntry(IPluginContext *pContext, const cell_t *params) +{ + Handle_t hndl = static_cast(params[1]); + + IDirectory *pDir; + HandleError herr; + int err; + if ((herr=g_HandleSys.ReadHandle(hndl, g_DirType, g_pCoreIdent, (void **)&pDir)) + != HandleError_None) + { + return pContext->ThrowNativeError("Invalid file handle %x (error %d)", hndl, herr); + } + + if (!pDir->MoreFiles()) + { + return false; + } + + cell_t *filetype; + if ((err=pContext->LocalToPhysAddr(params[4], &filetype)) != SP_ERROR_NONE) + { + pContext->ThrowNativeErrorEx(err, NULL); + return 0; + } + + if (pDir->IsEntryDirectory()) + { + *filetype = 1; + } else if (pDir->IsEntryFile()) { + *filetype = 2; + } else { + *filetype = 0; + } + + const char *path = pDir->GetEntryName(); + if ((err=pContext->StringToLocalUTF8(params[2], params[3],path, NULL)) + != SP_ERROR_NONE) + { + pContext->ThrowNativeErrorEx(err, NULL); + return 0; + } + + return true; +} + + +REGISTER_NATIVES(filesystem) +{ + {"OpenDirectory", sm_OpenDirectory}, + {"ReadDirEntry", sm_ReadDirEntry}, + {NULL, NULL}, +}; diff --git a/core/smn_handles.cpp b/core/smn_handles.cpp index ca60e8c5..ad9324a8 100644 --- a/core/smn_handles.cpp +++ b/core/smn_handles.cpp @@ -69,4 +69,5 @@ REGISTER_NATIVES(handles) {"IsValidHandle", sm_IsValidHandle}, {"CloseHandle", sm_CloseHandle}, {"CloneHandle", sm_CloneHandle}, + {NULL, NULL}, }; diff --git a/core/sourcemod.cpp b/core/sourcemod.cpp index a976b417..6a1d679d 100644 --- a/core/sourcemod.cpp +++ b/core/sourcemod.cpp @@ -5,7 +5,7 @@ #include "vm/sp_vm_engine.h" #include #include "PluginSys.h" -#include "ForwardSys.h" +#include "ShareSys.h" SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool); @@ -16,6 +16,7 @@ ILibrary *g_pJIT = NULL; SourceHook::String g_BaseDir; ISourcePawnEngine *g_pSourcePawn = &g_SourcePawn; IVirtualMachine *g_pVM; +IdentityToken_t *g_pCoreIdent = NULL; typedef int (*GIVEENGINEPOINTER)(ISourcePawnEngine *); typedef unsigned int (*GETEXPORTCOUNT)(); @@ -139,6 +140,9 @@ void SourceModBase::StartSourceMod(bool late) pBase = pBase->m_pGlobalClassNext; } + /* Make the global core identity */ + g_pCoreIdent = g_ShareSys.CreateCoreIdentity(); + /* Notify! */ pBase = SMGlobalClass::head; while (pBase) diff --git a/core/systems/HandleSys.cpp b/core/systems/HandleSys.cpp index b4ffa916..f2e1b2a8 100644 --- a/core/systems/HandleSys.cpp +++ b/core/systems/HandleSys.cpp @@ -302,10 +302,10 @@ Handle_t HandleSystem::CreateHandle(HandleType_t type, void *object, IdentityTok Handle_t HandleSystem::CreateScriptHandle(HandleType_t type, void *object, - sp_context_t *ctx, + IPluginContext *pContext, IdentityToken_t *ident) { - IPlugin *pPlugin = g_PluginSys.FindPluginByContext(ctx); + IPlugin *pPlugin = g_PluginSys.FindPluginByContext(pContext->GetContext()); return CreateHandle(type, object, pPlugin->GetIdentity(), ident); } diff --git a/core/systems/HandleSys.h b/core/systems/HandleSys.h index ec88d6ca..36629e7c 100644 --- a/core/systems/HandleSys.h +++ b/core/systems/HandleSys.h @@ -90,7 +90,7 @@ public: //IHandleSystem void *object, IdentityToken_t *source, IdentityToken_t *ident); - Handle_t CreateScriptHandle(HandleType_t type, void *object, sp_context_t *ctx, IdentityToken_t *ident); + Handle_t CreateScriptHandle(HandleType_t type, void *object, IPluginContext *pContext, IdentityToken_t *ident); HandleError FreeHandle(Handle_t handle, IdentityToken_t *ident); HandleError CloneHandle(Handle_t handle, Handle_t *newhandle, IdentityToken_t *source, IdentityToken_t *ident); HandleError ReadHandle(Handle_t handle, HandleType_t type, IdentityToken_t *ident, void **object); diff --git a/core/systems/LibrarySys.cpp b/core/systems/LibrarySys.cpp index 669e950b..6fc467b1 100644 --- a/core/systems/LibrarySys.cpp +++ b/core/systems/LibrarySys.cpp @@ -93,6 +93,11 @@ void CDirectory::NextEntry() #endif } +bool CDirectory::IsEntryValid() +{ + return IsValid(); +} + bool CDirectory::IsEntryDirectory() { #if defined PLATFORM_WINDOWS diff --git a/core/systems/LibrarySys.h b/core/systems/LibrarySys.h index 83d6fcb9..9c89c0c6 100644 --- a/core/systems/LibrarySys.h +++ b/core/systems/LibrarySys.h @@ -23,6 +23,7 @@ public: virtual const char *GetEntryName(); virtual bool IsEntryDirectory(); virtual bool IsEntryFile(); + virtual bool IsEntryValid(); public: bool IsValid(); private: diff --git a/plugins/include/files.inc b/plugins/include/files.inc new file mode 100644 index 00000000..bd4ec8d3 --- /dev/null +++ b/plugins/include/files.inc @@ -0,0 +1,42 @@ +/** + * :TODO: license info + */ + +#if defined _files_included + #endinput +#endif +#define _files_included + +/* @note All paths in SourceMod natives are relative to the mod folder unless otherwise noted. */ + +enum FileType +{ + FileType_Unknown = 0, /* Unknown file type (device/socket) */ + FileType_Directory = 1, /* File is a directory */ + FileType_File = 2, /* File is a file */ +}; + + +/** + * @brief Opens a directory/folder for contents enumeration. + * @note Directories are closed with CloseHandle(). + * @note Directories Handles can be cloned. + * + * @param path Path to open. + * @return A Handle to the directory, INVALID_HANDLE on open error. + */ +native Handle:OpenDirectory(const String:path[]); + +/** + * @brief Reads the current directory entry as a local filename, then moves to the next file. + * @note Contents of buffers are undefined when returning false. + * @note Both the '.' and '..' automatic directory entries will be retrieved for Windows and Linux. + * + * @param dir Handle to a directory. + * @param buffer String buffer to hold directory name. + * @param maxlength Maximum size of string buffer. + * @param type Optional variable to store the file type. + * @return True on success, false if there are no more files to read. + * @error Invalid or corrupt Handle. + */ +native bool:ReadDirEntry(Handle:dir, String:buffer[], maxlength, &FileType:type=0); diff --git a/plugins/include/sourcemod.inc b/plugins/include/sourcemod.inc index de440a2f..00d61855 100644 --- a/plugins/include/sourcemod.inc +++ b/plugins/include/sourcemod.inc @@ -16,6 +16,10 @@ struct Plugin const String:url[], /* Plugin URL */ }; +#include +#include +#include + /** * Declare this as a struct in your plugin to expose its information. * Example: